Element.scrollIntoView() with options

「だいたいあの辺に飛べば良いや」というときに便利な scrollIntoView() メソッド。
呼び方は三通り。

element.scrollIntoView();
element.scrollIntoView(alignToTop); // Boolean parameter
element.scrollIntoView(scrollIntoViewOptions); // Object parameter

そのうち、三番目の記法の話。

MDN は、こうある。

https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

こ、これだけ?
リファレンスを見に来るような人は、その選択肢の挙動が知りたいんだろうに。
以下、それぞれの属性の取りうる値(リファレンスのまま)と、その挙動。
選択肢で、気持ち赤くしてあるのがデフォルト値。

behavior

スクロールするときの動作の指定。

smooth
滑らかにアニメーションしてスクロールする
instant
アニメーションせずに、ぱちっとジャンプする
auto
マウスやキーの操作でスクロールしたときの動作と同じ動きをする

auto に影響を与えるのは、ブラウザの設定と、cssscroll-behavior
「ブラウザの設定」は、Firefox だと、about:config の general.smoothScroll
true でアニメーション、false でいきなりジャンプ。
その挙動を要素ごとに変更できるのが、cssscroll-behavior
general.smoothScroll が false になっていても、scroll-behaviorsmooth になっている要素のスクロールはぬるっと動く。

block

指定した要素がどの位置に見えるようにスクロールするかの指定(縦方向)。

start
要素がウィンドウの上端に来るように移動する
center
要素がウィンドウの中央に来るように移動する
end
要素がウィンドウの下端に来るように移動する
nearest
要素がウィンドウの中に入るように、最小限の移動距離で移動する

nearest が指定されたときは、対象の要素が
現在位置よりも下にある場合:要素がウィンドウの下に来るように、
現在位置よりも上にある場合:要素がウィンドウの上に来るように、
移動する。
更に、もし、対象の要素がウィンドウ内に一部でも見えているとスクロールしない。
その他の startcenterend の場合には、要素が見えていても指定された位置になるようにスクロールされる。

start の残念なところは、よくウィンドウの上に配置されている position: fixed の下に潜り込んじゃうところ。
キーでのスクロールの場合には、position: fixed のサイズを除外してスクロールしてくれるのに(Firefox の場合。他は知らん)。

inline

指定した要素がどの位置に見えるようにスクロールするかの指定(横方向)。

start
要素がウィンドウの左端に来るように移動する
center
要素がウィンドウの中央に来るように移動する
end
要素がウィンドウの右端に来るように移動する
nearest
要素がウィンドウの中に入るように、最小限の移動距離で移動する

縦方向の block と考え方は同じ。

横方向のスクロールがあるページは見づらいので、最近はほとんど見ないので、デフォルトの nearest を変更しなければいけないことは、まずないんじゃないかと。


blockinline は分かりにくい。
verticalhorizontal じゃダメだったんだろうか。


(おしまい)

ページの途中に表示するメッセージ


この質問の件。

「どんな方法でもいいので」ということなので、元のコードを修正するのではなく、動くコードを提示してみる。
↓にメッセージ。




パラメータは、質問に合わせて key で、値は大阪と広島。
お試しのリンク。


こんな感じのコード。

(function() {
    var m = /\bkey=(.*?)(&|$)/.exec(location.search);
    if (m) {
        var msg = "", img_src;
        switch (decodeURIComponent(m[1])) {
        case "大阪":
            msg = "大阪でっせ";
            img_src = "http://www.pref.osaka.lg.jp/houbun/reiki/reiki_honbun/word/k201IG00000410.jpg";
            break;
        case "広島":
            msg = "広島じゃけえ";
            img_src = "https://www.pref.hiroshima.lg.jp/soshiki_file/kouhou/kids/kids02-01.jpg";
            break;
        }
        if (msg != "") {
            document.write('<p class="message-by-key">' +
                '<img src="http://q.hatena.ne.jp/images/icon-jinriki-og3.gif">' +
                '<img src="' + img_src + '">' + msg + "</p>");
    }
})();


今どきのコードだと、こんな感じ?


(_ => {
    const message = {
        "大阪" : "大阪でっせ",
        "広島" : "広島じゃけえ",
    };
    const url = new URL(location.href);
    const param = url.searchParams;
    if (param.has("key")) {
        const key = param.get("key");
        if (message[key]) {
            const c_ = document.currentScript;
            c_.parentNode.insertBefore(Object.assign(document.createElement("p"), {
                innerHTML: message[key],
                className: "message-by-key",
            }), c_.nextSibling);
        }
    }
})();

Internet Explorer だと、この辺りがダメ。




もうひとつ質問きた。

エリア1

エリア2

エリア3

エリア4

エリア5

はてなブログでコメント欄を大きくする

id:INTER8 さんから、コメント欄を大きくするのは、どうやるのだ、とコメントがあったので。
「デザイン」→「カスタマイズ」→「デザインCSS」に、以下のコードを追加してます。

body > div.hatena-iframe-container:last-child:not([id="hatena-diary-edit-in-place"]) {
    width: 800px !important;
}

"800px" が、外側の横幅のサイズです。

Google の検索順位判定ロジックに変更が施されたかもとか、そんなこと

突然奈落の底へ落ちる【Google大変動2018年8月】何も言えなくて…夏」の件。

ブログでの広告収入なんて興味ないので、書きたいことを書き散らかしてるだけのブログをいくつか持ってる。
年に数回くらいしか開かない Search Console を見てみた。
その中でも書き込み量が、まあまああるふたつの流入の様子。
グラフの右側 \frac{1}{3} くらいが 2018年8月の分。

はてなブログの方

FC2の方

はてなブログの方は、人力検索がつまらなくなったこともあって、無駄に長い投稿が最近 増えてきたかなあという気はする程度で、真面目に更新してるとは言えない。
FC2の方は、ほんとに倉庫というレベルで、一ヶ月放置すると出てくる広告を消す程度にしか更新してない。


確かに、2018年8月に入ってから、検索順位の判定に何か変わったのかも、という気がしなくもない程度にはうっすらと傾向が変わってる。
何かしらの判定が厳しくなったのかしらということを想像してるらしいけれど、はてなブログの方は、(ほんのりだけど)むしろ増えてるので、一律に厳しくなったのではないような気もする。
2018年8月は、どちらのブログにも記事を投稿してないから、過去記事のクロール結果、もしくは、クロール済みの結果の判定に何かあったのかも。


広告収入を期待してる人は大変だね :-p
# 一般論にするには、PV 少なすぎるな(ケラケラ

人力検索と Hatena::Let とアドオンと

まずは、

Hatena::Let のコードがさみしいので、Syntax Highlight しようと思ったの。
よく見るところだから、Bookmarklet じゃなくてユーザスクリプト(アドオン)なの。

クラッチパッドで確認したよ


(() => {
    document.body.appendChild(Object.assign(document.createElement("link"), {
        rel: "stylesheet",
        href: "https://highlightjs.org/static/demo/styles/zenburn.css",
    }));
    document.body.appendChild(Object.assign(document.createElement("script"), {
        src: "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js",
        onload: () => {
            document.querySelectorAll('pre.code-raw > code').forEach(e => {
                hljs.highlightBlock(e);
            });
        },
    }));
})();

そんなに難しいことしてない。

アドオンだと動かないんだ

ブラウザツールボックスのコンソールには、こんなエラーが出てる。


ReferenceError: hljs is not defined

すぐに思い出したよ(うそ。ちょっと「あれ?」ってなった)。
chrome extension について。 ページ内から、contentscripts.js … - 人力検索はてな

Although content scripts don't by default get access to objects created by page scripts,

Content scripts - Mozilla | MDN

コンテンツスクリプトの window と、ページスクリプトの window は、同じじゃない。
だから、ページスクリプトにある window.hljs は、コンテンツスクリプトでは使えない。

window.postMessage と window.addEventListener を使うんだった


(() => {
    const d_ = document;
    d_.body.appendChild(Object.assign(d_.createElement("link"), {
        rel: "stylesheet",
        href: "//highlightjs.org/static/demo/styles/zenburn.css",
    }));

    d_.body.appendChild(Object.assign(d_.createElement("script"), {
        src: "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js",
        onload: () => {
            window.postMessage({
                command: "do_highlight",
            }, "*");
        },
    }));

    d_.body.appendChild(Object.assign(d_.createElement("script"), {
        innerHTML: `
            window.addEventListener("message", ev => {
                if (ev.source == window && ev.data && ev.data.command == "do_highlight") {
                    document.querySelectorAll('pre.code-raw > code').forEach(e => {
                        hljs.highlightBlock(e);
                    });
                }
            });
        `,
    }));
})();

きっと普通のやり方は、

質問に答える人とは?

「回答が自分のところに返ってくる」ってことも、間々あったりする :-)

質問に答える人とは? 単なる善意だけでは成り立っているとは思… - 人力検索はてな



(おしまい)

Google Maps API → OpenLayers API (V3以降)

Google Maps APIOpenLayers API に書き換えるとこうなる、という話です。

以前、こんな投稿をしたのですが、OpenLayers のバージョンは V2 です。
そのときは既に V3 が出ていましたし、この記事を書いている時点では、OpenLayersV5 が出ようか、という状況です。
というわけで、そのときの記事を OpenLayers V3 以降に対応するコードでリライトしました。
# コードは、記事を書いている時点の最新版 V4.6.5 で確認しました

では、ここから本題です。


id:ykhpno1 さんの、この質問。

その前までの一連の質問で、Google Maps API を使ってある程度の形になっていたのだけれど、アクセス数の制限があったりするから OpenStreet Map に変更したいという お話。
Google Maps API のここは、OpenLayers API ではこう書く、みたいな感じページが意外と見つからなかったので、備忘を兼ねて。

長いよ

  • まずは、ソース
  • Google Maps API vs. OpenLayers API (V3 以降)
    • (A) 地図の作成
    • (B) 地図の作成タイミング
    • (C) 地図を表示する要素との紐づけ
    • (D) 中心の位置
    • (E) スケールバー
    • (F) 良い感じにズーム
    • (G) ズームの最大値を抑制
    • (H) マーカーの作成
    • (I) マーカー画像の指定
    • (J) マーカーのツールチップ
    • (K) 吹き出しの作成
    • (L) マーカーをクリックしたときに、吹き出しの表示をトグル
    • (M) 吹き出しがマーカーを覆い隠す
    • (N) 地図のスタイル
    • (O) マーカーのクラスタリング
  • よく見かけるサンプルとの違い
  • 以前の OpenLayers V2 との比較の記事のコードから変更したところ
  • OpenLayers 2 と OpenLayers 3 以降
    • ol.Feature や ol.geom.* は、GeoJSON のオブジェクトモデルなんだ
    • 地図は、基本的に canvas に描かれる
    • Marker (ol.Feature) も、canvas に描かれるので、イベント処理は ol.Map のイベントを処理する
    • 吹き出しは、自分で DOM を用意して、ol.Overlay と紐づける
    • オブジェクトの入れ子の階層が深いけど、javascript は型チェックがないので、間違えたクラスを渡したときのエラーが分かりにくい
    • ol.style.Style のインスタンスは、キャッシュした方が良さそう
  • その他
    • 公式
    • リンク
    • 元ネタとか
    • Fiddle
続きを読む