※スマホ対応はしてません。

カテゴリー: Web

@ ts-checkを付けると、VS Codeが普通のJavaScriptもTypeScript扱いで見てくれるんだって。

カテゴリー: JavaScript

// @ts-check を書くと、JSファイルでもTSとしてvalidateしてくれるそうです。

(@tsのひとごめん。)

DOMノードどーすんの問題

引数もらって計算して結果を返すだけの関数ってならこれすげー便利で良いんだけど、 querySelector() 使うと対応が面倒な感じになる。これどうしたら良いかなあ。というかTSでもよく分からないや……。

const input = document.querySelecter('input#the-input');
console.log(input!.value); // -> Property 'value' does not exist on type 'Element'.

querySelecter() が返すのは Element 型なので、 <input> 用のプロパティが定義されていない。

一応、解決策としては instanceof で確認してやることで型が固定します。

const input = document.querySelecter('input#the-input');
if (!(input instanceof HTMLInputElement)) { return; }
console.log(input!.value);

ついでに null チェックもできて一石二鳥ではある。

JSじゃなくてTSの場合はジェネリクス <T> で書ける。

const input = document.querySelector<HTMLInputElement>('input#the-input')!;
input.value = 'Hello World!';

ただしこの場合は null の確認が必要。(これ↑は ! ですっ飛ばした。)

なんかもっと楽々書けないかなあ。そもそもReactやVueが全盛期の現代で querySelector() 自体をあんまり使わないか……。

DevToolsでz-index一覧できるやつ作ったよ。

カテゴリー: JavaScript

Chrome用とFirefox用です。

Download from Chrome Web Store Download Firefox add-ons

GitHubでソースコード公開してます。

見た目

Chrome版。

Firefox版はサブペインじゃなくてパネルとして追加するのでちょっとアレです。仕方なかった。

はじまり

コードスニペット版。これはこれで手軽でよろしいね。

Chrome版について

Elementsパネル内に “z-index” ペインを追加し、一覧を表示します。セレクターをクリックすると要素を選択するので、スタイルの詳細を確認できます。

ツールバーに追加されるアイコンはいらないので、右クリックから非表示にするのが良いと思います。

最初から出さないやり方もあるのかな。

Firefox版について

DevToolsに “z-index” パネルを追加し、一覧を表示します。セレクターをクリックするとInspector (Elements) パネルへ移動し要素を選択するので、スタイルの詳細を確認できます。たまに時間がかかることがあるけどよくわからない。

パネル vs ペイン

本当はChrome同様Elementsパネル内に表示したかったけど、できなかったので独立パネルになってます。

できなかった理由は二つあって、まず第一にペインにHTMLを追加するAPI setPage() がなかったこと。自由な項目が設置できない。

第二には、でもまあ見た目はアレだけどあんま気にしないにしよう思って、オブジェクトを表示する setExpression() を試した。ところが、これなんか中身が長いときにはみ出してスクロールもしないので、上位数件しか見えないっていう……。

setExpression() で出力した例。スクロールせず、全体を見ることができない。

何か良いやり方があれば教えてください。

今後の予定

更新の予定はないけど、脳内の構想としてはこんな感じ。

  • 要素をセレクターだけで検索するので、同じセレクターが複数あるとき選択が不正確なのを修正
  • スタックコンテキストとかも表示
  • style 属性で指定されている場合セレクターに反映
  • その場で z-index を更新してプレビュー(ElementsパネルのStylesペインみたいな)
  • アイコンとかそこら辺をアレする

気が向いたらやる感じです。欲しい機能あれば言ってくれると気が向いてくるかもしれません。

z-indexを減らそう!

ちゃんと設計してれば2桁もあれば相当余るはずなので、むやみに z-index: 999999 とか z-index: 2147483647 とかやめましょう。

よしCodeGridを読もう!

あとGitHubのほうでスターください!

ブラウザー拡張(アドオン、エクステンション)の作り方チュートリアル。

カテゴリー: JavaScript

思うところあって今後ちゃんと形にしようと思っているんだけど、その前に下書きというか叩き台くらいの感じで一度世に出してみます。

概要

  • すごいかんたん!
  • ビルドシステム類のない牧歌的構成でもいける
  • API互換性はそこそこ。ポリフィル入れてFirefoxに寄せて作るのが吉か
  • Edgeは闇を感じた
  • Safariは未調査

基本的な作り方

  1. フォルダを作る
  2. manifest.json を用意
  3. それに合わせて各種スクリプト等を用意
  4. ブラウザーで開発中のものを読み込み開発
  5. 公開

動く場所

  • ツールバーのボタン
  • 任意のサイト内
  • バックグラウンド
  • 独自ページ

他に開発者ツールにタブを追加したり、Firefoxならサイドバーを作ったりすることもできます。

できること

拡張用のAPIがいっぱいあるのでそれらを駆使する。

もちろん普通のウェブ開発の知見も再利用できるよ。

最新のJavaScriptを書ける

IE対応の必要がない(し、たぶんEdgeも無視されるだろう)ので、Chromeだけ、あるいはChromeとFirefoxだけが対象になります。すると最新のJavaScriptの書き方をがんがん使えます。

class とか async/await とか、関数引数の初期値とか分割代入とか。

そこら辺の勉強を兼ねて挑戦してみるのはきっと良い選択だと思います。

Hello Worldをインストールしてみる

最初のブラウザー拡張を自作するまえに、一度サンプルをインストールしてみましょう。どうせ自作したらやる作業です。

(さらに…)

Chrome、Edge、Firefox互換のブラウザー拡張を作るポリフィル。

カテゴリー: JavaScript

最近思うところあってブラウザー拡張を作って公開しました。(Macが対応していない絵文字を使っているので、変に見えます。いずれどうにかする。) 仕事中についSNS見ちゃうのを止めるやつです。

スイッチオンにしてTwitterとかを開くと止められます。

作ったものについてはそのうち記事に書きたいと思ってます。あとブラウザー拡張の作り方についてもちゃんとした形にしたいなと思って準備中。

それはそれとして、作成中に得た知見のひとつ、互換性についてです。

先にまとめ

  • ポリフィル使えばすぐコード共通化できるしPromise化する
  • 共通化したコードはFirefoxに寄る
  • Edgeはもうひと手間
  • async/await はいいぞ

互換性

前提として、ブラウザー搭載のAPIは以下のような感じ。

  • Chromeは chrome オブジェクト以下にAPIを持つ
  • Firefoxは chrome 、Edgeは browser にChrome互換APIを持つ
  • Chrome互換APIは、コールバックは引数に与える

Firefoxは互換APIに加えて別にAPIがあります。

  • Firefoxは browser にChromeのAPIと同機能だが別I/FのAPIを持つ
  • Firefox独自APIはPromise化されている
  • async/await を利用できる
  • 後述のポリフィルで、ChromeとEdgeでもいける(いえーい)

つまりどのブラウザーでもだいたい同じ機能がそろってるけど、インターフェイスがちょっと違うよと。表にまとめるとこんな感じ。

ブラウザー chrome browser ポリフィル
Chrome ◎ ✘ 〇
Edge ✘ △ 〇
Firefox 〇 ◎

Promiseだと嬉しいって話

「ちょっと違うインターフェイス」の差はPromise化されているかどうかです。なので共通化する場合は、全部Promise化するか、逆に全部Promiseを剥がすかのどちらかになるわけですが、前者Promise化する方をお勧めします。というわけでその理由なんですけれども。

コールバック関数方式

まずこちらの例。Chrome互換APIで、保存した情報を持ってくるやつです。

chrome.storage.local.get(["item1", "item2"], (result) => {
  console.log('# result', result.item1, result.item2);
});

まあこれはこれで問題ないんだけど。

Promise方式

一方FirefoxがChrome互換APIとは別に独自に持っている browser 系APIだと、これがPromiseになる。(「にもなる」の方が正しいかも。)

browser.storage.local.get(["item1", "item2"]).then((result) => {
  console.log('# result', result.item1, result.item2);
});

これだけだと、まああんまり変わらないように見える。

いちおうメリットとして、Promiseを使うと非同期処理を連結してもコードのインデントが深くならないというものががあります。が、そんなものより、ES2017で導入された async/await を利用できる面が大きい。

async/await

前述のPromiseを使ったコードは、( async な関数の中で)以下のように書ける。

const result = await browser.storage.local.get(["item1", "item2"]);
console.log('# result', result.item1, result.item2);

まっすぐ書けるのでたいそう見やすい。

どうすか

Promiseの方が良くないすか?

APIをPromise化するライブラリ

というわけでPromise化したくなりましたか? なりましたね? なったので、これ↓を導入して実現します。

残念ながらライブラリのファイルが単体で公開されていないようです。ビルドシステムを導入していない場合でも、一度npmでインストールしてからファイルをコピーしてきます。

$ npm install webextension-polyfill
$ cp node_modules/webextension-polyfill/dist/browser-polyfill.min.js .

でもって読み込むようにする。

<script src="/browser-polyfill.min.js"></script>
<script src="/popup.js"></script>

これでChromeでも browser を使って、 async/await 記法でさらさら書けるようになります。やったー!

Edge対応

最終的にできあがったのはこれ↓

ライブラリを有効化する

件のライブラリは現状ではEdgeに対応しておらず、検討中みたい。

詳細省略するけど、ライブラリ読み込み前にこれ↓を実行したらEdgeもうまいこといった。

// ※別途に `cloneDeep()` 的なものをご用意ください
"use strict";

// "SCRIPT5045: Assignment to read-only properties is not allowed in strict mode" を避ける
try {
  if (window.browser) {
    browser.storage.local.get = browser.storage.local.get;
  }
} catch (error) {
  // 上書きできるようにする
  window.chrome = cloneDeep(window.browser);

  // Chrome偽装
  window.browser = undefined;
}

openOptionsPage()

他に、自分の見つけた範囲だと chrome.runtime.openOptionsPage() が実装されていないようなので、自前でpolyfillを実装した。他にもそういうのありそう。

window.chrome.runtime.openOptionsPage = () => {
  const { options_page } = browser.runtime.getManifest();
  browser.tabs.create({
    url: `/${options_page}`,
  });
};

manifest.json の互換性

今回特につまづかなかったけど、いちおうブラウザーによって必須だったり名前が違ったりするところがある。

一覧

options_ui

Chromeでは chrome_style: true が推奨。Edgeでは options_page になる。

{
…
  "options_page": "options_ui/index.html",
  "options_ui": {
    "page": "options_ui/index.html",
    "chrome_style": true
  }
}

あとFirefoxでも browser_style: true が推奨だけど、初期値がそうなっているので記述しなくてもいい。

APIの互換性

ライブラリがあるとは言ってももともと実装されていないものはされていないのであきらめる。

MDNの互換性の表を見るのが良さそう。

例えば先ほどの runtime.openOptions() は、やっぱり対応してなかった。

その他

  • Firefoxの chrome オブジェクトについての記述がMDNで見当たらなかった
  • Firefoxの browser でもChrome互換APIと同様にコールバックを引数に与えられるっぽい。でもMDNでの記述は見当たらなかった
  • Edgeは全く関係ない chrome オブジェクトを持っているっぽいけど詳細不明
  • ブラウザー拡張の標準化がW3Cで進行中 → Browser Extensions
  • 標準化されたAPIはPromise化されている(つまりFirefox風)
  • Chromeは標準APIに寄せる気がないらしい[要出典]
  • EdgeはChromeだけを見ているらしい[要出典]
  • Edge拡張を作るのは簡単だけど、公開するの難しそうでつらい

おしまい

async/await いいわー。

更新履歴

2018-04-24

  • Edge対応コードの "use strict" がなんか抜けてたのを修正
  • Edge対応コード完成版のリンクを追加
  • APIの互換性について追加

Nuxt.js他で時計アプリ (PWA) を作ってみたよ。

カテゴリー: JavaScript

ええいや時計って……という感じはあるんだけど、とにかくNuxt.jsを使ってみたかったのです。あと自分では使う。

できあがったもの

アナログ時計が左に、デジタル時計が右に。あとポモドーロタイマー付き。

使った技術

ライブラリ、フレームワーク

ツール

ウェブ標準API

サービス

技術系感想

Nuxt.js

この記事の影響。

なんか久しぶりに「動くものがさくさく作れる」という快感を味わうことができたフレームワーク。Ruby on Railsにこなれてきた頃の快感を思い出しました。

vue-cli使って入れたんだけど、最初からディレクトリとか開発用サーバーとか、各種ビルドとか即時部分更新 (HMR) とか、追加のあれこれなしに書くだけですぐ動く。黒魔術的な感じなのもRailsっぽい。いや別にRailsと比べるものじゃないんだけど。

今回は静的HTML (SSR) でやったけど、そのうち動的なやつもやってみたい。Firebaseでホストすればできると聞いたような気がする? 未調査。別に # なURLでも構わないけども。

vue-cilで入れるやつのコマンド(公式ドキュメントより):

$ npx vue-cli init nuxt-community/starter-template my-project

Nuxt + PWA

こいつを yarn add するだけでわりとすぐ動いた。お手軽便利。これを導入するだけで用が済んでしまったので、ServiceWorkerも自前では書いてないです。

ドキュメントはあんまり親切じゃない感じがする。まだ使い方とかがあんまりわかってない。

Visual Studio Code

ずっとVimを使ってきたんだけど(最近はNeoVim)、ちょっと人に教えるのにこれはあれだよなーと思って「普通のエディター」として使い始めてみました。あらでも良いじゃない。

スクリーンショット。公式サイトから。

後発なうえに開発体制が盤石なだけあって、さすがに出来が良い。各種OSに対応している点、インストールしてすぐ使える点、プラグインが豊富かつ導入や管理も楽な点、日本語対応している点から、今後は人様にお勧めしていこうかなと思っております。

最初に導入してほしいプラグイン:

  • Code Spell Checker
  • EditorConfig
  • ESLint(JS系のひと向け)

ただ、スクロールがなかなかちょっと。これはCodeじゃなくてたぶんElectron for Windowsの問題で、Slack.exeなんかでも起こる。どうも onscroll で何かやってるとうまくスクロールが動かなくなるみたい。詳細未調査だけど、たしか自分が作ったアプリだとそんな感じだった。まあだいたいの人はMacだから問題ないね……。

あとVimプラグインはキー操作が衝突するんで、案の定アレでした。

CSS Grid

何度か使ったことあったかな。気がつけば一通りのブラウザサポートが揃っていたので。

CSS Gridは全てのモダンブラウザで動作する。画像はgrid-templateプロパティの場合。

今回複雑なレイアウトをしてはいないけれども、別にそんじょそこらの細かいところでも割と気軽に使えるので、今後はがしがし使って行きたい。

今回使ったのは右側半分。”T”の字に区切ってます。

GitHub Pages + Cloudflare

今回は全部静的ファイルなので、GitHub Pagesで公開してCloudflareでhttps化。

これも簡単にできて楽だったので、今後は同じようにサブドメインにどんどん生やしていく感じで色々作っていこうかなと思いました。

作業内容はこれ↓。

yarn

普段はnpmの方を使っているんだけど、今回はなんとなくこっちに。インストールが早いとかは聞いてるけれども、うーん特に不満はないけど利点を感じるほどでもなかった。npmも今はロックファイルあるし、普通にインストールしたら記録されるしなあ。

アプリの紹介

時計です。

ポモドーロのタイマー付きです。

おしまい

楽しかった。