「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」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。