定番の判定コードを改造
カラー値の定番の判定コードは、正規表現検索を使って「#+16進3桁」又は「#+16進6桁」に当てはまれば「OK」という判定を行います。 これは「HEX値カラーの判定」の定番ですが、「HEX値」は「Hexadecimal(16進)」から来ています。
判定コードは以下です。
で、「Draw The Line ⭐」のカラー値入力のコードを調整していると、透過度(アルファ値)の適用に「#+16進4桁」「#+16進8桁」を使っているので、上の判定コードでは「NG」になります。
これは、「Draw The Line ⭐」用に改造すれば簡単に解決できました。
「#+16進4桁」「#+16進8桁」も条件に入れてやれば良いので、下の様な判定コードになります。
このコードは、旧Edgeが「#+16進8桁」をサポートしなかったのが原因か、案外と書いているページがみつかりません。 これで「アルファ値付き」のコードも「OK」と判定できます。
「透過度」の設定コードを更新
これまでのコードを根本的に書換えました。
❶ 最初に「アルファ値付き」を含む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); } }}} }