スマホアプリによるClose処理などSNAPデータが無い場合に対応
「Every Page Opener 💢」は、SNAPデータが全く無い場合は動作しません。 またSNAPデータ有りの記事と無しの記事が混在する場合は、データがない「下書き」記事に対しては、処理をしない様にしています。
この処理の仕様は、「公開の意図が無い記事」を不用意に公開してしまう事を防ぐため、譲れないものです。「Every Page Opener 💢」は、これまでに「公開したレベル」を決して越えて公開しない様にしているのです。
しかし、スマホアプリで既にCloseしてしまった場合には、「Opener 💢」は一切対応出来ない事になります。 全く「アメンバー記事」が無いから全て公開にしたい、あるいは「アメンバー記事」が公開されても手作業で変更できる数で、とにかく公開にしたいなどのニーズがあるかも知れません。
この場合は、初期の「Every Page Opener」が使えますが、シーケンス動作の採用前のコードです。 そこで「Every Page Opener 💢」に、SNAPデータなしで処理可能な特別なモードを追加しました。 これで、上記の様なニーズにも応えられるツールになりました。
操作部のデザイン
コントロール部のSNAPデータ枠に、新しいアイコンを追加しました。 アイコンが「🔽」の場合は、従来のSNAP対応の公開処理を行います。
このアイコンをクリックすると、SNAPデータなしで動作する「特別オープンモード」になります。 ぺージがリロードされてアイコンが「🟩」に変わります。 元のSNAPデータに対応したモードに戻す場合は、アイコンをもう一度クリックします。
「特別オープンモード」では、「ファイル読込みボタン」と「SNAP詳細表示」が無くなり、下の様な公開設定の表示が出ます。 この表示はモードの違いを明瞭にするためのものです。 なお、このモードに入れると、ツールが保有するSNAPデータの表示がなくなりますが、データがストレージから削除されるのではありません。
「特別オープンモード」でも、最初の処理スタート時だけダイアログで処理仕様を表示します。(連続処理で次ページに移動してからは表示されません)
表示は、SNAPデータなしで公開処理を行う事のことわりで、以下の内容です。
現在に「下書き」の記事は
元が「全員に公開」「アメンバー限定公開」の記事 ➡ 「全員に公開」
現在に「全員に公開」「アメンバー限定公開」の記事は 変換しない
元が「アメンバー限定公開」や「下書き」の記事も、現在「下書き」の状態なら全て「全員に公開」になるので、この点は注意が要ります。
公開処理の仕様が異なるだけで、進行は「Every Page Opener 💢」と同様です。
「Every Page Opener 💢」操作上の注意点
既に「💢」シリーズのツールを経験している場合は、以下は繰り返しになります。
● このツールは編集サブウインドウを開くため、ブラウザのポップアップブロック設定が有効になっていると動作を妨げられます。 以下のページ末尾のブロック解除の設定方法に従い「https://blog.ameba.jp」を解除URLに追加してください。
また Firefoxで使用する際は、ブラウザの「オプション」→「タブグループ」の設定で「新しいウィンドウではなく新しいタブに開く」にチェックを入れてください。
●「Every Page Opener 💢」をONにする際は、「Tampermonkey」に登録した他のツールを全てOFFにします。 特に「Closer 💢」「Snap 💢」は相反する動作をするので、同時にONとすると不測の事態になるので注意してください。
更に、ブログ編集画面やブラウザの他画面などを閉じ、処理対象とする「記事の編集・削除」のページのみを開いて操作するのが理想です。
●このツールは、現行の「最新版エディタ」「タグ編集エディタ」で作成された記事が対象です。(旧い時代のエディタによる記事は未確認です)
●「💢」シリーズのツールは、記事の「公開設定」のみを変更し、記事内容を損なう事はないと思いますが、利用上のトラブルは自己責任とお考えください。
「Every Page Opener 💢」ver. 2.4 のコード
以下のコードを「Tampermonkey」にコピー&ペーストして登録する事で、このツールを利用出来ます。
「Every Page Opener 💢」は、一括の公開処理を行う場合にのみONとするスクリプトで、常駐させて使用するスクリプトではありません。 処理作業が終了したら、かならずOFFにしてください。
このツールは Chrome版/Firefox版/Edge版の「Tampermonkey」で動作を確認しています。 Chrome / Firefox の場合は「Stylus」で「Ameblo Management」のページアレンジを適用した方が、画面のちらつきが少なくなります。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
アメブロ編集画面の「アメーバ限定公開」のボタン廃止に伴い、更新をしました
〔 Every Page Opener 💢 〕 ver. 2.4 N
// ==UserScript== // @name Every Page Opener 💢 // @namespace http://tampermonkey.net/ // @version 2.4 N // @description 「記事の編集・削除」ページで全ての「下書き」を「公開記事」に変更する // @author Ameba Blog User // @match https://blog.ameba.jp/ucs/entry/srventrylist* // @match https://blog.ameba.jp/ucs/entry/srventryupdate* // @run-at document-start // @grant none // ==/UserScript== window.addEventListener('DOMContentLoaded', function(){ // CSSデザインを適用するためのスクリプト let css=[ '.include-ex-linkBtn, .save-browserPush, .save-hashtag-module, .adcrossBanner{ display: none }', 'html { overflow-y: overlay !important }', '#globalHeader, #ucsHeader, #ucsMainLeft h1, .l-ucs-sidemenu-area, #ucsMainRight,', '#entryList dl, #entryList .rightCol input, .actionControl,', '#footerAd, #globalFooter, .checkboxAllControl { display: none }', '#ucsContent{ width: 720px !important; box-shadow: 0 0 0 100vh #c5d8e1 }', '#ucsMain{ background: #fff } #ucsMainLeft { width: 690px !important; float: none }', '#entryList li{ height: 24px; padding: 8px 5px 5px !important }', '#entryList li:hover{ background-color: #e2eef0 }', '#entryList .leftCol, #entryList .titleCol h2{ width: 400px !important; line-height: 24px }', '.leftCol a:hover{ text-decoration: none } .leftCol a:visited{ color: #3970b5 }', '#entryList .rightCol{ display: flex; width: 260px !important }', '#entryList .txtCol .date{ font-size: 13px; color: #000 }', '#entryList .txtCol{ white-space: nowrap; font-size: 13px; margin-top: 4px; line-height: 16px }', '#entryList .deleteCol { margin: -3px 0 0 20px }', '.deleteCol a:nth-child(2), .deleteCol a:nth-child(3), .rightCol input { display: none }', '#entryList .btnDefault { height: 25px }', '#entryList .btnDefault:hover { box-shadow: inset 0 0 0px 2px #1976d2 }', '#entryList ul input[value="1"] + input + li .txtCol span:first-child{ display: inline-block;', 'margin-top: -2px; padding: 2px 13px 0; color: #fff; background: #2196f3 !important }', '#entryList ul input[value="2"] + input + li .txtCol span:first-child{ display: inline-block;', 'width: 3em; text-indent: -1em; overflow: hidden; margin-top: -2px; padding: 2px 13px 0;', 'vertical-align: -4px; color: #fff; background: #009688 !important }', '#entryMonth { font-size: 14px; overflow: visible; margin-top: 3px }', '#entryMonth li, #entryMonth #nowMonthLi { padding: 2px 10px 0 }', '#nowMonth { padding: 1px 6px 0; border: none; border-radius: 1px;', 'box-shadow: 0 0 0 2px #0066cc; color: #000 }', '#entryListEdit form { display: flex; flex-direction: column } #entrySort { order: -2 }', '.pagingArea { order: -1; padding: 4px; margin-bottom: -33px; background: #ddedf3 }', '.pagingArea a { border: 1px solid #888 } .pagingArea .active{ border: 2px solid #0066cc }', '.pagingArea a, .pagingArea .active, .pagingArea .disabled { font-size: 14px; line-height: 23px }', '#sorting { margin: 38px 0 4px; padding: 4px 10px; height: 110px; background: #ddedf3 }', '#sorting select, #sorting ul { display: none }', 'input { font-family: meiryo; font-size: 14px }'].join(' '); let style=document.createElement('style'); style.insertAdjacentHTML('afterbegin', css); let head=document.getElementsByTagName('head')[0]; head.appendChild(style); }) window.addEventListener('load', function(){ // このスクリプトは孫ウインドウだけで働く let body_id=document.body.getAttribute('id'); if(body_id=="entryCreate"){ // この項だけ孫ウインドウで働く window.document.body.style.background='#c5d8e1'; window.document.body.style.boxShadow='0 0 0 100vh #c5d8e1'; window.document.querySelector('#subContentsArea').style.display='none'; select_e(close_w); function select_e(close_w){ let error_report=document.querySelector('h1.p-error__head'); if(error_report==null){ // エラー無い場合 grayを送信 親ウインドウを閉じる if(window.opener){ report('gray'); window.opener.close(); }} else{ // エラー報告の場合 redを送信 親ウインドウを残す if(window.opener){ report('red'); window.opener.location.reload(); }} close_w(); } function close_w(){ window.open('about:blank','_self').close(); } // 孫ウインドウは常に閉じる function report(color){ window.opener.document.querySelector('html').style.color=color; }} }) window.addEventListener('load', function(){ // このスクリプトは親ウインドウで働くメインスクリプト let next; let mode; // 動作モード let except_am; //「アメンバー記事」以外を開く特別モード let mode_arr=[]; let blogDB={}; // 記事IDリスト let entry_id_DB=[]; // ID検索用の配列 let filter; let regex_id; let entry_target; let entry_id; let publish_f; let pub_all; let pub_dra; let pub_ame; let list_bar; let new_win; let link_target; let ua=0; let agent=window.navigator.userAgent.toLowerCase(); if(agent.indexOf('firefox') > -1){ ua=1; } // Firefoxの場合のフラグ if(agent.indexOf('edge') > -1){ ua=2; } // Edgeの場合のフラグ let read_json=localStorage.getItem('blogDB_back'); // ローカルストレージ 保存名 blogDB=JSON.parse(read_json); // blogDB(SNAP記録)はこのスクリプトでは読取り専用 if(blogDB==null){ blogDB=[['00000000000', 's']]; } else{ reg_set(); } function reg_set(){ let k; entry_id_DB=[]; // リセット pub_all=0; pub_dra=0; pub_ame=0; for(k=0; k<blogDB.length; k++){ entry_id_DB[k]=blogDB[k][0]; // ID検索用の配列を作成 if(blogDB[k][1]=='0'){ pub_all +=1; continue; } if(blogDB[k][1]=='1'){ pub_dra +=1; continue; } if(blogDB[k][1]=='2'){ pub_ame +=1; continue; }} filter=entry_id_DB.join('|'); regex_id=RegExp(filter); } // フィルター作成 read_json=localStorage.getItem('blogDB_mode'); // ローカルストレージ 保存名 mode_arr=JSON.parse(read_json); if(!mode_arr || mode_arr.length!=3){ mode_arr=[0, 0, 0]; } mode=mode_arr[0]; // modeが「3」ならページングでぺージを開いた連続作業とみなす except_am=mode_arr[2]; //「アメンバー記事」以外を開く特別モード mode_arr[0]=0; // 不正規の終了を考慮してリセット let write_json=JSON.stringify(mode_arr); localStorage.setItem('blogDB_mode', write_json); // ローカルストレージ保存 paging_watch(); function paging_watch(){ let k; let ym_pager=document.querySelectorAll('#entrySort a'); for(k=0; k<ym_pager.length; k++){ ym_pager[k].addEventListener('mousedown', function(){ mode_send(); }); } let pn_pager=document.querySelectorAll('.pagingArea a'); for(k=0; k<pn_pager.length; k++){ pn_pager[k].addEventListener('mousedown', function(){ mode_send(); }); } function mode_send(){ // 「0」以外から移動時の場合は「3」をローカルストレージ保存 if(mode>0){ mode_arr[0]=3; let write_json=JSON.stringify(mode_arr); localStorage.setItem('blogDB_mode', write_json); }}} // ローカルストレージ 保存 entry_target=document.querySelectorAll('.deleteCol'); entry_id=document.querySelectorAll('input[name="entry_id"]'); publish_f=document.querySelectorAll('input[name="publish_flg"]'); list_bar=document.querySelectorAll('#entryList li'); let body_id=document.body.getAttribute('id'); if(body_id=='entryListEdit'){ // 親ウインドウでのみ働く let sty; let insert_div0; insert_div0=document.createElement('div'); insert_div0.setAttribute('id', 'div0'); insert_div0.style='color: #333; font-size: 14px; margin: 10px -10px 0 15px'; let box=document.querySelector('#sorting'); box.appendChild(insert_div0); let insert_div1; insert_div1=document.createElement('div'); insert_div1.setAttribute('id', 'div1'); insert_div1.style='color: #000; font-size: 14px; margin: 8px 15px; border: 1px solid #888'; box.appendChild(insert_div1); let button1=document.createElement('input'); button1.setAttribute('id', 'start_button'); button1.setAttribute('type', 'submit'); button1.setAttribute('style', 'padding: 2px 8px 0; margin: 7px 35px 7px 0; width: 160px'); insert_div0.appendChild(button1); button1.setAttribute('value', '公開処理の開始 ▶'); button1.onclick=function(e){ e.preventDefault(); if(mode==0){ // 最初の起動直後 if(except_am==0){ // 特別オープンモードOFF start_select(); } else if(except_am==1){ // 特別オープンモードON start_select_ex(); }} else if(mode==1){ // 続行状態 mode=2; // クリックされたら停止モード button1.setAttribute('value', '公開処理を続行 ▶'); } else if(mode==2){ // 停止状態 mode=1; // クリックされたら続行モード button1.setAttribute('value', '公開処理を停止 ❚❚'); open_win(next); } else if(mode==3){ // 前ページから連続作業で開いた状態 if(entry_target.length==0 || entry_target==null){ // 編集対象がリストに無い場合 alert('このページに編集対象の記事がありません'); } // クリックで modeは「3」のまま else if(entry_target.length >0){ // 編集対象がリストに有る場合 mode=1; // クリックされたら続行モード button1.setAttribute('value', '公開処理を停止 ❚❚'); open_win(0); }}} // 連続作業でスタート function start_select(){ if(blogDB.length==1){ alert(['⛔ SNAPデータを blogDB(n).json ファイルから読込んでください。', '\n Every Page Snap 💢 で作成した適切なファイルが無い場合は', '\n Every Page Opener を使用して公開処理をしてください。', '\n\n⛔ 〔注意〕', '\n Every Page Opener は 元 「アメンバー記事」 から 「下書き」 に', '\n 変更処理をした記事に関しても 「全員に公開」 に変更します。', '\n この点には注意して下さい。 このツールを終了します'].join('') ); } else if(entry_target.length==0 || entry_target==null){ // 編集対象がリストに無い場合 alert('このページに編集対象の記事がありません'); } else if(entry_target.length >0){ // 編集対象がリストに有る場合 let conf_str=['🟠 このページの 「下書き」 を SNAPデータに従って公開処理します\n', '\n SNAP時の 「全員公開」の記事 ➡ 「全員に公開」', '\n SNAP時の 「アメンバー記事」 ➡ 「アメンバー限定公開」', '\n 現在の 「アメンバー限定公開」 は 変更しません', '\n SNAPデータに記録がない記事は 変更しません \n', '\n OKを押すと公開処理を開始します'].join(''); let ok=confirm(conf_str); if(ok){ mode=1; button1.setAttribute('value', '公開処理を停止 ❚❚'); open_win(0); }}} function start_select_ex(){ if(entry_target.length==0 || entry_target==null){ // 編集対象がリストに無い場合 alert('このページに編集対象の記事がありません'); } else if(entry_target.length >0){ // 編集対象がリストに有る場合 let conf_str=['🟠 このページの 「下書き」 を SNAPデータなしで公開処理します\n', '\n 元の 「全員公開」「アメンバー記事」 ➡ 「全員に公開」', '\n 現在の 「アメンバー記事」「全員公開」 は変更しません\n', '\n OKを押すと公開処理を開始します'].join(''); let ok=confirm(conf_str); if(ok){ mode=1; button1.setAttribute('value', '公開処理を停止 ❚❚'); open_win(0); }}} if(except_am==0){ // 特別オープンモードOFFの場合のみ表示 let button2=document.createElement('input'); button2.setAttribute('type', 'file'); button2.setAttribute('style', 'vertical-align: 1px; width: 300px'); if(ua==2){ button2.setAttribute('style', 'vertical-align: 0; width: 300px; direction: rtl'); } insert_div0.appendChild(button2); button2.addEventListener("change", function(){ if(!(button2.value)) return; // ファイルが選択されない場合 let file_list=button2.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)=='[["00000000000"'){ // blogDB.jsonの確認 let data_in=JSON.parse(file_reader.result); blogDB=data_in; // 読込み上書き処理 let write_json=JSON.stringify(blogDB); localStorage.setItem('blogDB_back', write_json); // ローカルストレージ 保存 reg_set(); time_disp(new Date(file.lastModified)); snap_disp(); } else{ alert(" ⛔ 不適合なファイルです blogDB(n).json ファイルを選択してください");}};}); let span1=document.createElement('span'); span1.setAttribute('id', 'span1'); let sty2=['display: inline-block; font-size: 14px; color: #000;', 'width: 140px; padding: 3px 0 2px 12px'].join(' '); span1.setAttribute('style', sty2); insert_div0.appendChild(span1); span1.textContent=' '; function time_disp(time_obj){ let date_sty=time_obj.getFullYear() + "/" + (time_obj.getMonth() + 1) + "/" + time_obj.getDate() + " " + time_obj.getHours() + ":" + time_obj.getMinutes(); span1.textContent=date_sty; }} let span5=document.createElement('span'); span5.setAttribute('id', 'snap_result'); span5.style='display: inline-block; margin: 6px 12px 4px'; insert_div1.appendChild(span5); if(except_am==0){ // 特別オープンモードOFFの場合のみ表示 snap_disp(); } function snap_disp(){ reg_set(); let span5=document.querySelector('#snap_result'); span5.textContent=' 記録件数:' + (blogDB.length -1) + ' 全員に公開:' + pub_all + ' アメンバー限定公開:' + pub_ame + ' 下書き:' + pub_dra; } let span6=document.createElement('span'); span6.setAttribute('id', 'am_button'); span6.style='display: inline-block; margin: 6px 15px 0; float: right; cursor: pointer'; insert_div1.appendChild(span6); if(except_am==0){ // 特別オープンモードOFF span6.textContent='🔽'; span5.style='display: inline-block; margin: 6px 12px 4px'; } else if(except_am==1){ // 特別オープンモードON span6.textContent='🟩'; span5.style='display: inline-block; margin: 6px 12px 4px 60px'; span5.textContent='◼◼◼◼◼ 現在のアメンバー記事以外を 全員に公開します ◼◼◼◼◼'; } span6.onclick=function(e){ e.preventDefault(); if(except_am==0){ // 特別オープンモードOFF except_am=1; } else if(except_am==1){ // 特別オープンモードON except_am=0; } mode_arr[2]= except_am; write_json=JSON.stringify(mode_arr); localStorage.setItem('blogDB_mode', write_json); // ローカルストレージ保存 location.reload(); }} // 特別オープンモードの変更時はリロードする function open_win(k){ new_win=Array(entry_target.length); link_target=Array(entry_target.length); link_target[k]=entry_target[k].getElementsByTagName('a')[0].getAttribute('href'); let top_p=100 + 30*k; if(mode==1 && except_am==0){ // 特別オープンモードOFF let index=entry_id_DB.indexOf(entry_id[k].value); if(index==-1){ // IDが SNAPデータに記録がない記事の場合 list_bar[k].style.backgroundColor='#fff5aa'; next_do(k); } //⏩ 子ウインドウを開かず リスト背景 黄色 else{ // IDがSNAPデータに記録されていた場合 if(publish_f[k].value==1){ // リスト上の公開設定が「下書き」のみ処理 if(blogDB[index][1]==1){ // SNAPデータが「下書き」の場合 list_bar[k].style.backgroundColor='#eceff1'; next_do(k); } //⏩ 子ウインドウを開かず リスト背景 淡グレー else{ publish_f[k].value=blogDB[index][1]; // リスト上の公開設定をSNAPデータに従って更新する new_win[k]=window.open(link_target[k], k, 'top=' + top_p + ', left=200, width=750, height=180'); // 編集画面を開く let publish_f_tetCol=list_bar[k].querySelector('.txtCol span:first-child'); publish_f_tetCol.style='padding: 2px 13px 0; opacity: 0'; list_bar[k].style.boxShadow='inset 0 0 0 2px #03a9f4'; // リスト 青枠表示 new_win[k].addEventListener('load', function(){ setTimeout( function(){ edit_target(publish_f[k].value, k); }, 50); });}} //🟦 子ウインドウで書込み開始 else{ // リスト上の公開設定が「下書き」ではない場合 list_bar[k].style.backgroundColor='#eceff1'; next_do(k); }}} //⏩ 子ウインドウを開かず リスト背景 淡グレー if(mode==1 && except_am==1){ // 特別オープンモードON if(publish_f[k].value==1){ // リスト上の公開設定が「下書き」のみ処理 publish_f[k].value=0; //「全員に公開」に設定更新する new_win[k]=window.open(link_target[k], k, 'top=' + top_p + ', left=200, width=750, height=180'); // 編集画面を開く let publish_f_tetCol=list_bar[k].querySelector('.txtCol span:first-child'); publish_f_tetCol.style='padding: 2px 13px 0; opacity: 0'; list_bar[k].style.boxShadow='inset 0 0 0 2px #03a9f4'; // リスト 青枠表示 new_win[k].addEventListener('load', function(){ setTimeout( function(){ edit_target(publish_f[k].value, k); }, 50); });} //🟦 子ウインドウで書込み開始 else{ // リスト上の公開設定が「下書き」ではない場合 list_bar[k].style.backgroundColor='#eceff1'; next_do(k); }}} function edit_target(val,k){ new_win[k].addEventListener('beforeunload', flag_line, false); publish_do(val,k); function flag_line(){ if(new_win[k]){ var send_color=new_win[k].document.querySelector('html').style.color; } if(send_color=='gray'){ // 文書保存が正常終了した場合 list_bar[k].style.boxShadow='none'; // 青枠を消す list_bar[k].style.backgroundColor='#a4d5fd'; // 子ウインドウが閉じられ リスト背景 淡ブルー let publish_f_tetCol=list_bar[k].querySelector('.txtCol span:first-child'); if(publish_f[k].value==0){ //「全員に公開」へ処理した場合 let sty=['display: inline-block; margin-top: -2px; padding: 2px 0 0;', 'color: #000; background: #fff !important; opacity: 1'].join(' '); publish_f_tetCol.textContent='全員に公開'; publish_f_tetCol.style=sty; } else if(publish_f[k].value==2){ //「アメンバー限定公開」へ処理した場合 let sty=['padding: 2px 13px 0;', 'color: #fff; background: #009688 !important; opacity: 1'].join(' '); publish_f_tetCol.textContent='アメンバー'; publish_f_tetCol.style=sty; } next_do(k); } // ⏩ else if(send_color=='red'){ // 文書保存が異常終了の場合は子ウインドウは閉じない list_bar[k].style.boxShadow='inset 0 0 0 2px red'; // リスト 背景 白 赤枠表示 list_bar[k].style.backgroundColor='#fff'; next_do(k); }} // ⏩ function publish_do(val, k){ let publish_b0=new_win[k].document.querySelector('button.js-submitButton[publishflg="0"]'); let publish_b1=new_win[k].document.querySelector('button.js-submitButton[publishflg="1"]'); if(val==0){ publish_b0.click(); } if(val==1){ publish_b1.click(); } if(val==2){ let amb_ck=new_win[k].document.querySelector('#amemberFlg'); amb_ck.checked = true; setTimeout(()=>{ publish_b0.click(); }, 20); }}} function next_do(k){ next=k+1; if(next<entry_target.length){ open_win(next); } else{ mode=4; // 終了状態 let button1=document.querySelector('#start_button'); button1.setAttribute('value', '処理が終りました'); }} })
「Every Page Opener 💢」最新版について
旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。
●「Every Page Opener 💢」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。