-
-
Save syoichi/2943717 to your computer and use it in GitHub Desktop.
エラーの発生、インジケーターの表示がずれるのを修正した。また、arguments.calleeとsetInterval、getBoundingClientRectを使わないようにし、アニメーションはCSS Transitionsで行うようにした。さらに、原稿用紙への切り替えはインジケーターのクリックでできるように変更した。そして、文字数のカウントをサロゲートペアに対応させた。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @id textarea character count | |
// @name textarea character count | |
// @namespace http://tokyoenvious.net/ | |
// @author motemen | |
// @version 0.0.1 | |
// @update 2012-06-17T15:44:53.818Z(GMT+09:00) | |
// @description テキストエリアの文字数をカウントする。 | |
// @include http://* | |
// @include https://* | |
// @run-at document-end | |
// @priority 0 | |
// @compatibility Firefox 13.0.1(Scriptish 0.1.7), Chrome 19.0.1084.56, Safari 5.1.7(NinjaKit 0.9.1), Opera 12.00 on Windows 7 Home Premium SP1 64bit | |
// @charset UTF-8 | |
// ==/UserScript== | |
/*jslint browser: true, maxlen: 80*/ | |
// Edition 2012-05-09 | |
(function executeTextareaCharacterCount(win, doc) { | |
'use strict'; | |
var enableGenko, getStringLength, getGenko, setIndicator, changeGenko; | |
doc.head.appendChild(doc.createElement('style')).textContent = [ | |
'textarea + .indicator {', | |
' background-color: #333 !important;', | |
' color: white !important;', | |
' font-family: Verdana !important;', | |
' font-size: 9pt !important;', | |
' padding: 0.1em 0.5em !important;', | |
' border-radius: 0.2em !important;', | |
' position: absolute !important;', | |
' opacity: 0 !important;', | |
' -webkit-user-select: none !important;', | |
' -moz-user-select: none !important;', | |
' -ms-user-select: none !important;', | |
' -o-user-select: none !important;', | |
' user-select: none !important;', | |
' cursor: pointer !important;', | |
' -webkit-transition: opacity linear 0.3s !important;', | |
' -moz-transition: opacity linear 0.3s !important;', | |
' -ms-transition: opacity linear 0.3s !important;', | |
' -o-transition: opacity linear 0.3s !important;', | |
' transition: opacity linear 0.3s !important;', | |
'}', | |
'textarea:hover + .indicator,', | |
'textarea + .indicator:hover {', | |
' opacity: 1 !important;', | |
'}' | |
].join('\n'); | |
enableGenko = false; | |
getStringLength = function getStringLength(str) { | |
return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '1').length; | |
}; | |
getGenko = function getGenko(text) { | |
var lineCount, lines, linesLen, line, lineTextLen, idx, pageCount, | |
genko; | |
lineCount = 0; | |
lines = text.replace(/\n+$/, '').split('\n'); | |
linesLen = lines.length; | |
while (linesLen) { | |
line = lines[linesLen -= 1]; | |
lineTextLen = getStringLength(line); | |
idx = 0; | |
while (idx < lineTextLen) { | |
lineCount += 1; | |
idx += 20; | |
if (/[っ。、」』]/.test(line[idx])) { | |
idx += 1; | |
if (idx >= lineTextLen) { | |
break; | |
} | |
} | |
} | |
} | |
pageCount = Math.floor(lineCount / 20); | |
lineCount = lineCount % 20; | |
genko = '原稿用紙 '; | |
if (pageCount) { | |
genko += pageCount + ' 枚'; | |
if (lineCount) { | |
genko += ' + '; | |
} | |
} | |
if (!pageCount || lineCount) { | |
genko += lineCount + ' 行'; | |
} | |
return genko; | |
}; | |
setIndicator = function setIndicator(evt) { | |
var target, targetNextElement, indicator, indicatorStyle, oTop, oLeft; | |
target = evt.target; | |
if (target.tagName !== 'TEXTAREA') { | |
return; | |
} | |
targetNextElement = target.nextElementSibling; | |
if (targetNextElement && targetNextElement.className === 'indicator') { | |
indicator = targetNextElement; | |
} else { | |
indicator = doc.createElement('span'); | |
target.parentNode.insertBefore( | |
indicator, | |
target.nextSibling | |
).className = 'indicator'; | |
} | |
indicator.textContent = enableGenko | |
? getGenko(target.value) | |
: getStringLength(target.value); | |
indicatorStyle = indicator.style; | |
oTop = target.offsetTop; | |
oLeft = target.offsetLeft; | |
indicatorStyle.top = | |
(oTop + target.clientHeight - 25) + 'px'; | |
indicatorStyle.right = | |
(win.innerWidth - oLeft - target.clientWidth - 10) + 'px'; | |
}; | |
changeGenko = function changeGenko(evt) { | |
var target, prevNode; | |
target = evt.target; | |
prevNode = target.previousSibling; | |
if ( | |
!( | |
prevNode && | |
prevNode.tagName === 'TEXTAREA' && | |
target.tagName === 'SPAN' && | |
target.className === 'indicator' && | |
target.getAttribute('style') | |
) | |
) { | |
return; | |
} | |
enableGenko = !enableGenko; | |
setIndicator({target: prevNode}); | |
}; | |
doc.addEventListener('input', setIndicator); | |
doc.addEventListener('click', changeGenko); | |
}(window, document)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment