「MediaWiki:Gadget-SummaryByteCounter.js」の版間の差分

提供: TRPG.NET Wiki
ナビゲーションに移動 検索に移動
(1版)
 
(1版: ガジェット取り込み)
 
(相違点なし)

2014年10月30日 (木) 08:00時点における最新版

/* 
 * 要約欄に書き込める残りバイト数を表示する。
 */
jQuery(function($) {
    /* 最大制限バイト数 */
    var BYTE_LIMIT = 255;

    /* 編集画面かどうかを要約欄の有無で判断する。 */
    var $summary = $('#wpSummary');
    if ($summary.length === 0) { return; }

	/* CSS を設置 */
	mw.util.addCSS( '.summary-byte-counter.warn { color: red; }' );
	
    /* カウンターの用意と設置 */
    var $label = $('#wpSummaryLabel');
    var $counter = $('<span>')
        .attr('class', 'summary-byte-counter')
        .css({
            'display': 'inline-block',
            'width': '2em',
            'font-weight': 'bold',
            'text-align': 'center'
        })
        .text(BYTE_LIMIT);
    $label.append($counter);

    // 最初の更新
    updateCounter();

    /* wikEd への対応 */
    if (window.wikEd && window.wikEd.ResizeSummary) {
        window.wikEd.ResizeSummary();
    }

    /* イベントに接続 */
    $summary.on({
        'keyup': updateCounter,
        'focus': updateCounter,
        'blur': updateCounter,
        'change': updateCounter
    });

    /* 
     * 文字列を UTF-8 にした場合のバイト数を取得する。
     */
    function numberOfUTF8Bytes(string) {
        var len = 0;
        if (!string) { return len; }
        var code, surrogate = false;
        for (var i = 0; ; ++i) {
            code = string.charCodeAt(i);
            if (isNaN(code)) { break; }
            if (code < 0) {
                throw new Error('Illegal number: ' + code);
            } else if (code <= 0x007F) {
                len += 1;
            } else if (code <= 0x07FF) {
                len += 2;
            } else if (code <= 0xD7FF) {
                len += 3;
            } else if (code <= 0xDBFF) {
                surrogate = true;
            } else if (code <= 0xDFFF) {
                len += 4;
                surrogate = false;
            } else if (code <= 0xFFFF) {
                len += 3;
            } else {
                throw new Error('Illegal number: ' + code);
            }
        }
        return len;
    }

    /* 更新用の関数 */
    function updateCounter() {
        var val = $summary.val();
        if (typeof val === 'string') {
            var remained = BYTE_LIMIT - numberOfUTF8Bytes(val);
            if (remained <= 30) { // 残り30バイト
                $counter.addClass('warn');
            } else {
                $counter.removeClass('warn');
            }
            $counter.text(remained);
        }
    }
});