IMUZA.com

Xserver<<WordPress(ConoHa)<<はてなブログ

ホーム / javascript / はてなブログカードの iframe 内を弄る(自サイトのみ)

はてなブログカードの iframe 内を弄る(自サイトのみ)

2019/01/15 javascript, はてなブログ

  • 外部リンクを別ウィンドウで開く方法
  • ブログカードはすべてのリンクが別ウィンドウで開く
  • クロスドメインで iframe内を弄れない
  • 自サイト名/embed でもブログカードはできる
  • iframe内の aタグを target=_parent に変更する javascript
  • iframeの src属性を自サイトに変更する javascript
  • 完成

外部リンクを別ウィンドウで開く方法

はてなブログでは、公式のエディタを使ってリンクを挿入しますと外部サイトであっても同じウィンドウ(タブ)で開いてしまいます。

HTML編集で target="_blank" を直書きすればいいのですが、面倒ですし、うっかり忘れたりすることも多いので、当サイトでは、javascript で target="_blank" を挿入するようにしています。興味のある方は下記記事をご覧ください。

  • はてなブログのリンクを素の Javascript で別ウィンドウに開く(jQuery なし)
  • はてなブログ簡単カスタマイズ imzModules バージョンアップ

ブログカードはすべてのリンクが別ウィンドウで開く

で、この記事の本題はそのことではなく、ブログカードでリンクを挿入した場合には逆に自サイトも別ウィンドウで開いてしまうのをなんとかしようというものです。

ブログカードとはこれです。

www.imuza.com

HTMLソースを見ますとこうなっています。

<iframe
  src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.imuza.com%2Fentry%2F2019%2F01%2F07%2F210817"
  title="はてなブログ簡単カスタマイズ imzModules バージョンアップ - IMUZA.com"
  class="embed-card embed-blogcard"
  scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe>
<cite class="hatena-citation">
  <a href="https://www.imuza.com/entry/2019/01/07/210817">www.imuza.com</a>
</cite>

iframe 内のリンクを見てみますと、

<a href="https://www.imuza.com/entry/2019/01/07/210817" target="_blank">はてなブログ簡単カスタマイズ imzModules バージョンアップ</a>

のように、target="_blank" が挿入されています。これ、当たり前で、何も指定しないと iframe内に表示されてしまいます。

で、この target要素の値を自サイトのブログカードだけ _parent に変更できないかということです。

クロスドメインで iframe内を弄れない

iframe内のコンテンツを取得するには contentWindow.document プロパティがあります。ただ、これが使えるのはドメイン名が同じ自サイトに限ります。ドメインが違う場合は次のようなクロスドメインのエラーが出ます。

Uncaught DOMException: Blocked a frame with origin "https://www.imuza.com" from accessing a cross-origin frame.

え、自サイトなのに? と思うのですが、ブログカードのソースを見てみますと、src属性が https://hatenablog-parts.com になっていますのでクロスドメインになってしまいます。独自ドメインといえどもブログシステムのバーチャルドメイン(でいいのかな?)ですので当然です。

自サイト名/embed でもブログカードはできる

いろいろ調べますと、クロスドメイン通信ができる window.postMessage というメソッドがあることがわかったのですが、これで可能かどうかは別にしても、外部サイト側(iframe内のページ)にもスクリプトが必要になるというとても面倒なことになりますので早々にあきらめ、さらに調べましたら、iframeの src属性が 自サイト名/embed/エントリー でもブログカードはできることがわかりました。

たとえば、ブログカードにしたい自サイトのページが https://www.imuza.com/entry/2019/01/07/210817 であれば、iframe の src属性にそのURLの entry を embed に差し替えた値を指定すればクロスドメインにならずにブログカードをつくることができます。

手作業で行う場合は、見たまま編集に限りますが、ブログカードを挿入した後にHTML編集で src属性を変更しておけば、後は表示する際に javascriptで aタグの taget属性を変更することが可能になるはずです。

iframe内の aタグを target=_parent に変更する javascript

<script>
window.addEventListener('load', function(){
    var contents = document.getElementById('main'); // メインコンテンツ内のiframeに限定するため
    var cards = contents.getElementsByTagName('iframe');
    Array.prototype.forEach.call(cards,function(card){
        var cFlag = card.classList.contains('embed-blogcard'); // ブログカードか?
        var reg = new RegExp('^http(s)?://' + location.hostname + '.+$'); // 自サイトか?
        if(cFlag && reg.test(card.src)){
            var body = card.contentWindow.document;
            var as = body.getElementsByTagName('a');
            Array.prototype.forEach.call(as, function(a){
                a.target = '_parent';
            });
        }
    });
}, false);
</script>

このスクリプトをフッタにでも入れておけば、iframeの src属性が自サイトに変更されていればブログカードは同じウィンドウで開きます。イベントが発火するタイミングは iframe内のドキュメントが読み込まれていないと意味がありませんので、すべてのリソースが読み込まれた後に発火する loadにします。

iframeの src属性を自サイトに変更する javascript

(2019/1/20)この項目の内容はうまくいかない場合があります。原因は調査中です。

<script>
document.addEventListener('DOMContentLoaded', function(){
    var article = document.getElementsByTagName('article')[0];
    if(article !== undefined){
        var iframes = article.getElementsByTagName('iframe');
        var reg = new RegExp('http(s)?%3A%2F%2F' + location.hostname + '.+$');
        Array.prototype.forEach.call(iframes, function(iframe){
            var embedUrl = reg.exec(iframe.src);
            if(embedUrl !== null) iframe.src = decodeURIComponent(embedUrl[0]).replace('entry', 'embed');
        });
    }
}, false);
</script>

iframeの src属性は iframe内が展開される前に変更しておかないとクロスドメインになってしまうようですので、イベントの発火は COMContentLoadedを使います。

ということで、ふたつ合わせて次のスクリプトをフッタにでも入れておけば、はてな公式のエディタで挿入したブログカードのうち、自サイトのものは同じウィンドウで開くはずです。

完成

(2019/1/20)この項目の内容はうまくいかない場合があります。原因は調査中です。

<script>
document.addEventListener('DOMContentLoaded', function(){
    var article = document.getElementsByTagName('article')[0];
    if(article !== undefined){
        var iframes = article.getElementsByTagName('iframe');
        var reg = new RegExp('http(s)?%3A%2F%2F' + location.hostname + '.+$');
        Array.prototype.forEach.call(iframes, function(iframe){
            var embedUrl = reg.exec(iframe.src);
            if(embedUrl !== null) iframe.src = decodeURIComponent(embedUrl[0]).replace('entry', 'embed');
        });
    }
}, false);


window.addEventListener('load', function(){
    var contents = document.getElementById('main'); // メインコンテンツ内のiframeに限定するため
    var cards = contents.getElementsByTagName('iframe');
    Array.prototype.forEach.call(cards,function(card){
        var cFlag = card.classList.contains('embed-blogcard'); // ブログカードか?
        var reg = new RegExp('^http(s)?://' + location.hostname + '.+$'); // 自サイトか?
        if(cFlag && reg.test(card.src)){
            var body = card.contentWindow.document;
            var as = body.getElementsByTagName('a');
            Array.prototype.forEach.call(as, function(a){
                a.target = '_parent';
            });
        }
    });
}, false);
</script>

何だか面倒なことになりますね。他にいい方法はないものでしょうか?

はてなブログ簡単カスタマイズ imzModules バージョンアップ
Joomla! 3.9.2 セキュリティ & バグフィックスがリリースされています
Twitter
Facebook
ブックマーク
LINEで送る

最初のサイドバー

最新記事

2023/02/1

WordPress:期間指定で人気記事を表示(プラグインなし)

2023/01/26

WordPress:メニューのid,classを整理カスタマイズ

2023/01/19

WordPress:JSON-LD構造化データをプラグインなしで出力

2023/01/11

WordPress:OGPタグをプラグインなしで挿入する

2022/12/27

WordPress:canonicalタグをプラグインなしで制御する

最新記事を一覧で見る

よく読まれている記事

よく読まれている記事を一覧で見る

カテゴリー

  • はてなブログ214
  • WebTips108
  • javascript98
  • Joomla!88
  • Windows68
  • CSS63
  • Wordpress60
  • Joomla!更新53
  • Linux49
  • はてなテーマ45
  • Plamo33
  • Google32
  • はてなプラグイン25
  • php22
  • Node.js18
  • Ubuntu16
  • SASS16
  • laravel415
  • Chrome11
  • cms-style10
  • iPhone9
  • genesis6
  • ConoHa WING6
  • Git入門6
  • Python5
  • Android5
  • スマートフォン4
  • PC全般4
  • 静的サイトジェネレーター3
  • Firefox3
  • SSD3
  • Facebook3
  • Blankslate3
  • Docker3
  • Mactype2
  • GitHub2
  • youtube1
  • rails入門1
  • Twitter1
  • はてなブクマ1
  • 映画1
  • Xserver1

Footer

My Web Sites

  • @半径とことこ60分
  • そんなには褒めないよ。映画評
  • IMUZA.com
  • GitHub

Related Sites

  • WordPress公式
  • WordPress関数リファレンス
  • PHPマニュアル

Contact Us

  • お問い合わせフォーム
  • Twitter
  • Facebook
  • Feedly

Copyright © 2023 · IMUZA.com