hogashi.*

日記から何から

querySelectorAllの結果をmapしたいときはArray.fromすると良い

 こんにちは〜 はてなエンジニア - Qiita Advent Calendar 2024 - Qiita の 1日目です。

querySelectorAllの結果をmapしたいとき

 JavaScript で、 Document: querySelectorAll() メソッド の結果を map したいことがある。が、そのままだと map できない。
 Chrome の devtools で試すとこう↓。 map は関数ではないです、というエラーになっている。

document.querySelectorAll('div').map(div => div.innerText)
// Uncaught TypeError: document.querySelectorAll(...).map is not a function
//    at <anonymous>:1:34
querySelectorAllの結果をそのままmapしようとしてエラーになっている様子

 map するには、 Array.from() を使って、 Array インスタンスにしてあげると良い。

Array.from(document.querySelectorAll('div')).map(div => div.innerText)
//=> ['hoge', ...] (innerText が入った配列が返ってくる)
querySelectorAllの結果をArray.fromしたのでmapできる様子

くわしく

 querySelectorAll の戻り値は NodeList というオブジェクト。

DocumentquerySelectorAll() メソッドは、指定された CSS セレクターに一致する文書中の要素のリストを示す静的な(生きていない)NodeList を返します。

https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll

 NodeList に map メソッドが存在しないので、そのまま map しようとすると冒頭のエラーになる。 MDN の NodeList のページには、まさに Array.from を使うといい、と書かれている。

メモ: NodeListArray とは異なりますが、forEach() メソッドで処理を反復適用することは可能です。Array.from() を使うことで Array に変換することができます。

https://developer.mozilla.org/ja/docs/Web/API/NodeList
ちなみに"静的な(生きていない)NodeList"とは

 生きた NodeList と生きていない NodeList というのは、 DOM の変化に応じて、自動的に更新されるかどうか、という話題。 NodeList - Web API | MDN に詳しい。
 querySelectorAll の戻り値は生きていないほうなので、取得して変数に格納したオブジェクトの内容が変化しない。逆に、 Node: childNodes プロパティ は生きた NodeList なので、 DOM が変化すると、その内容も変わりうる。

 試しに、 body タグの childNodes を変数に格納してから、 body タグに div タグをひとつ増やしてみた。変数に格納しておいたオブジェクトが変化していることがわかる。

child = document.body.childNodes
//=> NodeList(5) [script, div#root, script#hydration, div#a11y-status-message, div.ReactModalPortal]
document.body.insertAdjacentHTML('beforeend', '<div>hello!</div>')
//=> undefined
child
//=> NodeList(6) [script, div#root, script#hydration, div#a11y-status-message, div.ReactModalPortal, div]
childNodes(を変数に格納したオブジェクト)が変化している様子

 querySelectorAll に似たメソッド群で Document: getElementsByClassName() メソッド などは、生きた HTMLCollection が戻り値になっている。 querySelectorAll と同じ気持ちでコードを書いているとハマることがありそう……。

list = document.getElementsByClassName('browsers')
//=> HTMLCollection [div.browsers]
document.body.insertAdjacentHTML('beforeend', '<div class="browsers">Hi!</div>')
//=> undefined
list
//=> HTMLCollection(2) [div.browsers, div.browsers]
getElementsByClassNameの結果(を変数に格納したオブジェクト)が変化している様子

拡張機能「twitter画像原寸ボタン」v7.1.0公開

 拡張機能twitter画像原寸ボタン」v7.1.0 を公開しました。主に依存パッケージとパッケージマネージャの更新のみで、機能に変化はありません。細かいところでは、ポップアップの設定画面の保存ボタンのテキストが折り返すことがあったので広めにしました。

 インストールはこちら:

Google Chrome
chromewebstore.google.com

Microsoft Edge
microsoftedge.microsoft.com

shufコマンドがないときに同じことをするシェルスクリプト

 shuf コマンドとは、入力の行をシャッフルして出力するコマンド。 shuf invocation (GNU Coreutils 9.5)

 手元の環境に入ってなかったので、こういうのを書いてみた。 Bash で試しています。オプションとかは実装してません。

function shuf() {
  OLD_IFS=$IFS
  IFS=$'\n'
  (
    for line in $(
      if [ -n "$1" ]; then
        cat "$1"
      else
        cat /dev/stdin
      fi
    ); do
      echo "$RANDOM"$'\t'"$line"
    done
  ) | sort -n | cut -f2-
  IFS=$OLD_IFS
}

 こう使える。哲学者の例文は 食事する哲学者の問題 - 診断メーカー から。

$ echo {A..G} | tr ' ' '\n' | shuf
C
A
B
E
G
D
F
$ shuf shokuji.txt
ニーチェが右のフォークを置く
ニーチェが右のフォークを取る
プラトンがルソーを殴る
ルソーがニーチェを殴る
ソクラテスが素手で食べ始める

 パイプとかリダイレクトって普段何気なくやっているけど、そういえば標準入力で流し込まれる側って、どうやってその内容取るんだっけ……? となって面白かった。 Redirections (Bash Reference Manual) を見ると、標準入力は /dev/stdin から取れることがわかる。

 $RANDOMBash のシェル変数で、参照するたびに 0 〜 32767 のランダムな整数が展開される https://www.gnu.org/software/bash/manual/bash.html#index-RANDOM

 $IFS もシェル変数で、フィールドの区切り文字の列 https://www.gnu.org/software/bash/manual/bash.html#index-IFS 。これを一時的に改行文字のみに変えることで、 for で変数に入る区切りを 1行ごとにする (これをしないと、 for で空白文字とかで区切られてしまって、行の途中までで別の行になったりしてしまう……)。 $OLD_IFS に逃がしておく技は、過去に whichコマンドを読んだ - hogashi.* で見たやつ。

progress要素でモアイまわしができる

 progress 要素で遊ぶシリーズ。

 まず普通に x と y を追従するようなものをつくるとこう。 Glitch で遊んでたのをここにコピペしてるのでなんか変かも。

 x と y を入れ替えると、もう奇妙な感覚になる。

 つまりこれをうまく使って遊べそう → これモアイまわしじゃん、ということに気づいたのだった。

300x300で, x と y は...

 やっぱり座標が変そうなので Glitch 版も貼っておきます。

 GIF で貼っておくと、こういう動きをするはず。

クリア表示もあります

 追記: もちろん progress 要素じゃなくてもよくて、月とかでもよい。こっちのほうが回転の様子とかはわかりやすい。

 MDN <progress>: The Progress Indicator element - HTML: HyperText Markup Language | MDN を見ていたら、 ::-webkit-progress-bar みたいな疑似要素があって、色とかを変えられるようだった。 ::-webkit-... のほうしか指定してないので Chrome 系じゃないと色が変わらないかも。

 あと MDN 見てると meter 要素 <meter>: The HTML Meter element - HTML: HyperText Markup Language | MDN というのもあって、今回みたいな用途だったら meter 要素のほうが比較的あっている?かも? しかしモアイの回転度が進捗かというとそんな気もする。

 本家モアイまわしはこちら。子どものころから大好きなゲームです。
www.skt-products.com

progress要素並べまくるとスペクトラムアナライザみたいな表示ができる

 progress 要素はこういうやつ <progress>: 進捗インジケーター要素 - HTML: ハイパーテキストマークアップ言語 | MDN

 並べまくるとこうなる。 DOM なのでたぶん遅そう。

 値はランダムなだけだけど、こういう音楽といっしょに楽しめる。
www.youtube.com

会話日記

 実家に帰って親と会話していて 2時間くらい経っていた。いろんな話題があったけど、その中で、常々頭の中にはあった考えを即興で言葉に起こして流れをもって伝える、という場面がお互いにたくさんあった。喋りながら、これはブログだなと思って、あまりしっかり推敲しない、構成とかもなんとなくの文章を、なんとなく読んでもらい、返信をもらって(細かい相槌はあるが)、今まであった思考が半ば無理やり形に落ち着いて、なんとなくそうかなと思っていたこととかの結論が(選択肢としていくつかある、という形ででも)出たのが嬉しい状態。