はてなブログの画像ポップアップをオリジナル画像に変える

はてなブログでは画像をクリックしますとポップアップでその画像が表示されます。ただ、特にスマホですと画像自体が横幅いっぱいに表示される場合が多いですのでほとんどポップアップの意味がなく、CSSでクリックイベントをオフにしている人も多いかと思います。

また、はてなブログでは画像保存にフォトライフ(Fotolife)というウェブアルバムを使っており、保存の際にオリジナル画像を保存するように設定できます。

そこで、デフォルトでは表示画像と同じ画像がポップされる仕様をオリジナル画像を表示するように変更しようと思います。


前記事:Javascript, jQuery のイベントを削除する



はてなブログ画像ポップアップの仕組み

  • ポップアップは、クラス名に .hatena-fotolife を持つ画像にクリックイベントが設定される
  • クリックされると jQuery のプラグイン Colorbox が呼ばれる
  • オーバーレイクリックで閉じる以外にポップアップをクリックで閉じる設定が付加されている
  • それらの関数は https://cdn.blog.st-hatena.com/js/hatenablog.js に記述されている


仕様変更の概要

  • 設定されたクリックイベントを削除する
  • クリックされた画像の src 属性からオリジナル画像の URL を作成し存在チェックをする
  • 存在していればオリジナル画像、なければ元画像で Colorbox を呼ぶ
  • ポップアップをクリックで閉じるイベントを追加する


画像の存在チェック

過去の記事にはオリジナル画像を持っていないものもありますのでその振り分けが必要になります。その画像の存在チェックが以外に難しいです。


onload, onerror を使う

よく使われるのは img要素の onload, onerror イベントを見る方法です。

const img = new Image();
img.onload = () => {
  console.log("image exists");
}
img.onerror = () => {
  console.log("no image");
}
img.src = "画像url";


ただし、画像の読み込みは、 src属性に url を設定しますと非同期で走りますのでチェックのタイミングを誤りますと正しく評価できません。


コールバック関数にしてみる

const checkImage = (url, callback) => {
  const img = new Image();
  img.onload = () => callback(true);
  img.onerror = () => callback(false);
  img.src = url;
};

checkImage("画像url", (result) => console.log(result));


これならうまくいきそうなんですが、当然ながら、画像がなければ下の画像のように 403 (Forbidden) エラーが出ます。


f:id:ausnichts:20201031102708j:plain

これはどの方法をとっても制御できません(多分)。


XMLHttpRequest を使う

もうひとつ、XMLHttpRequest を使う方法もありますが、今回の場合はオリジン間リソース共有(CORS)エラーで読み込み自体がサーバーから拒否されます。


const xhr = new XMLHttpRequest();
xhr.open("HEAD", "画像url", false);
xhr.send(null);
consol.log(xhr.status);


はてなブログの画像ポップアップをオリジナル画像に変える

ということで Javascript は次のようになりました。


※自由に使っていただいて構いませんが、転載はしないでください。

window.addEventListener("DOMContentLoaded", () => {
    $(document).off("click","img.hatena-fotolife, img.magnifiable, img.http-image");
    $(document).on("click","img.hatena-fotolife", (e) => {
        const checkImage = (url) => {
            return new Promise((resolve) => {
                const originalUrl = url.replace(".jpg", "_original.jpg");
                const img = new Image();
                img.src = originalUrl;
                img.onload = () => resolve(originalUrl);
                img.onerror = () => resolve(url);
            });
        };
        const src = $(e.currentTarget).attr("src");
        checkImage(src).then(result => {
            $(this).colorbox({maxWidth:"95%",maxHeight:"95%",transition:"none",photo:!0,href:result,title:" ",open:!0,opacity:.9});
        });
    });
    $("#cboxContent").on("click", () => $.colorbox.close());
});


お問い合わせ等

当記事内のスクリプト等によるいかなる損害についても責任を負いかねますので自己責任でご使用ください。

お問い合わせ、バグの報告、仕様変更のご要望等は Contact Us までお願いします。


日本の美しい幻想風景

日本の美しい幻想風景