JavaScript
dom
bookmarklet
es2015

jQueryに頼らない! DOM操作を伴うブックマークレットの作り方


概要


  • jQuery使わないよ

  • 基本的なDOM情報の取得・操作はJavaScriptのquerySelector querySelectorAllを使うよ

  • ネイティブのメソッド(querySelectorなど)を別の変数に入れて使おうとしたら怒られたよ

  • querySelectorで取得できるNodeListは配列ではないので、配列のメソッドで処理する時は配列化しておくと便利だよ


ブックマークレットとは


  1. ブックマークに追加

  2. 適当な名前をつけ、URLとして「javascript:」から始まるコードを保存。

  3. 任意のページで実行すると、そのスクリプトが実行できる。


ES2015

自分が使えればいいので、ブラウザ対応は考えなくて良い。

思う存分最新のJS文法で書きましょう。

(function() {

"use strict";
r();
// 実行本体
function r() {
// ここに色々書いていく
}
})();


取得→配列化

配列のメソッドを使って抽出・操作したいので、任意のDOMを取得したら即配列化します。

domArrは配列なので、.map().filter().reduce() など自由に使えます。

※callメソッドを使えばNodeListのまま関数適用は可能ですが、繰り返しメソッドを適用する場合には面倒です。

// 取得

const $dom = document.querySelectorAll('.className');

// 配列化
const domArr = [].slice.call($dom);

// スプレッド演算子を使っても良い
const domArr = [...$dom];


抽出

クラスで大まかに絞った後、「要素内のタイトルが「にゃーん」の要素だけに絞りたい」なんていうことをしないといけなかったりします。

配列のfilter、findメソッドの出番です。メソッド内で、任意の要素を取得し、そのtextContentを文字列比較して true を返すようにすれば抽出できます。

そもそも要素自体が取得できないケースもあるため、その場合はfalseを返すようにします。


filter

複数の要素を抽出する場合に使います。

const $target = domArr.filter(el => {

const $title = el.querySelector('.title');
if(!$title) { // そもそも要素が取得できないケースもあるので falseを返すようにする
return false;
}
return $title.textContent === 'にゃーん';
});

// $targetは配列なので、抽出した1つの要素を操作する場合は $target[0] でアクセスする


find

最初に見つかった1つの要素のみで良い場合は、filterよりもfindの方が向いています。

挙動・返り値が変わるだけで、条件の書き方はfilterと同じです。

つまりリファクタリングしやすい、ということ。

const $target = domArr.find(el => {

const $title = el.querySelector('.title');
if(!$title) { // そもそも要素が取得できないケースもあるので falseを返すようにする
return false;
}
return $title.textContent === 'にゃーん';
});

// $targetはDOM要素


合計する

今回はターゲットとなるカラムのアイテム1つ1つに含まれるポイント数を合計したかったので、

さくっとポイントの文字列を抽出して合計します。

// ポイントが含まれている要素を抽出

const $pointDom = $target.querySelectorAll('.point');

// 配列化
const pointDomArr = [...$pointDom];

// ポイント文字列を数値に変換しつつ抽出 → さらにundefinedなど、合計すると NaN になる要素を除外
// [1, 3, 5...] のような配列が生成される
const pointArr = pointDomArr.map(v => v.textContent * 1).filter(v => v);

// 合計
const points = pointArr.reduce((a, b) => a + b, 0);


セミコロンを忘れないこと

minifyして1行にするため、各処理の最後にセミコロンがないと意味が変わってエラーが生じてしまいます。省略しないこと。


minify

素晴らしいWebサービスが存在するので使わせていただきましょう。

エディタ上で出来るけど? という方はそれで構いません。

下記のサービスの場合、ブックマークレット化に必要な「javascript:」も補ってくれます。


備考

怒られました。


// TypeError: Illegal invocation
const qAll = document.querySelectorAll;

// これならOK
const qAll = function(selector){
return document.querySelectorAll(selector);
};


作ったもの

今回はAsanaの「DONE」とタイトルの付いたリストのポイント(スクリーンショット「2」の部分)を合計するためのブックマークレットを作りました。

日頃のタスクをちょっと便利にするブクマ、気軽に作っていきましょう〜。

スクリーンショット 2019-06-07 午後3.19.44.png