• 解決済 krgn

    (@kirig)


    ・WP ver6.9
    ・プラグイン導入なし、自力テーマ
    ・エディタ:グーテンベルグ

    カスタムhtml使用時などのプレビューについての質問です。

    <iframe class="components-sandbox"><html><body data-resizable-iframe-connected="" style="position: absolute; width: 100%;"><div>プレビューソース</div></html></iframe>

    この状態となる<div>を<section class=”abcd”><div class=”inner”></div></section>
    のようにしたいのですが、 根本的に可能なのでしょうか。以下でjsを読み込むまでは終わっています。

    function addBlockEditorStyle(){
    wp_enqueue_script('theme-gutenberg-js',get_theme_file_uri('/js/cs_edit.js'),['wp-blocks','wp-element','wp-edit-post','wp-components','wp-data'],false,true);
    }
    add_action('enqueue_block_editor_assets','addBlockEditorStyle');
9件の返信を表示中 - 1 - 9件目 (全9件中)
  • ytsuyuzaki

    (@ytsuyuzaki)

    ご質問の内容は、カスタムHTMLで iframe を表示し、その iframe 内の HTML 要素(今回の <div>)の構造やラッパー要素を変更したい、という意図と理解しました。

    一般的には、JavaScript で iframe の読み込み完了後に iframe 内の DOM へアクセスし、要素を操作する形で実装を検証していくことになります。
    iframe 内の要素へは contentWindow.document または contentDocument を通じてアクセスでき、読み込み完了の検知には load イベントを利用するのが基本です。

    例えば以下のような形になります。(実際に動かしていないのでこれで動くかは不明です)

    document.addEventListener('DOMContentLoaded', () => {
      const iframe = document.querySelector('iframe.components-sandbox');
    
      if (!iframe) return;
    
      iframe.addEventListener('load', () => {
        const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
        if (!iframeDoc) return;
    
        const targetDiv = iframeDoc.querySelector('div');
        if (!targetDiv) return;
    
        // 新しいラッパー要素を作成
        const section = iframeDoc.createElement('section');
        section.className = 'abcd';
    
        const inner = iframeDoc.createElement('div');
        inner.className = 'inner';
    
        // 既存の要素を包む
        targetDiv.parentNode.insertBefore(section, targetDiv);
        section.appendChild(inner);
        inner.appendChild(targetDiv);
      });
    });
    

    ただし、WordPress のブロックエディタ(Gutenberg)のカスタムHTMLプレビューは内部的な描画処理や読み込み順が独自になっているため、タイミング調整や対象要素の取得方法などで微調整が必要になる可能性があります。

    エディタ側の更新や再描画の影響も受けるため、その点も考慮しながら検証されるとよいかと思います。

    トピック投稿者 krgn

    (@kirig)

    ご回答ありがとう御座います。
    こちらはこちらとして参考にさせていただきますが、質問部分が違っておりましてすみません。

    iframe.components-sandbox は、カスタムHTMLのプレビューを表示したときのプレビュー部分そのものの囲みです。

    iframe.components-sandbox→html→body→div→カスタムHTMLの中身✴︎

    ✴︎この外側にあるdivを操作してクラスをつけたりしたい、という意味です(プレビューに大してだけ操作できればよい。

    ytsuyuzaki

    (@ytsuyuzaki)

    補足ありがとうございます。
    実際に表示するカスタムHTMLの中身ではなく、ブロックエディタのプレビューでの要素変更ですね。

    この場合、管理画面(ブロックエディタ)での編集時のみにフックして対象の要素を操作する JavaScript が用意できれば実現自体は可能だと思いますが、標準の仕組みとしてその外側のラッパー要素へ直接フックできる明確な方法は、少なくとも私の理解では用意されていないように思います。

    もし実現するのであれば、既存のカスタムHTMLブロックをそのまま利用するのではなく、独自のカスタムブロックを作成し、その中でカスタムHTMLを描画しつつ必要な JavaScript を実行させる、といった構成で対応する方法が考えられます。
    ただし、この方法は実装やメンテナンスの負担が大きくなりやすいため、あまり積極的にはおすすめしにくいです。

    私の知識の範囲では上記のような対応が思い浮かびますが、より良い方法や別のアプローチをご存じの方がいるかもしれませんので、他の方の意見も募ってみるとよいかもしれません。

    モデレーター まーちゅう

    (@rocketmartue)

    こんにちは。
    いくつかアプローチが考えられますが、最適な方法は目的によって大きく変わります。

    たとえば、「プレビューにCSSを当てたい」のか「構造的にラッパーが必要」なのかなど、何のためにプレビューの div にクラスを付与したり、ラッパーで囲みたいのか、具体的に実現したいことを記載いただけると、より最適な回答が付きやすくなると思います。

    トピック投稿者 krgn

    (@kirig)

    ありがとうございました。

    プレビューにCSSを当てたい、が主になります。テンプレートでthe_contentの外側に特定クラス(.abcde)があり、読み込み対象のcssに記述があるため、その部分が崩れます。cssはそのまま修正せずに反映させたいためです。

    • この返信は3週、 6日前にkrgnが編集しました。
    モデレーター まーちゅう

    (@rocketmartue)

    状況がよくわかりました。

    テーマのテンプレートで the_content の外側にある .abcde を前提としたCSSがあり、エディタのプレビューではその祖先要素がないためスタイルが崩れる、ということですね。

    この場合、iframe 内部を直接操作するのではなく、editor.BlockEdit フィルターを使ってエディタ側のDOMでブロックをラッパーで囲む方法が良さそうです。

    cs_edit.js に以下のコードを追加してみてください。
    エディタ上でカスタムHTMLブロックが <div class="abcde">...</div> で囲まれた状態になるので、既存のCSSがそのまま適用されるはずです。
    カスタムHTMLブロックだけでなく他のブロックにも同じラッパーが必要な場合は、props.name !== 'core/html' の条件を外すか、対象ブロックを配列で管理するなど調整してみてください。

    (function () {
    const { createHigherOrderComponent } = wp.compose;
    const { addFilter } = wp.hooks;

    const withCustomWrapper = createHigherOrderComponent((BlockEdit) => {
    return (props) => {
    if (props.name !== 'core/html') {
    return wp.element.createElement(BlockEdit, props);
    }
    return wp.element.createElement(
    'div',
    { className: 'abcde' },
    wp.element.createElement(BlockEdit, props)
    );
    };
    }, 'withCustomWrapper');

    addFilter(
    'editor.BlockEdit',
    'my-theme/custom-html-wrapper',
    withCustomWrapper
    );
    })();
    モデレーター まーちゅう

    (@rocketmartue)

    追記、JSのコードについて

    createHigherOrderComponent
    既存のブロック編集コンポーネント(BlockEdit)を受け取り、新しいコンポーネントで包んで返す関数です。Reactの高階コンポーネント(HOC)パターンに基づいています。

    props.name !== 'core/html'
    ブロックの種類を判定しています。カスタムHTMLブロック(core/html)以外はラッパーを追加せず、そのまま返します。

    wp.element.createElement
    Reactの createElement に相当する関数です。<div class="abcde"> を作成し、その中に元のブロック編集コンポーネントを配置しています。

    addFilter('editor.BlockEdit', ...)
    ブロックエディタが各ブロックの編集画面を描画する際に呼ばれるフィルターです。ここにフックすることで、ブロックの描画をカスタマイズできます。

    (function () {
    // wp.compose から高階コンポーネント作成関数を取得
    const { createHigherOrderComponent } = wp.compose;
    // wp.hooks からフィルター追加関数を取得
    const { addFilter } = wp.hooks;

    /**
    * ブロックの編集コンポーネントをラップする高階コンポーネント
    * 対象ブロックの外側に任意のラッパー要素を追加する
    */
    const withCustomWrapper = createHigherOrderComponent((BlockEdit) => {
    return (props) => {
    // カスタムHTMLブロック以外はそのまま返す
    if (props.name !== 'core/html') {
    return wp.element.createElement(BlockEdit, props);
    }

    // カスタムHTMLブロックを <div class="abcde"> で囲む
    return wp.element.createElement(
    'div',
    { className: 'abcde' },
    wp.element.createElement(BlockEdit, props)
    );
    };
    }, 'withCustomWrapper');

    // editor.BlockEdit フィルターに登録
    // 第2引数はフィルターの一意な名前空間
    addFilter(
    'editor.BlockEdit',
    'my-theme/custom-wrapper',
    withCustomWrapper
    );
    })();

    JS読み込み側の補足

    既に enqueue_block_editor_assets で JS を読み込む仕組みを用意されていますが、依存関係に wp-composewp-hooks を追加してください。これがないと wp.composewp.hooks が未定義になりエラーになります。

    function addBlockEditorStyle() {
    wp_enqueue_script(
    'theme-gutenberg-js',
    get_theme_file_uri( '/js/cs_edit.js' ),
    array( 'wp-blocks', 'wp-element', 'wp-edit-post', 'wp-components', 'wp-data', 'wp-compose', 'wp-hooks' ),
    false,
    true
    );
    }
    add_action( 'enqueue_block_editor_assets', 'addBlockEditorStyle' );
    トピック投稿者 krgn

    (@kirig)

    ありがとうございました。
    時間かかりましたが解消できました。

    モデレーター まーちゅう

    (@rocketmartue)

    @kirig 解決されたようでよかったです。

    具体的にどのように解決されたのかをぜひ情報を共有してください。
    他のフォーラム参加者の参考になります。

9件の返信を表示中 - 1 - 9件目 (全9件中)

このトピックに返信するにはログインが必要です。