はてなブログでは画像をクリックしますとポップアップでその画像が表示されます。ただ、特にスマホですと画像自体が横幅いっぱいに表示される場合が多いですのでほとんどポップアップの意味がなく、CSSでクリックイベントをオフにしている人も多いかと思います。
また、はてなブログでは画像保存にフォトライフ(Fotolife)というウェブアルバムを使っており、保存の際にオリジナル画像を保存するように設定できます。
そこで、デフォルトでは表示画像と同じ画像がポップされる仕様をオリジナル画像を表示するように変更しようと思います。
前記事:Javascript, jQuery のイベントを削除する
01はてなブログ画像ポップアップの仕組み
- ポップアップは、クラス名に
.hatena-fotolife
を持つ画像にクリックイベントが設定される - クリックされると jQuery のプラグイン Colorbox が呼ばれる
- オーバーレイクリックで閉じる以外にポップアップをクリックで閉じる設定が付加されている
- それらの関数は
https://cdn.blog.st-hatena.com/js/hatenablog.js
に記述されている
02仕様変更の概要
- 設定されたクリックイベントを削除する
- クリックされた画像の src 属性からオリジナル画像の URL を作成し存在チェックをする
- 存在していればオリジナル画像、なければ元画像で Colorbox を呼ぶ
- ポップアップをクリックで閉じるイベントを追加する
03画像の存在チェック
過去の記事にはオリジナル画像を持っていないものもありますのでその振り分けが必要になります。その画像の存在チェックが以外に難しいです。
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)
エラーが出ます。
これはどの方法をとっても制御できません(多分)。
XMLHttpRequest を使う
もうひとつ、XMLHttpRequest を使う方法もありますが、今回の場合はオリジン間リソース共有(CORS)エラーで読み込み自体がサーバーから拒否されます。
const xhr = new XMLHttpRequest(); xhr.open("HEAD", "画像url", false); xhr.send(null); consol.log(xhr.status);
04はてなブログの画像ポップアップをオリジナル画像に変える
ということで 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()); });
05お問い合わせ等
当記事内のスクリプト等によるいかなる損害についても責任を負いかねますので自己責任でご使用ください。
お問い合わせ、バグの報告、仕様変更のご要望等は Contact Us までお願いします。