WordPressの Embedカードのリンクを別ウィンドウで開く(PCのみ。スマホ・タブレットはそのまま)

WordPressの Embedカード(ブログカード)のリンクは、デフォルトでは同ウィンドウで開くようになっていますが、これを別ウィンドウ(別タブ)で開くようにしてみました。
PCブラウザのみに適用。スマホやタブレットではデフォルトのまま同ウィンドウで開くようにしました。

WordPressの Embedカードは <iframe>で表示され、この<iframe>は「sandbox属性」で中に仕込まれた HTMLの機能を制限しています。
ですのでテンプレートのHTML部分(になぜかあるtarget属性)をいじってもムダ。
たぶん JavaScript でリンクを飛ばす先を指定しているんだろうと、まずは 同ウィンドウに開くjsを探すところから始めました。

本日のINDEX

本ブログの Embedカードを貼っておきます。クリック(タップ)してみてください。
Embedに関するPHPファイルの構成の記事です。

WordPress4.5で Embedカードの PHPファイルの構造がだいぶ変わったみたい

スポンサーリンク

同ウィンドウに開くjsを探す

まずは Embedカードのベースファイル内を「window.top」や「top」で検索しました。
ベースファイルは wp-includes > embed.php です。

すると、カードの <blockquote> や <iframe> を書き出す部分で、<iframe> の前の CDATAセクションに top にリンクを開く指定がありました。

jsファイル名が「wp-embed.js」らしいので、embed.php内を検索してみると、ありました。この jsファイルのリンクを書き出すコードが。
というわけで、この「wp-embed.js」をオリジナルに差し替えればイケそうです。

この wp-embed.js を見てみます。

やはり「window.top.location.href」を使ってますので、top の代わりに open() を使えば別ウィンドウで開くはず。

このファイルは wp-includes > js 内にあります。

wp-embed-template.js(wp-embed-template.min.js)は、カード内のシェアボタンを押した時のダイアログ表示用のようです。

スマホ・タブレットではデフォルトのままに

window.top.location.href を window.open().location.href に変更すると、PCブラウザでは 別ウィンドウ(別タブ)で開きますが、iOS では開きません
iOSでは、ポップアップブロック機能がデフォルトでONの仕様だからだそうです。

これは非同期通信を同期に変えれば(async: false)良いらしい…などの情報もあったのですが、そもそもスマホ・タブレットではスワイプで行ったり来たりしたほうが早いので、デフォルトのままにし、PCブラウザだけ、別ウィンドウで開く設定にすることにしました。

PCブラウザでも「別ウィンドウで開く必要があるか」という問題がありますが。
私はPCブラウザでは「今見ているページは確保して、参考ページは別タブで開きたい」です。単に好みの問題ですが。
PCで調べ物をしている時は、同ウィンドウで開き続けて ある程度進んでしまうと、元のページは「どれだっけ?」状態になります。別タブで開いていたほうが、横道に逸れてもすぐ元に戻れてラクなんです。
そこで本ブログも、ほとんどの外部リンクは別ウィンドウ(別タブ)で開くようにしており、Embedカードも、そのようにしたいと思いました。
ただし、スマホ・タブレットの場合は、別ウィンドウで開くと、かえって元に戻るのに時間がかかる。スワイプでささっと探せるので同ウィンドウで開いていたほうがラクです。

というわけで、スマホやタブレットか PCブラウザかを判定して、条件分岐で動作を指定することにしました。

ユーザーエージェントを判別して条件分岐させる

オリジナルのjsファイルを作ります。

ユーザーエージェント(ブラウザ)を判別するコードは、コチラからいただきました。

2015年版JavaScriptユーザエージェント判別・判定|W3G合同会社

これを利用して JavaScriptで「スマホ・タブレットの場合」「それ以外の場合(PC)」を条件分岐をさせます。
ファイルは wp-embed.js をコピーして編集します。

ファイルの先頭にユーザエージェントの判別のコードを入れ、
こう↓なっていた箇所を、

if ( document.activeElement === source ) {
  window.top.location.href = data.value;
}

このように書き換えただけ。

if ( document.activeElement === source ) {
  if(_ua.Mobile || _ua.Tablet){
    window.top.location.href = data.value;
  }else{
    window.open().location.href = data.value;
  }
}

このファイルはミニファイしておきました。

ミニファイにはこちらのサイトが便利。
Pretty Diff – The difference tool
Minify だけでなく Beautify もできますし、CSS も JavaScript もOKです。

functions.phpでオリジナルのJavaScriptを読み込む

上記のファイルをアクティブなテーマ内に置き、functions.phpで下記のコードを書いて、各ページの </body>の前に jsを書き出すようにしました。

function my_embed_scripts() {
   wp_enqueue_script( 'myembedjs', get_template_directory_uri() . '/js/wp-embed.min.js', array(), false, true );
}
add_action( 'wp_enqueue_scripts', 'my_embed_scripts');

上のコードでは、オリジナルのファイル「wp-embed.min.js」は テーマ内の「js」フォルダに置いています。

これだけだと、オリジナルのjsに加えて、もとのデフォルトのjsも読み込まれています。

<script type='text/javascript' src='http://webdesign.practice.jp/wp-content/themes/webd_practice/js/wp-embed.min.js?ver=4.5.3'></script>
<script type='text/javascript' src='http://webdesign.practice.jp/wp-includes/js/wp-embed.min.js?ver=4.5.3'></script>
</body>
</html>

ベースファイル wp-includes > embed.php にある デフォルトのjsを読みこませるコードがイキているからですね。

さきほど functions.php に書いたコードに、この↑デフォルトjsを読み込ませない1行を追加します。

function my_embed_scripts() {
   wp_enqueue_script( 'myembedjs', get_template_directory_uri() . '/js/wp-embed.min.js', array(), false, true );
   wp_deregister_script( 'wp-embed' );
}
add_action( 'wp_enqueue_scripts', 'my_embed_scripts');

これで、Embedカードの <iframe>用の jsが書き換えられ、PCでは別ウィンドウ(別タブ)に、スマホ・タブレットならデフォのままの同ウィンドウに リンクが開くようになりました。

wp_enqueue_script() のパラメータ

wp_enqueue_script() でjsファイルを読み込みます。
これの5つのパラメータについてメモ。

wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
$handle(必須)(デフォルト値:なし)
ハンドル名を指定
決められたハンドル名もあるので、今回のように単にオリジナルのjsに差し替えるだけなら、絶対かぶらない名前をつけます。
$src(デフォルト値:false)
ファイルのパス
ファイルを置いた場所を指定します。
$deps(デフォルト値:array())
このスクリプトより前に読み込まれる必要があるスクリプトをハンドル配列で指定
例えば、JQuery に依存するjsをリンクする場合は array( ‘jquery’ )
$ver(デフォルト値:false)
スクリプトのバージョン番号
バージョンなんて無い場合は、falseにしておけば WordPress のバージョン数と同じバージョン番号が勝手に追加されます。
$in_footer(デフォルト値:false)
書き出す位置
デフォルトの false だと <head>要素の中にリンクが書き出されます。←この場合、テンプレートタグ「wp_head()」を使用して書き出します。
true にすれば </body>の前に書き出します。←この場合、テンプレートタグ「wp_footer()」で書き出すので、footer.phpに忘れずに「wp_footer()」を書いておく必要があります。

参考:関数リファレンス/wp enqueue script – WordPress Codex 日本語版

iframeはsandbox化されてるので target属性は無効

最後に余談ですが、
冒頭でもちらっと書きましたが、WordPressの Embedカードは <iframe>で表示され、このiframeは「sandbox属性」で、中のHTMLの機能の制限をしています。

<blockquote data-secret="◯◯◯◯" class="wp-embedded-content">
  <a href="記事のURL">記事タイトル</a>
</blockquote>
<iframe class="wp-embedded-content"
  sandbox="allow-scripts" 
  security="restricted" 
  style="position: absolute; clip: rect(1px, 1px, 1px, 1px);" 
  src="埋め込むHTML" 
  width="500" 
  height="282" 
  title="記事のタイトル"
  data-secret="◯◯◯◯" 
  frameborder="0" 
  marginwidth="0" 
  marginheight="0" 
  scrolling="no">
</iframe>

sandbox="allow-scripts" と指定されているので、iframe内の HTMLはスクリプトのみ有効
HTML内にフォームがあっても表示のみでデータを送ったりは不可。そして、HTMLの target属性は無効になります。

sandbox属性についてはコチラ↓をご覧ください。
ほんっとにはじめての HTML5 と CSS3|[63] インライン・フレームで 他のHTMLファイルを組み込もう

にも関わらず、wp-includes > theme-compat > embed-content.php のHTML部分のリンクには「target="_top"」の記述があるんだよね。

無効になるものを記述するとは変ですね。(ここを _blank にしてみたりしたんだよね最初。なんか悔しい)
何か目的があってのことかもしれないけど。

私はこの「embed-content.php」を自分のテーマ内にコピペして編集していますが、そのときこの target属性をすべて削除しました。それでも今のところ別に何の問題なく Embedカードを表示し、リンク先に飛んでいます。なにか不具合あったら元に戻しますww

関連記事

WordPressの Embedカードのスタイルを編集する方法2つ

前回の記事で、WordPress 4.5 の Embedカード(ブログカード)の「テンプレートの構成」や「HTML要素のクラス名」などを調べました。これを元に、 [記事を読む]

WordPress4.5で Embedカードの PHPファイルの構造がだいぶ変わったみたい

前回から WordPressの Embedカード(ブログカード)について調べたことをメモっています。 今回は Embedカードの PHPファイルの構造について [記事を読む]

WordPressの Embed(埋め込み)機能が意外とオモシロイ。何がどう貼られるか確認してみた

投稿画面に WordPressサイトの記事のURLを書くだけで Embedカードで置けるそうなので、どんなカードが貼られるのか試してみました。 画像の縦横比に [記事を読む]

Comments

  1. Kanami より:

    はじめまして。
    とても参考になる良記事を公開して下さりありがとうございます。
    どこを探してもわからなかった別ウィンドウでの表示方法が実現できて大変嬉しく思っております。

    最後に、fuctions.php追加するコード内の相対パス「 ‘/js/wp-embed.min.js’」の部分ですが、私の環境では「’/js/wp-embed.js’」に変更することで正常に表示されるようになりましたので、ご報告させていただきます。

    この度は、本当にお世話になりました。
    心より感謝御礼申し上げます。

Kanami へ返信する コメントをキャンセル

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。

^