定番の判定コードを改造

カラー値の定番の判定コードは、正規表現検索を使って「#+16進3桁」又は「#+16進6桁」に当てはまれば「OK」という判定を行います。 これは「HEX値カラーの判定」の定番ですが、「HEX値」は「Hexadecimal(16進)」から来ています。

 

判定コードは以下です。

 

function test_color(color){
    return color.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)!==null; }

 

で、「Draw The Line ⭐」のカラー値入力のコードを調整していると、透過度(アルファ値)の適用に「#+16進4桁」「#+16進8桁」を使っているので、上の判定コードでは「NG」になります。

 

これは、「Draw The Line ⭐」用に改造すれば簡単に解決できました。

「#+16進4桁」「#+16進8桁」も条件に入れてやれば良いので、下の様な判定コードになります。

 

function test_color(color){
    return color.match(
        /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{4})$/)!==null; }

 

このコードは、旧Edgeが「#+16進8桁」をサポートしなかったのが原因か、案外と書いているページがみつかりません。 これで「アルファ値付き」のコードも「OK」と判定できます。

 

 

 

「透過度」の設定コードを更新 

これまでのコードを根本的に書換えました。

 

function trance(){
    let l_color_code;
    let l_color=document.querySelector('#l_color');
    let l_trance=document.querySelector('#l_trance');

    if(l_trance.value){
        if(test_color(l_color.value)){ // ❶
            if(l_color.value.length==4){ // ➋
                let ch=l_color.value.split("");
                l_color_code=
                    '#'+ch[1]+ch[1]+ch[2]+ch[2]+ch[3]+ch[3]+'90'; }
            if(l_color.value.length==5){ // ➋
                let ch=l_color.value.split("");
                l_color_code=
                    '#'+ch[1]+ch[1]+ch[2]+ch[2]+ch[3]+ch[3]+ch[4]+ch[4]; }
            if(l_color.value.length==7){ // ➋
                l_color_code=l_color.value+'90'; }
            if(l_color.value.length==9){ // ➋
                l_color_code=l_color.value; } 

            if(l_trance.value!=1){
                let ch=l_color_code.split('');
                if(ch[7].match(/[A-Fa-f]/)){ // ❸
                    ch[7]='9'; } 
                if(Number(ch[7])<10*l_trance.value-1){ // ❹
                    l_trance.value=Number(ch[7])/10; }
                else{
                    ch[7]=10*l_trance.value.toString(); } // ❺
                ch[8]='0';
                l_color.value=ch.join(''); }

            else if(l_trance.value==1){ // ❻
                l_color.value=l_color_code.slice(0, -2); }
        }}}

 

 

❶ 最初に「アルファ値付き」を含む16進カラー値かどうか判定します。 これは、上記の新しい判定コード「test_color()」を使います。

 

❷ 適合するカラー値は、全て「#+16進8桁」に変更します。 この際、「3桁」「6桁」の「アルファ値無し」は、アルファ値に「90」を追加します。 これは、この設定コードが、「90」~「10」までのアルファ値の範囲で動作するからです。

 

❸ 次の段階は、「透過度設定値」により、透過度を書き換える操作です。

上の ❷の操作でも、手入力による「#+16進4桁」「#+16進8桁」のコードには、アルファ値が「9a」を越えるものが通過して来る可能性があります。 これを「90」に切り下げます。

 

❹ カラー値入力枠にアルファ値付きの「#+16進8桁」が入力された場合、従来は「透過度」の初期値を「1」に戻し、「透過度」のスピナーで「0.9」へと調整を始めると、アルファ値は「90」に戻されてから調整する状態でした。 これは、手入力のアルファ値を全く無視する仕様なので、改善しました。

 

調整対象の「アルファー値の上位桁」が「透過度設定値×10」より2以上少ない場合を、手入力した「アルファ値」の初期値と判断し、その場合は「透過度設定藍」の方を書換え、「アルファー値の下位桁」は「0」に書換えます。

 

このコードは「2以上少ない」という所がミソで、「透過度」調整時の上位桁は、1ずつ「透過度設定値×10」と差があり、それを越えた場合を手入力と判断しています。 これで、上位桁が手入力で7以下の場合は、その桁の透過度から調整が出来ます。

 

❺ 手入力値をサポートするものが ❹ですが、❺は本来の「透過度」入力枠の値に沿って「90」~「10」のアルファ値を書換える部分です。

 

❻「透過度」の調整を開始すると、カラー値を全て「#+16進8桁」に変更します。 しかし、「透過度」の値を「1」に戻した時は「アルファ値」を「ff」に戻す必要があります。 インラインに書込むのコード文字数を減らす意味で、「ff」にする代わりにカラー値末尾の2桁を削除しています。

 

 

 

テストツール 

以上の「判定コード」「透過度設定コード」の実際の動作を確認する、テストツールです。 カラー値の入力と、有効なカラー値の判定と、カラー値のローカルストレージへの記録のテストで、実用性はありません。 

 

●「透過度」の設定機能は、「#+16進3桁」「#+16進4桁」「#+16進6桁」「#+16進8桁」の入力値の場合に動作します。

 

●「#+16進8桁」で、末尾2桁の「アルファー値」入力が間違っていても、他が適合する場合は、自動的に修正して「透過度」の設定が可能です。

 

● 入力枠に、カラー名やRGB表記の値が入力されている時は、この機能は動作しません。 また「透過度」変更中は、入力判定は動作しません。

 

●「透過度」を調整したカラー値は、そのままローカルストレージに記録され、次回にも再現します。 再現されたカラー値の透過度は、その値から再調整できます。

 

 

 

テストツールのコード 

このコードは Chrome / 新Edge / Firefox の「Tampermonkey」上で動作します。 

 

このコードを実行して試すには、各ブラウザの「Tampermonkey」の「新規スクリプト」の編集画面で、最初から登録されているテンプレートを削除して完全に空白にした上で、以下のコードをコピー&ペーストして「保存」してください。

 

〔コピー方法〕 軽量シンプルなツール「PreBox Button   」を使うと

  コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」

  の操作で、掲載コードのコピーが可能になります。

 
 

〔 Color Code Test ◪ 〕ver. 0.2

 

// ==UserScript==
// @name         Color Code Test ◪
// @namespace  http://tampermonkey.net/
// @version      0.2
// @description  カラーコードの有効・無効を判定するツール
// @author       Ameba Blog User
// @match        https://blog.ameba.jp/ucs/entry/srventry*
// @exclude      https://blog.ameba.jp/ucs/entry/srventrylist.do*
// @grant         none
// ==/UserScript==


let retry=0;
let interval=setInterval(wait_target, 100);
function wait_target(){
    retry++;
    if(retry>10){ // リトライ制限 10回 1sec
        clearInterval(interval); }
    let target=document.getElementById('cke_1_contents'); // 監視 target
    if(target){
        clearInterval(interval);
        main(); }}


function main(){
    let editor_iframe;
    let iframe_doc;
    let selection;
    let range;
    let task=0; // アンダーライン・マーカー線・消し線・終了
    let add_padd; //「MS Pゴシック」のために padding-bottom追加フラグ

    let read_json;
    let setting; // 入力枠の設定とユーザー設定値登録

    let ua=0; // Chromeの場合のフラグ
    let agent=window.navigator.userAgent.toLowerCase();
    if(agent.indexOf('firefox') > -1){ ua=1; } // Firefoxの場合のフラグ



    read_json=localStorage.getItem('Draw_Line'); // ローカルストレージ 保存名
    setting=JSON.parse(read_json);
    if(setting==null){
        setting=[['DrawTheLine','0','0','0'],['1','1.23','#333','0'],['1','1.23','#333','0'],
                 ['0.6','0.7','#ccc','0'],['1','0.66','#333','0'],['1','0.54','#333','0']]; }
    let write_json=JSON.stringify(setting);
    localStorage.setItem('Draw_Line', write_json); // ローカルストレージ 保存


    let target=document.getElementById('cke_1_contents'); // 監視 target
    let monitor=new MutationObserver(catch_key);
    monitor.observe(target, {childList: true}); // ショートカット待受け開始

    catch_key();

    function catch_key(){
        if(document.querySelector('.cke_wysiwyg_frame') !=null){ //「通常表示」から実行開始
            editor_iframe=document.querySelector('.cke_wysiwyg_frame');
            iframe_doc=editor_iframe.contentWindow.document;
            selection=iframe_doc.getSelection();

            iframe_doc.addEventListener('keydown', check_key);
            document.addEventListener('keydown', check_key);

            function check_key(event){
                let gate=-1;
                if(event.ctrlKey==true){
                    if(event.keyCode==114){
                        event.preventDefault(); gate=1; }
                    if(gate==1){
                        event.stopImmediatePropagation();
                        do_task(); }}}

            function do_task(){
                if(task==0){
                    task=1;
                    panel_disp();
                    set_panel();
                    draw_line(); }
                else if(task==1 || task==2){
                    task=0;
                    panel_remove(); }}
        }} // catch_key()



    function draw_line(){
        show_color();
        pick_color();

        let l_type=document.querySelector('#l_type');
        let single=document.querySelector('#single');
        let double=document.querySelector('#double');
        let l_trance=document.querySelector('#l_trance');
        let l_color=document.querySelector('#l_color');
        let ms=document.querySelector('#ms');

        single.checked=true;
        l_color.value=setting[1][2];
        test_colorE(l_color.value); // test_colorEを実行 ⏹

        double.onclick=function(){
            double.checked=true;
            if(task==1){
                task=2; }}

        single.onclick=function(){
            single.checked=true;
            if(task==2){
                task=1; }}


        l_trance.addEventListener('input', function(event){
            event.preventDefault();

            if(!test_color(l_color.value) && l_color.value.length==9){ // 不適合な #付き9桁コードの場合
                if(test_color(l_color.value.slice(0, -2))){ // アルファ―値のみ不適合なら修正
                    l_color.value=l_color.value.slice(0, -2); }}
            if(!test_color(l_color.value) && l_color.value.length==8){ // 不適合な #付き8桁コードの場合
                if(test_color(l_color.value.slice(0, -1))){ // アルファ―値のみ不適合なら修正
                    l_color.value=l_color.value.slice(0, -1); }}

            if((test_color(l_color.value))){
                trance();
                l_color.style.boxShadow='inset -20px 0 ' + l_color.value; }
            else{
                l_trance.value=1; } // 変換不能なコード, カラー名などは「1」を変更できない

            setting[1][2]=l_color.value;
            let write_json=JSON.stringify(setting);
            localStorage.setItem('Draw_Line', write_json); }); // ローカルストレージ 保存

    } // draw_line()



    function set_panel(){
        let l_type=document.querySelector('#l_type');
        let l_trance=document.querySelector('#l_trance');
        let l_color=document.querySelector('#l_color');

        l_type.value="カラー値チェック";

        l_trance.value='1'; // 初期値
        l_trance.setAttribute('min', '0.1');
        l_trance.setAttribute('max', '1');
        l_trance.setAttribute('step', '0.1');

        l_color.value=setting[1][2]; }



    function panel_disp(){
        let panel=document.createElement('div');
        panel.setAttribute('id', 'l_panel');

        panel.innerHTML=
            '<input id="l_type" type="submit">'+
            '<div id="type_wrap">'+
            '<div id="type_1">'+
            '<input id="single" type="radio" name="s_d"><span class="l_label">アラート非表示</span>'+
            '<input id="double" type="radio" name="s_d"><span class="l_label">アラート表示</span>'+
            '</div>'+
            '<div id="type_2">'+
            '<span class="l_label">透過度</span>'+
            '<div class="wtr"><input id="l_trance" type="number"></div>'+
            '</div>'+
            '</div>'+
            '<span class="l_label">線色</span>'+
            '<input id="l_color" type="text" value="#333" autocomplete="off">'+
            '<div id="test">◪</div>';
        //        '<div id="test"></div>';


        let css=
            '#l_panel { position: fixed; top: 15px; left: calc(50% - 490px); padding: 6px 15px; '+
            'font-size: 14px; border: 1px solid #ccc; border-radius: 4px; background: #eff5f6; z-index: 10; }'+
            '#type_wrap { display: inline-block; text-align: right; width: 370px; }'+
            '#type_1 { display: inline-block; margin-right: 20px; } #type_2 { display: inline-block; }'+
            '#l_panel input { position: relative; margin-right: 10px; padding-top: 2px; }'+
            '#l_panel input:hover { z-index: 1; }'+
            '#l_panel input[type="radio"] { margin: 0 2px 0 8px; vertical-align: -2px; box-shadow: none; }'+
            '.l_label { margin: 0 4px 0 0; }'+
            '#l_type { width: 130px; margin-right: 4px !important; }'+
            '.wtr { position: relative; display: inline-block; }'+
            '#l_trance { width: 40px; text-align: center; padding: 2px 0 0 4px; }'+
            '#l_color { width: 90px; padding: 2px 24px 0 6px; border: thin solid #aaa; height: 23px; }'+
            '#test { display: inline-block; padding: 4px 7px 3px; border: thin solid #aaa; background: #fff; }'+
            //            '#test { display: inline-block; }'+
            '#cke_42 { top: 60px !important; left: calc( 50% - 45px) !important; }';

        if(ua==1){
            css=css +
                '#l_trance, #l_color { height: 24px; border: thin solid #aaa; }'+
                '.wtr::after { content: " "; position: absolute; right: 11px; top: 5px; '+
                'background: #fff; width: 1.2em; }'; }

        let style=document.createElement('style');
        style.innerHTML=css;
        panel.appendChild(style);

        let l_panel=document.querySelector('#l_panel');
        if(!l_panel){
            document.querySelector('.l-body').appendChild(panel); }} // panel_disp()



    function panel_remove(){
        let l_panel=document.querySelector('#l_panel');
        l_panel.remove(); }



    function test_color(color){
        return color.match(
            /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{4})$/)!==null; }



    function test_colorE(color){
        let test=document.querySelector('#test');
        test.style.color='#000001';
        if(color!=''){
            test.style.color=color; } // 引数の入力がない場合
        let colorR=window.getComputedStyle(test).color;
        if(colorR){
            if(colorR!='rgb(0, 0, 1)'){
                if(task==2){
                    alert(colorR + '  🟢 適正コード'); }
                return true; }
            else{
                if(color=='rgb(0, 0, 1)' || color=='#000001' || color=='#000001ff'){
                    if(task==2){
                        alert(colorR + '  🟢 適正コード'); }
                    return true; }
                else{
                    if(task==2){
                        alert(colorR +'  🔴 不適なカラーコード'); }
                    return false; }}}
        else{
            if(task==2){
                alert(colorR + '  🔴 メソッド戻り値無し'); } // 実際はこの状態にならない
            return false; }}



    function show_color(){
        let l_color=document.querySelector('#l_color');
        l_color.style.boxShadow='inset -20px 0 ' + l_color.value; }



    function pick_color(){
        let set_color;
        let color_input_selector;
        let color_label;
        let icon_button;

        editor_iframe=document.querySelector('.cke_wysiwyg_frame');
        iframe_doc=editor_iframe.contentWindow.document;
        selection=iframe_doc.getSelection();

        if(ua==0){
            color_label=document.querySelector('#cke_16_label');
            icon_button=document.querySelector('#cke_17'); }
        else if(ua==1){
            color_label=document.querySelector('#cke_15_label');
            icon_button=document.querySelector('#cke_16'); }

        let target_p=color_label; // 監視 アイコンのカラーラベル
        let monitor_p=new MutationObserver( get_copy );

        let l_color=document.querySelector('#l_color');


        l_color.onclick=function(event){
            if(event.ctrlKey==true){
                event.preventDefault();
                icon_button.click();
                selection.removeAllRanges(); // 反転選択がある場合に背景指定を防止する
                monitor_p.observe(target_p, {attributes: true}); }} // アイコンカラー取得開始

        l_color.addEventListener('input', function(event){
            event.preventDefault();
            let l_trance=document.querySelector('#l_trance');
            if(l_trance){
                l_trance.value=1; } // 透過度をリセットする

            if(test_colorE(l_color.value)){ // test_colorEを実行 ⏹
                l_color.style.boxShadow='inset -20px 0 ' + l_color.value; }
            else{
                if(l_color.value==''){
                    l_color.style.boxShadow='inset 0 0 0 1px black'; }
                else{
                    l_color.style.boxShadow='inset 0 0 0 1px black'; // 担保コード
                    l_color.style.boxShadow=
                        'inset 0 0 0 1px black, inset -20px 0 ' + l_color.value; }}

            setting[1][2]=l_color.value;
            let write_json=JSON.stringify(setting);
            localStorage.setItem('Draw_Line', write_json); }); // ローカルストレージ 保存


        document.addEventListener('mousedown', function(){
            monitor_p.disconnect(); }); // アイコンカラー取得終了

        if(document.querySelector('.cke_wysiwyg_frame') !=null){
            let editor_iframe=document.querySelector('.cke_wysiwyg_frame');
            let iframe_doc=editor_iframe.contentWindow.document;
            iframe_doc.addEventListener('mousedown', function(){
                monitor_p.disconnect(); }); } // アイコンカラー取得終了

        function get_copy(){
            let l_trance=document.querySelector('#l_trance');
            if(l_trance){
                l_trance.value=1; } // 透過度をリセットする
            set_color=color_label.getAttribute('data-color');
            l_color.value='#'+ set_color;
            l_color.style.boxShadow=
                'inset -20px 0 ' + l_color.value;
            monitor_p.disconnect(); // アイコンカラー取得終了

            test_colorE(l_color.value ); // test_colorEを実行 ⏹
            setting[1][2]=l_color.value;
            let write_json=JSON.stringify(setting);
            localStorage.setItem('Draw_Line', write_json); } // ローカルストレージ 保存


        let target_body=document.querySelector('.l-body'); // 監視 target
        let monitor_generator=new MutationObserver(stealth);
        monitor_generator.observe(target_body, {childList: true, subtree: true});

        function stealth(){
            let color_generator=document.querySelector('.ck-l-colorGenerator');
            if(color_generator){
                color_generator.addEventListener('mousedown', function(event){
                    event.stopImmediatePropagation(); }); }}
    } // pick_color()



    function trance(){
        let l_color_code;
        let l_color=document.querySelector('#l_color');
        let l_trance=document.querySelector('#l_trance');

        if(l_trance.value){
            if(test_color(l_color.value)){ // #カラーコードは全て#+16進8桁に変更
                if(l_color.value.length==4){
                    let ch=l_color.value.split("");
                    l_color_code='#'+ch[1]+ch[1]+ch[2]+ch[2]+ch[3]+ch[3]+'90'; }
                if(l_color.value.length==5){
                    let ch=l_color.value.split("");
                    l_color_code='#'+ch[1]+ch[1]+ch[2]+ch[2]+ch[3]+ch[3]+ch[4]+ch[4]; }
                if(l_color.value.length==7){
                    l_color_code=l_color.value+'90'; }
                if(l_color.value.length==9){
                    l_color_code=l_color.value; }

                if(l_trance.value!=1){
                    let ch=l_color_code.split('');
                    if(ch[7].match(/[A-Fa-f]/)){ // アルファ値の初桁が「9」を超える場合は「9」に
                        ch[7]='9'; }
                    if(Number(ch[7])<10*l_trance.value-1){ // 初桁とl_tranceの差が「2」以上は手入力
                        l_trance.value=Number(ch[7])/10; } // この場合はl_trance値を入力値に合わせる
                    else{
                        ch[7]=10*l_trance.value.toString(); } // l_tranceの入力に合わせて増減操作
                    ch[8]='0';
                    l_color.value=ch.join(''); }

                else if(l_trance.value==1){
                    l_color.value=l_color_code.slice(0, -2); }
            }}}

}