リンクカードの編集が必要な時
今年になって実現した「リンクカード」は、やはり重宝します。「リブログカード」はページ上に1個しか置けない仕様でしたから、それだけでも扱い易さが違います。
しかし「リンクカード」を貼り付けると、思う様なカバー画像(サムネイル画像)が選択されなかったり、カバー画像が表示されない場合もあります。 また、「タイトル」や「記事の出だし」などが、周囲の記事の流れにそぐわない事もあります。
私はHTML編集で、納得できるカードに仕立てる事が時々あります。 ただ、カードのコードは密集したHTMLコードで、編集は手間です。 カードの出来に少々不満があっても、手を加えないユーザーは多いかも知れません。
今回 手がけるのは、このリンクカードを「通常表示」の編集画面から、比較的簡単に編集可能にするツールです。 現在は未完成ですが、順次機能を拡充する予定です。
最初の1歩は「contenteditable」属性の変更
「リンクカード」に「通常編集」の画面でマウスポインターを乗せると、下図の様にポインターが「手」の形になり、カード内にキャレットを入れる事ができません。
〔注〕「手」の形は「リンクカード」上の「a要素」にポインターが反応したからですが、「編集枠」内の「a要素」はリンク先に遷移すると編集が台無しになるので無効化されています。
本来「編集枠」内の表示要素は、内部のテキスト等が編集出来ますが、それが出来ないのは「リンクカード」のHTMLコードの最初に以下の指定があるからです。
「article要素」に指定された「contenteditable="false"」の指定は、「編集不可」を指定するものです。 この属性を「true」に変更する事で、下図の様に、カード内にキャレットが入り、「タイトル」「記事の出だし」などがすべて「通常表示」の編集画面から編集が可能になります。
上図は、ショートカット「Ctrl + F6」でこのツールを起動した状態で、「編集枠」の上部に「 ▢ LinkCard Editor 」の帯が表示されています。 ツールの起動と同時に、ページ上の「リンクカード」は全て「contenteditable="true"」に変更されます。
また、「リンクカード」の編集が終わり、「Ctrl + F6」でこのツールを終了すると、「リンクカード」は全て「contenteditable="false"」に戻されます。
現在はプロトタイプで、このカードのテキスト編集の機能だけですが、この機能だけで、「タイトル」や「記事の出だし」が編集可能になったわけです。 今後、カバー画像のユーザーによる設定機能を制作する予定です。
「LinkCard Editor」ver. 0.1
このツールは Chrome・Edge 上で制作中のものです。「Tampermonkey」に以下のコードを登録する事で、ツールを試用することが出来ます。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
〔 LinkCard Editor 〕ver. 0.1
// ==UserScript== // @name LinkCard Editor ⭐ // @namespace http://tampermonkey.net/ // @version 0.1 // @description 「通常表示」上のリンクカードを編集 「Ctrl+F6」 // @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 mode=0; // Card編集状態 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 iframe_body; let wysiwyg; // 通常表示の iframe内 html let target=document.getElementById('cke_1_contents'); // 監視 target let monitor=new MutationObserver( catch_key ); monitor.observe(target, {childList: true}); // ショートカット待受け開始 catch_key(); function catch_key(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ // WYSIWYG表示が実行条件 when_back(); iframe_doc=editor_iframe.contentWindow.document; iframe_doc.addEventListener('keydown', check_key); // iframe内 document.addEventListener('keydown', check_key); // iframe外 function check_key(event){ if(event.ctrlKey && event.keyCode==117){ // ショートカット「Crtl+F6」 event.stopImmediatePropagation(); if(mode==0){ mode=1; sign(); card_edit(); } else if(mode==1){ mode=0; sign_clear(); card_close(); }}}} before_end(); } // catch_key() function when_back(){ if(mode==1){ sign(); card_edit(); }} function card_edit(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ // WYSIWYG表示が実行条件 iframe_doc=editor_iframe.contentWindow.document; if(iframe_doc){ let iframe_body=iframe_doc.querySelector('body'); if(iframe_body){ let target_card=iframe_body.querySelectorAll('.ogpCard_root'); for(let k=0; k<target_card.length; k++){ let ogpCard_wrap=target_card[k].querySelector('.ogpCard_wrap'); if(ogpCard_wrap){ ogpCard_wrap.setAttribute('contenteditable', 'true'); }} }}}} // card_edit() function card_close(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ // WYSIWYG表示が実行条件 iframe_doc=editor_iframe.contentWindow.document; if(iframe_doc){ let iframe_body=iframe_doc.querySelector('body'); if(iframe_body){ let target_card=iframe_body.querySelectorAll('.ogpCard_root'); for(let k=0; k<target_card.length; k++){ let ogpCard_wrap=target_card[k].querySelector('.ogpCard_wrap'); if(ogpCard_wrap){ ogpCard_wrap.setAttribute('contenteditable', 'false'); }} }}}} function sign(){ monitor.disconnect(); // 起動時セットアップを MutationObserverに反応させない let css= '#cke_1_contents { display: flex; flex-direction: column; } '+ '#disp_le { display: none; margin: 0 0 9px; padding: 4px 0 2px; '+ 'font-size: 16px; color: #fff; background: #607d8b; }'; let disp=document.createElement("div"); disp.setAttribute("id", "disp_le"); disp.innerHTML=" ▢ LinkCard Editor"; let style=document.createElement('style'); // disp_le のデザインを指定 style.setAttribute("id", "le_style"); style.innerHTML=css; if(!target.querySelector('#le_style')){ target.appendChild(style); } editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ if(!target.querySelector('#disp_le')){ target.insertBefore(disp, editor_iframe); }} target.querySelector('#disp_le').style.display='block'; editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; iframe_body=iframe_doc.querySelector('body'); let box_style= iframe_doc.createElement('style'); // box のデザインを指定 let css_box= '.open_box { outline: 2px solid green !important; height: auto !important; }'; box_style.setAttribute("id", "box_style"); box_style.innerHTML=css_box; let iframe_html=iframe_doc.getElementsByTagName('html')[0]; if(!iframe_html.querySelector('#box_style')){ iframe_html.appendChild(box_style); }} monitor.observe(target, {childList: true}); } function sign_clear(){ if(target.querySelector('#disp_le')){ target.querySelector('#disp_le').style.display='none'; }} // 起動表示を非表示 function before_end(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); let submitButton=document.querySelectorAll('.js-submitButton'); submitButton[0].addEventListener("click", all_close, false); submitButton[1].addEventListener("click", all_close, false); function all_close(){ if(mode==1){ if(!editor_iframe){ //「HTML表示」編集画面の場合 alert("⛔ LinkCard Editor が処理を終了していません\n\n"+ " 通常表示画面に戻り 編集を終了してください"); event.stopImmediatePropagation(); event.preventDefault(); } else if(editor_iframe){ //「通常表示」編集画面の場合 mode=0; card_close(); }}} } // before_end() } // main()
「LinkCard Editor ⭐」最新版について
旧いバージョンの「LinkCard Editor ⭐」は、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。 最新バージョンへのリンクは、以下のページのリンクリストから探せます。