「Fixed Format Palette ⭐」は定型範囲の入力ツールです
ページに配置する定型のデザインしたリンクカードや枠付きの案内などがある場合、新しい記事にそれらを再配置するには、過去記事を編集画面に開き、その定型の要素をコピーして、新しい記事にペーストする必要があります。 コピーする定型要素の種類によっては、HTML表示の画面でコピーし、新しい記事でHTML表示を開いてペーストしないと、上手くコピー出来ないものもあります。
見栄えの良いページや、行き届いた案内を設置したページを作るには、この様な定型の表示パーツを再利用すると効果的です。 しかし、いちいち過去のページから必要な表示パーツを探しコピーするのは手間です。 そこで、再利用する表示パーツをブラウザのローカルストレージに登録しておき、必要な時にいつでも取り出してペーストできるツール「Fixed Format Palette ⭐」を作りました。
しかし、実はこのツール、苦労した割にインターフェイスが悪く、これまではコピー登録もペーストも扱い難いものでした。 ネックはショートカットに「3キー」を使う仕様で、登録した内容が利用時にペーストしないと判らず、私自身が9個の登録Bankの内の2~3個しか使わないという状態でした。
そこで、問題のインターフェイスを最初から組み直し、スクロールホイールでBankの全てが一覧選択できる様にしました。 この更新で画期的に使い易くなりました。
新しい操作方法 / 登録した表示パーツのペースト
● ショートカット「Ctrl+F11」でペースト用のサブパネルが表示されます。
● マウスポインターをサブパネルに乗せてホイール操作をすると、Bank1~Bank9に登録されたパーツを順に参照できます。
下は、Bankを順に開き、ペーストする表示パーツを選んでいるところです。
● 必要な表示パーツを出して「Enter」キーで、編集画面のキャレット位置にそのパーツをペーストします。「Esc」でペーストを中止し、サブパネルが閉じます。
● ペーストは必ず「通常表示」の編集画面で行います。 また、編集画面内にキャレットが無いと、挿入する位置が定まらないので、ペースト動作をしません。
新しい操作方法 / 表示パーツの登録
● 登録する表示パーツ(特定の要素やページの範囲)を、通常表示の編集画面上のキャレット操作で反転選択します。
● 上はリンクカードの例ですが、カードの1行手前からカードを越えた次の1行までを選択しています。 登録時は、この様に選択範囲の前後に余裕を採ると確実です。
● ショートカット「Alt+F11」を押します。
サブパネルの上側に、選択した表示パーツが表示されます。 下側は登録するBankのこれまでの登録内容が表示されます。(ツールの最初の使用時は、下側が空です)
● ホイール操作で、登録するBankを選びます。
▶ 既に登録があるBankを選んだ場合
●「Enter」で、これまでの登録(下側の表示パーツ)は上書きされ、代わりに上側の新しい表示パーツが登録されます。
▶ 未登録の空いたBankを選んだ場合
●「Enter」で、この空Bankに表示パーツが登録されます。
Bankの登録内容の削除
● キャレットを編集画面内に置き、何も選択しない状態で「Alt+F11」を押します。
最初に表示されるBankは常に「Bank1」なので、削除したいBankをホイール操作で選択します。
● 削除する表示パーツがサブパネルに表示されたら「Enter」を押します。
選択したBankが空Bankになります。
新しい操作方法 / 表示パーツのHTML登録
「HTML登録」は Chrome/Edge でのみ可能な機能で、「HTML表示画面」で表示パーツを登録することができます。
この方法の利点は表示パーツの前後の余裕を省いて、きっちり表示パーツだけを登録できる事です。 この機能を扱う前提として、HTMLのコード上で、表示パーツの範囲を正確に判別して指定できる必要があります。
● 登録するパーツのHTMLコードを選択します。
●「Alt+F11」を押します。
サブパネルに選択した表示パーツが表示されます。
● 登録するBankをホイール操作で選択して「Enter」を押します。
選択したBankに表示パーツが登録されます。
登録データのファイル化
Bankに登録したデータは、ブラウザを終了しても消える事はありません。 しかしファイル化してバックアップするとより確実です。 また、9個のBankで足りない時は、ファイルにBank内容を書き出し、ファイル単位で管理すると無限に登録できます。
「登録」「ペースト」のサブパネルの隅に「File」ボタンがあります。
これを押すと、サブパネルが下の様なファイル専用のメニューになります。
●「登録データをファイルに保存」をクリックすると、PCのダウンロードフォルダーにファイル名が「FFP(n).json」といった形で、ファイルが保存されます。
この(n)の部分は自動連番で、ファイル化するごとに数が増えます。
●「登録データファイルを読込む」をクリックすると、PC内のファイルを読込めます。 前例のファイルなら、ダウンロードフォルダを開いて、目的の「FFP.json」ファイルを指定して開きます。
このツールが保存したファイルを指定すると、そのデータが各Bankに読込まれます。 この操作は同時に、それまでのBankの登録内容を上書きするので注意してください。
「Fixed Format Palette ⭐」ver. 5.0 を使用するには
このツールは Chrome・Edge / Firefox の各ブラウザ版「Tampermonkey」で動作します。「Tampermonkey」にページ末尾の掲載コードを登録する事で、このツールを利用することが出来ます。
この版から基本操作が変わりましたが、これまでの Bankのデータやバックアップファイルはそのまま使用できます。 ただし、「Tampermonkey」に登録した旧バージョンがある場合はそれを削除して、このバージョンを新たに登録してください。
❶「Tampermonkey」を導入します
使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。 以下のページに簡単な導入の説明があるので参照ください。
❷「Tampermonkey」にスクリプトを登録します
●「Tampermonkey」の「+」マークの「新規スクリプト」タブを開きます。
●「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
● 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。
〔 Fixed Format Palette ⭐ 〕 ver. 5.0
// ==UserScript== // @name Fixed Format Palette ⭐ // @namespace http://tampermonkey.net/ // @version 5.0 // @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=document.querySelector('.cke_wysiwyg_frame'); let iframe_doc; let iframe_html; if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; iframe_html=iframe_doc.querySelector('html'); } let format_data; let bank; let mode=-1; // 通常表示Write=0・Record=1 Html表示Record=2 Backup=3 let select_format; let ua=0; // Chromeの場合のフラグ let agent=window.navigator.userAgent.toLowerCase(); if(agent.indexOf('firefox') > -1){ ua=1; } // Firefoxの場合のフラグ let read_json=localStorage.getItem('Format_Data'); // ローカルストレージ 保存名 format_data=JSON.parse(read_json); if(format_data==null){ format_data= [['0','FixedFormatPalette'],['1',''],['2',''],['3',''],['4',''],['5',''],['6',''],['7',''],['8',''],['9','']]; } format_data[0][1]='FixedFormatPalette'; let write_json=JSON.stringify(format_data); localStorage.setItem('Format_Data', 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('.l-gHeaderLeft__link a')){ // 起動を表示 📛 document.querySelector('.l-gHeaderLeft__link a') .style.boxShadow='inset -14px 0 0 0 #79fbf6'; } editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ // iframe がある「通常表示」の場合 mode=-1; if(document.querySelector('.ffp_menu')){ document.querySelector('.ffp_menu').remove(); } iframe_doc=editor_iframe.contentWindow.document; iframe_doc.addEventListener("keydown", check_key); function check_key(event){ if(event.ctrlKey && event.keyCode==122){ // 「Ctrl + F11」Bankから書出し event.preventDefault(); mode=0; setTimeout(()=>{ write_format(); }, 20); } if(event.altKey && event.keyCode==122){ // 「Alt + F11」Bank登録 event.preventDefault(); mode=1; setTimeout(()=>{ record_format(); }, 20); } if(event.keyCode==122){ // ページ拡大の誤入力を抑止 event.preventDefault(); } } // check_key() } //「通常表示」の場合 else{ //「HTML表示」の場合 mode=-1; if(document.querySelector('.ffp_menu')){ document.querySelector('.ffp_menu').remove(); } document.addEventListener("keydown", check_key_h); function check_key_h(event){ if(event.ctrlKey && event.keyCode==122){ // HTML表示で書込み操作をした場合 event.preventDefault(); document.querySelector('.CodeMirror textarea').blur(); setTimeout(()=>{ alert( " ⛔ 定型ブロックの記入は通常編集枠で行ってください\n"+ " == Fixed Format Palette =="); }, 20); } if(event.altKey && event.keyCode==122){ //「Alt+F11」Bank登録(HTMLで登録) event.preventDefault(); if(ua==0){ mode=2; // HTMLでの登録処理 setTimeout(()=>{ record_format_h(); }, 20); } else if(ua==1){ // FirefoxはHTML編集でブロック登録が出来ない event.stopImmediatePropagation(); document.querySelector('.CodeMirror textarea').blur(); setTimeout(()=>{ alert( " ⛔ 定型ブロックの登録は通常編集枠で行ってください\n"+ " == Fixed Format Palette =="); }, 20); }} if(event.keyCode==122){ // ページ拡大の誤入力を抑止 event.preventDefault(); } } // check_key_h } //「HTML表示」の場合 } // catch_key function write_format(){ disp_menu(0); iframe_doc.addEventListener("keydown", menu_key1); function menu_key1(event){ if(event.keyCode==27 && mode==0){ //「Esc」 event.preventDefault(); mode=-1; menu0_end(); } if(event.keyCode==13 && mode==0){ //「Enter」 event.preventDefault(); write_in(); // ペースト処理 setTimeout(()=>{ menu0_end(); }, 20); }} function menu0_end(){ if(document.querySelector('.ffp_menu')){ document.querySelector('.ffp_menu').remove(); }} function write_in(){ let selection=iframe_doc.getSelection(); let range; if(selection && selection.rangeCount>0){ range=selection.getRangeAt(0); } let ac_node=selection.anchorNode; let insert_node_d=iframe_doc.createElement('div'); insert_node_d.innerHTML=format_data[bank][1]; if(ac_node && ac_node.parentNode){ // insert_node_d 生成の条件 親が div要素か BODYの場合 if(ac_node.parentNode.tagName=='DIV' || ac_node.parentNode.tagName=='BODY'){ ac_node.parentNode.insertBefore(insert_node_d, ac_node.nextSibling); d_before_after(); } // insert_node_d 生成の条件 ひとつ外の親が div要素か BODYの場合 else if(ac_node.parentNode.parentNode.tagName=='DIV' || ac_node.parentNode.parentNode.tagName=='BODY'){ ac_node.parentNode.parentNode.insertBefore( insert_node_d, ac_node.parentNode.nextSibling); d_before_after(); } mode=4; } function d_before_after(){ range.setEnd(insert_node_d, 0); range.collapse(); }} // レンジを閉じる } // write_format() function record_format(){ let selection=iframe_doc.getSelection(); let range; if(selection && selection.rangeCount>0){ range=selection.getRangeAt(0); } select_format=document.createElement('div'); select_format.appendChild(range.cloneContents()); select_format=select_format.innerHTML; disp_menu(1); iframe_doc.addEventListener("keydown", menu_key0); function menu_key0(event){ if(event.keyCode==27 && mode==1){ //「Esc」 event.preventDefault(); mode=-1; menu1_end(); } else if(event.keyCode==13 && mode==1){ //「Enter」 event.preventDefault(); format_data[bank][1]=select_format; let write_json=JSON.stringify(format_data); localStorage.setItem('Format_Data', write_json); mode=4; menu1_end(); }} // ローカルストレージ 保存 function menu1_end(){ selection.removeAllRanges(); // 反転を解除 editor_iframe.blur(); // 編集枠からカーソルを外し誤記入を防ぐ if(document.querySelector('.ffp_menu')){ document.querySelector('.ffp_menu').remove(); }} } // record_format() function record_format_h(){ let result=new Promise( function(){ document.execCommand("copy"); }) navigator.clipboard.readText().then( function(clipText){ select_format=clipText; }) .then( function(){ disp_menu(1); }) .then( function(){ document.querySelector('.CodeMirror textarea').blur(); }) document.addEventListener("keydown", menu_key_h); function menu_key_h(event){ if(event.keyCode==27 && mode==2){ //「Esc」 event.preventDefault(); mode=-1; menu1_end(); } if(event.keyCode==13 && mode==2){ //「Enter」 event.preventDefault(); mode=4; format_data[bank][1]=select_format; let write_json=JSON.stringify(format_data); localStorage.setItem('Format_Data', write_json); // ローカルストレージ 保存 menu1_end(); }} function menu1_end(){ if(document.querySelector('.ffp_menu')){ document.querySelector('.ffp_menu').remove(); }} } // record_format_h(} function disp_menu(type){ let css= '.ffp_menu { position: absolute; top: 15px; right: 10px; z-index: 15; '+ 'font-family: Meiryo; font-size: 16px; line-height: 1.6; width: 620px; '+ 'padding: 8px 8px 18px; border: 1px solid #009688; border-radius: 4px; '+ 'background: #fff; box-shadow: 20px 20px 60px 0 rgba(0, 0, 0, .2), '+ 'inset 0 0 0 8px #eee; transform-origin: top; } '+ '.ffp_menu img { max-width: 99%; height: auto; } '+ '.ffp_title { padding: 3px 15px 1px; margin: 10px 0; background: #2196f3; '+ 'color: #fff; font-size: 16px; } '+ '.ffp_bk { display: inline-block; padding: 0 6px; line-height: 24px; '+ 'height: 22px; border: 1px solid #fff; border-radius: 3px; cursor: pointer; } '+ '.ffp_bk:hover { color: #2196f3; background: #fff; } '+ '.ffp_input { display: none; }'; let style_menu=document.createElement('style'); style_menu.setAttribute('id', "style_ffp_menu"); style_menu.textContent=css; if(!document.querySelector('#style_ffp_menu')){ document.querySelector('.l-body').appendChild(style_menu); } let menu=document.createElement('div'); menu.setAttribute('class', "ffp_menu"); if(!document.querySelector('.ffp_menu')){ document.querySelector('.l-body').appendChild(menu); } if(type==1){ setTimeout(()=>{ let selection=iframe_doc.getSelection(); if(selection){ selection.removeAllRanges(); // 反転を解除しコピー元の削除を防ぐ }}, 20 ); } let out=0; bank=1; menu_change(1); if(ua==0){ menu.onmousewheel=function(event){ let wd=event.wheelDelta/120; out-=wd; if(out>=0){ bank=out%9+1; } else{ bank=(out+1)%9+9; } menu_change(bank); }} if(ua==1){ menu.addEventListener('DOMMouseScroll', function(event){ let wd=- event.detail/3; out-=wd; if(out>=0){ bank=out%9+1; } else{ bank=(out+1)%9+9; } menu_change(bank); }); } function menu_change(bank){ let menu=document.querySelector('.ffp_menu'); let menu_str; if(type==0){ menu_str= '<div class="ffp_title">'+ '◁ Bank '+ bank +' ▷ の内容を貼り付けます '+ ' 貼り付け:Enter 中止:Esc <span class="ffp_bk">File</span></div>'+ format_data[bank][1]; } if(type==1){ menu_str='<div id="check">'+ select_format + '</div>'; // テスト menu.innerHTML=menu_str; let check=document.querySelector('#check'); if(check){ if(getComputedStyle(check, null).getPropertyValue("height")=='0px'){ select_format=''; // 非表示要素は無入力に変換する:登録の削除 menu_str= '<div class="ffp_title" style="background: #000;">'+ '◁ Bank '+ bank +' ▷ の以下の内容を削除します'+ ' 削除:Enter 中止:Esc</div>'+ format_data[bank][1]; } else { // 登録データを更新する場合 menu_str= '<div class="ffp_title">'+ '◁ Bank '+ bank +' ▷ に以下の内容を登録します'+ ' 登録:Enter 中止:Esc '+ '<span class="ffp_bk">File</span></div>'+ '<div id="check">'+ select_format + '</div>'+ '<div class="ffp_title" style="background: #000;">'+ '◁ Bank '+ bank +' ▷ の以下の登録内容は削除されます</div>'+ format_data[bank][1]; }}} menu.innerHTML=menu_str; let ffp_bk=document.querySelector('.ffp_bk'); if(ffp_bk){ ffp_bk.onclick=function(){ ffp_backup(); }}} // menu_change() } // disp_menu(); function ffp_backup(){ let menu=document.querySelector('.ffp_menu'); let menu_str; menu_str= '<div class="ffp_title"> '+ '<span class="ffp_button1 ffp_bk">登録データをファイルに保存</span> '+ '<span class="ffp_button2 ffp_bk">登録データファイルを読込む</span> '+ '<span class="ffp_button3 ffp_bk">✖</span>'+ '<input class="ffp_input" type="file"></div>'; menu.innerHTML=menu_str; let button1=document.querySelector('.ffp_button1'); let button2=document.querySelector('.ffp_button2'); let ffp_input=document.querySelector('.ffp_input'); let button3=document.querySelector('.ffp_button3'); button1.onclick=function(){ let write_json=JSON.stringify(format_data); // 記録用配列 format_data を書出す let blob=new Blob([write_json], {type: 'application/json'}); let a_elem=document.createElement('a'); a_elem.href=URL.createObjectURL(blob); a_elem.download='FFP.json'; // 保存ファイル名 if(ua==1){ a_elem.target='_blank'; document.body.appendChild(a_elem); } a_elem.click(event); event.preventDefault(); if(ua==1){ document.body.removeChild(a_elem); } URL.revokeObjectURL(a_elem.href); } button2.onclick=function(){ ffp_input.click(); } ffp_input.addEventListener("change", function(){ if(!(ffp_input.value)) return; // ファイルが選択されない場合 let file_list=ffp_input.files; if(!file_list) return; // ファイルリストが選択されない場合 let file=file_list[0]; if(!file) return; // ファイルが無い場合 let file_reader=new FileReader(); file_reader.readAsText(file); file_reader.onload=function(){ if(file_reader.result.slice(0, 15)=='[["0","FixedFor'){ // FFP.jsonの確認 let data_in=JSON.parse(file_reader.result); format_data=data_in; // 記録用配列 format_data を上書き let write_json=JSON.stringify(format_data); localStorage.setItem('Format_Data', write_json); // ローカルストレージに保存 }};}); button3.onclick=function(){ if(document.querySelector('.ffp_menu')){ document.querySelector('.ffp_menu').remove(); }} } // ffp_backup() } // main()
「Fixed Format Palette」はブログ編集画面の表示パーツをコピー登録して、必要な時にペーストできるツールです。 9個のBankを選んで登録でき、ブログに表示できるものはほぼ全て登録が可能です。
▶ 登録・ペースト操作は「通常表示」の編集画面で
操作します( Chromeは「HTML登録」が可能 )
▶ 行数・サイズ・表示内容等に制限はありません
▶ 複雑なデザインを施したパーツの再利用に最適
ショートカット ➔ Bankへ登録: Alt + F11
ショートカット ➔ ペースト : Ctrl + F11
登録Bank・ペーストBank の選択はサブウインドウで指定します。
登録Bankの内容をファイルにバックアップ保存ができます。
「Fixed Format Palette」最新版について
旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。
●「Fixed Format Palette」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。