エディタのプレビュー要素の囲みにクラスを付与したい
-
・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');
-
ご質問の内容は、カスタム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プレビューは内部的な描画処理や読み込み順が独自になっているため、タイミング調整や対象要素の取得方法などで微調整が必要になる可能性があります。
エディタ側の更新や再描画の影響も受けるため、その点も考慮しながら検証されるとよいかと思います。
ご回答ありがとう御座います。
こちらはこちらとして参考にさせていただきますが、質問部分が違っておりましてすみません。iframe.components-sandbox は、カスタムHTMLのプレビューを表示したときのプレビュー部分そのものの囲みです。
iframe.components-sandbox→html→body→div→カスタムHTMLの中身✴︎
✴︎この外側にあるdivを操作してクラスをつけたりしたい、という意味です(プレビューに大してだけ操作できればよい。
補足ありがとうございます。
実際に表示するカスタムHTMLの中身ではなく、ブロックエディタのプレビューでの要素変更ですね。この場合、管理画面(ブロックエディタ)での編集時のみにフックして対象の要素を操作する JavaScript が用意できれば実現自体は可能だと思いますが、標準の仕組みとしてその外側のラッパー要素へ直接フックできる明確な方法は、少なくとも私の理解では用意されていないように思います。
もし実現するのであれば、既存のカスタムHTMLブロックをそのまま利用するのではなく、独自のカスタムブロックを作成し、その中でカスタムHTMLを描画しつつ必要な JavaScript を実行させる、といった構成で対応する方法が考えられます。
ただし、この方法は実装やメンテナンスの負担が大きくなりやすいため、あまり積極的にはおすすめしにくいです。私の知識の範囲では上記のような対応が思い浮かびますが、より良い方法や別のアプローチをご存じの方がいるかもしれませんので、他の方の意見も募ってみるとよいかもしれません。
こんにちは。
いくつかアプローチが考えられますが、最適な方法は目的によって大きく変わります。たとえば、「プレビューにCSSを当てたい」のか「構造的にラッパーが必要」なのかなど、何のためにプレビューの
divにクラスを付与したり、ラッパーで囲みたいのか、具体的に実現したいことを記載いただけると、より最適な回答が付きやすくなると思います。ありがとうございました。
プレビューにCSSを当てたい、が主になります。テンプレートでthe_contentの外側に特定クラス(.abcde)があり、読み込み対象のcssに記述があるため、その部分が崩れます。cssはそのまま修正せずに反映させたいためです。
-
この返信は3週、 6日前に
krgnが編集しました。
状況がよくわかりました。
テーマのテンプレートで
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
);
})();追記、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-composeとwp-hooksを追加してください。これがないとwp.composeやwp.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' ); -
この返信は3週、 6日前に
このトピックに返信するにはログインが必要です。