「iframe」の再表示でスクリプトが無効になる

前ページのスクリプトは、「通常表示」の編集枠が最初に表示された時には、正しく動作しました。 しかし「HTML表示」を一度開き「通常表示」に戻ると、もはや全くスクリプトが実行されなくなります。

 

下は「通常表示」から「HTML表示」タブを押して移動した瞬間のHTMLです。 青枠の「#cke_1_contents」の中に、赤枠の「textarea」が表示されようとしています。

 

 

下は、逆に「通常表示」タブを押した直後で、「#cke_1_contents」の中に赤枠の「iframe」が動的に表示(生成)される瞬間です。

 

 

HTML上の「iframe」が消失すると、スクリプトが対象を失って無効となる様です。 これは無効になると言うより「終了してしまう」と言うべきかも知れません。

 

この問題を解決するのは、かなり苦労しました。 色々コードを試したのですが、最後に「MutationObserver」というコードでこれを解決出来た様です。

 

 

 

DOMの変更を検知して関数を実行させる「MutationObserver」

DOMは簡単には要素構成と考えて良いでしょう。「MutationObserver」は、特定の要素の構成を監視して、変更があった場合に指定した関数を実行させます。 これを使って「#cke_1_contents」を監視させ、その子要素が「textarea」⇄「iframe」と入れ替えられた際に、前ページで作ったショートカットキーを受けるスクリプトを実行させるという算段です。

 

この方法では「iframe」が表示される度にスクリプトが実行されるので、「iframe」の「document」を再取得し、キー操作に対応する動作が実現出来ました。

 

以下は、最初に上手く動作したコードです。

 

// ==UserScript==
// @name         ▶ Ameblo Writer Extension8
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  Ctrl + F8 でスクリプト起動 改善版
// @author       PersonWritep
// @match        https://blog.ameba.jp/ucs/entry/srventry*
// @grant        none
// ==/UserScript==

( window.onload = function() {
    'use strict';

function catch_key() {
var editor_iframe = document.getElementsByClassName('cke_wysiwyg_frame');
var iframe_doc = editor_iframe[0].contentWindow.document;

iframe_doc.onkeydown = keydown;
function keydown() {
    if (event.ctrlKey == true) {
        if (event.keyCode == 119) {
            alert( "Ctrl + F8 が押された"); }}}}

var target = document.getElementById('cke_1_contents');
var monitor = new MutationObserver(catch_key);
monitor.observe(target, {childList: true});

})();

 

青文字の部分は、前ページのコードのままです。 これを改めて「catch_key()」という関数として宣言しています。

 

その後の3行は「MutationObserver」の定型の書式です。

1行目: 監視対象「target」に「#cke_1_contents」を設定しています。

2行目:「MutationObserver」で関数「catch_key()」を実行させる事を設定。

3行目:「target」の「子要素の変更」に関しての監視を実行開始。

 

このコードで「HTML表示」をした後に、ショートカットキーにスクリプトが反応する様になりました。 しかしまだ不完全で、編集画面を開いて、一度「HTML表示」に行き、戻ってからしかスクリプトが働きません。 このコードは、一度は編集枠の変更をしないと、スクリプトを実行してくれないのです。

 

 

 

変更の監視の前に一度スクリプトを実行させる

この問題は、簡単にクリアー出来ました。 既に「catch_key()」という関数として、ショートカットキーを受け取るスクリプトを登録しています。 これを監視開始の前に一度実行してやると、最初に開いた「通常表示」の編集枠でそれが実行されました。 簡単な話ですが、「catch_key();」の一行を入れるのは実用上で肝心な事です。

 

以下が今回のスクリプトの完成形です。

 

// ==UserScript==
// @name         ▶ Ameblo Writer Extension8
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  Ctrl + F8 でスクリプト起動 改善版
// @author       PersonWritep
// @match        https://blog.ameba.jp/ucs/entry/srventry*
// @grant        none
// ==/UserScript==

( window.onload = function() {
    'use strict';

function catch_key() {
var editor_iframe = document.getElementsByClassName('cke_wysiwyg_frame');
var iframe_doc = editor_iframe[0].contentWindow.document;

iframe_doc.onkeydown = keydown;
function keydown() {
    if (event.ctrlKey == true) {
        if (event.keyCode == 119) {
            alert( "Ctrl + F8 が押された"); }}}}

catch_key();

var target = document.getElementById('cke_1_contents');
var monitor = new MutationObserver(catch_key);
monitor.observe(target, {childList: true});

})();

 

以上で、「通常表示」の編集枠でショートカットキーをスイッチとするスクリプトが、ほぼ完成したと言えるでしょう。

 

このスクリプトの「alert( "Ctrl + F8 が押された");」の部分に、実際に動作させたい関数を書き込んで、実行させる事が出来るはずです。

 

さて、「通常表示」の編集枠で、カーソルの位置を取得する様なスクリプトが、作れるものかどうか。 先は長そうです。