htsign's blog

ノンジャンルで書くつもりだけど技術系が多いんじゃないかと思います

以後は特に指定のない限りJSはES6記法で書いていこうと思います。

Intlオブジェクトというものを知りました。
国際化表記における各種変換を取りまとめるそこそこ大規模なオブジェクトらしい。

Collator DateTimeFormat NumberFormatの3つのサブオブジェクトを持つ模様。
それぞれインスタンス化して使用するっぽい。

(() => {
  let localeOption = { style: "currency", currency: "jpy" };
  let locale = new Intl.NumberFormat("ja-JP", localeOption);
  console.log(locale.format(1234500)); // => ¥1,234,500
})();

便利。

第二引数のoptionにcurrencyDisplayを指定すると表記方法が変わるっぽい。
currencyDisplay: "symbol"がデフォルトで、他にcodenameがあるらしい。
symbolの場合の記号が半角とか全角とか、その辺は実装依存っぽい。

とか思ってたら

Number#toLocaleStringとか、他の代表的なオブジェクトにメソッドとして同等機能が提供されていた。
newはオーバーヘッドも大きいし*1、特別な理由がない限りは基本こっちですね。

*1:実測はしていませんが

Microsoft Edge (Windows 10 Mobile) のUser-Agent

なかなかすごいことになっています。
どこかの記事(確かスラド辺り)で読んだことありますが、WebKitと同じ挙動を示すようにしたとかなんとか。

Lumia 950で確認しました。

Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586

例えば以下のような条件判定に一致するようになります。

var ua = navigator.userAgent.toLowerCase(), cond;

cond = /android/.test(ua) && /mobile/.test(ua);
console.log("Android : " + cond); // "Android : true"

cond = /safari/.test(ua);
console.log("Safari : " + cond);  // "Safari : true"

Linux; U;が入っていないのが救いですね。
参照: 滅び行くAndroid 標準ブラウザをサポート外にして悩みの種をなくす話 - Qiita


User-Agentでブラウザの判断をせざるを得ない現状も個人的にはどうかと思います。
本当であれば機能面で分けるべきなんですよね。

console.log("Legacy IE : " + (/*@cc_on ! @*/false));

var webkitKeys = Object.keys(window).filter(function(e){
  return window.hasOwnProperty(e) && e.indexOf("webkit") !== -1;
});
console.log("WebKit : " + (webkitKeys.length > 0));

まぁこれはこれで穴がありますが…。

BookLiveで今まで使ってきた金額を出すスクリプト書いた

いやー久しぶりにJavaScript書いたわー。

(function(d){var s=d.createElement("script");s.src="//dl.dropboxusercontent.com/u/414379/www/BookLivePaid/script.js";d.body.appendChild(s)})(document)

一時期Amazon.co.jpで使った額を調べるスクリプトが流行ったことがありましたが、アレのBookLive版だと思えば大体あってます。

使い方

  1. 上のコードをコピーします。
  2. http://booklive.jp/my/top に移動してBookLiveにログインします。
    • すでにログイン済みならトップページで実行しても問題ないはず。
  3. 開発者コンソール出す。
    • IE/Firefox/Chromeなど主要ブラウザなら「F12」キーで出せます。
  4. 貼り付けてEnter。
  5. コンソールに結果が出力されます。


動作確認はIE11でしかしていません。
たぶん他でも動くと思いますが、Firefoxさん辺りは実行前に警告文出すかも。

IE/Firefox/Chromeのそれぞれ最新版で正常に動作することを確認しました。

ソース

実際に実行されるスクリプトの中身です。
呼び出すソースはDropboxにアップロードしたものですが、コードは同一です。

main();

function main() {
    var now = new Date();
    var startYear = now.getFullYear();
    var startMonth = now.getMonth() + 1;
    
    var paid = 0;
    var least = prompt("何年まで遡りますか?", startYear);
    if (!/^[0-9]{4}$/.test(least)) {
        console.warn("半角4文字の西暦で入力してください。");
        return;
    }
    
    for (var y = startYear + 1; --y >= least; ) {
        for (var m = (y === startYear ? startMonth : 12) + 1; --m > 0; ) {
            paid += monthSum(y, m);
            console.info("ここまでの累計: " + paid + "円");
        }
    }
    console.info("合計: " + paid + "円");
}

function monthSum(year, month) {
    var sum = 0;
    console.info(year + "年" + month + "月のリクエスト中...");
    var doc = request("/my/product?year=" + year + "&month=" + month);
    var nodes = doc.querySelectorAll('[id^="myproduct_display"]');
    
    if (nodes.length !== 0) {
        sum = [].slice.call(nodes)
            .map(function(e){ return e.textContent.trim(); })
            .filter(function(text){ return text.indexOf("円") === text.length - 1; })
            .map(function(price){ return parseInt(price.split(",").join("")); })
            .reduce(function(a, b){ return a + b; });
    }
    
    console.info(sum + "円");
    return sum;
}

function request(url) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, false);
    xhr.send(null);
    
    var range = document.createRange();
    return range.createContextualFragment(xhr.responseText);
}

ちなみに

私の消費金額は2013年1月から7月12日現在で654,126円らしいです。

今更Brainf*ckインタプリタ

何番煎じだよって感じのネタ。
まぁ、JavaScriptの練習ですね。

https://dl.dropboxusercontent.com/u/414379/www/brainf_ck/brainf_ckInterpreter.html

素地自体はあっさり作れたんですが、細かいところをアレも気になるコレも気になるってな感じでちょこちょこ弄っていたら、なんだかんだで3日くらい開発にかかってしまいました。

デザインには全く気を払っていないのでCSSは未使用です。


ところでイベントリスナの登録用メソッドについては、エラーハンドリングとか全然してませんしIE8以下全滅ですけど、それなりに流用できるのではないかな?と思います。
こんなの↓

HTMLElement.prototype.addEvent = function(){
    var args = Array.apply(null, arguments);
    
    switch (args.length) {
        case 1: addEventObj.call(this, args[0]); break;
        case 2:
            if (typeof args[0] === "string") {
                this.addEventListener(args[0], args[1].bind(this), false);
            }
            else {
                addEventArr.call(this, args[0], args[1]);
            }
            break;
    }
    
    function addEventObj(eventSet){
        var DELIMITER = ",";
        
        var name = "";
        var event = {};
        var namesArray = [];
        
        for (name in eventSet) {
            event = eventSet[name];
            
            if (name.indexOf(DELIMITER) !== -1) {
                namesArray = name.split(DELIMITER).map(function(e){ return e.trim() });
                addEventArr.call(this, namesArray, event);
            }
            else {
                this.addEventListener(name, event.bind(this), false);
            }
        }
    }
    function addEventArr(eventNameList, event) {
        eventNameList.forEach(function(e){
            this.addEventListener(e, event.bind(this), false);
        }, this);
    }
};

※ここではインデント浅くするためにprototypeに直接生やしてますが、元コードではObject.defineProperty使ってます。

これによって、例えば

var sample = document.getElementById("sample");

// 普通の単なるエイリアスっぽい書き方
sample.addEvent("click", function(){
    alert("hello!");
});

// 一気に複数リスナ指定
sample.addEvent(["click", "focus"], function(){
    alert("hello!");
});

// 一気に複数イベント指定
sample.addEvent({
    "click": function(){
        alert("hello!");
    },
    "focus": function(){
        alert("yeah!");
    }
});

// もちっと複雑に
sample.addEvent({
    "click": function(){
        alert("hello!");
    },
    "focus, blur": function(){
        alert("yeah!");
    }
});

みたいなコードでイベントリスナの追加ができるようになります。
あれ、それjQueryでできるんじゃね?と思ったアナタはスルドイ!!

でも最後の複雑な複数イベント登録はプラグイン無しの素のjQueryではできないと思っているんですが、どうでしょうか。実はできるのかな…。うーん。
まぁjQueryを使わないところに価値があるということで。


この記事書き始めてから思ったけど、callとかbindとか使わなくても、先頭の方でvar _this = this;とか書いておいてそれ参照すりゃ済む話ですね…。

追記 (2014/05/24 23:42)

今までIE11でしかテストしてなかったから全然気づかなかったけど、Firefox, Chromeで動かすとイベントハンドリングがうまく動いていない。
これは酷い。
でもFirefoxはともかくとしてChromeは普段使ってないからどうでもいいや。
気が向いたら修正しますが多分やりますん。

IEスキーとして一言物申したい

Web開発に必携の「Google Chrome デベロッパーツール」の便利ワザ10個まとめ*二十歳街道まっしぐら
を読んで、

うん!WebkitのDevTools便利だよね!でもそれほとんどIE11のF12 開発者ツール(以下、開発者ツール)でもできるよ!!

って言いたかった。
わざわざ対抗する意味あるのかとかそういうのは置いといて。


元記事に倣って、順に書いていきたいと思います。

1.開発者ツールのウィンドウ位置の変更

f:id:htsign:20140201220138p:plain
起動後、張り付いてる状態


f:id:htsign:20140201220539p:plain
切り離すにはここをクリック(右側配置はIEでは無理)

2.虫眼鏡で要素の選択

f:id:htsign:20140201221603p:plain
要素を選択中

要素サイズがリアルタイムで見られないのはちょい残念。
でも隣や上下の要素とのズレが見やすいのは評価してあげてもいいと思うんだ。

3.ファイルの横断検索

は無理です。


f:id:htsign:20140201222254p:plain
逐次検索はできるよ。

4.スタイルシートの有効/無効、追加/編集

f:id:htsign:20140201223405p:plain
カラーパレットは使えないので直感的ではない

使える値の候補は出てくるので、最低限の補完機能はある。

5.スマートフォンページの動作確認

これは簡単に使える。

f:id:htsign:20140201223952p:plain
ただし、モバイルのUAはデフォルトでWindows Phoneしかないので、その他を使いたい場合は適宜自分で追加する必要がある。
これが少し、いやかなり面倒。

f:id:htsign:20140201224319p:plain
カスタムUAは一度追加すれば記憶してくれるので、2度目以降は比較的楽に設定できる。
ちなみにiPadUAは初めからある。

タッチイベントのエミュレーションは試してないから知らないけど、たぶんできないんじゃないかな…。

6.読み込まれている外部ファイルを一覧表示

これはできない。
文句なしにWebkit系のDevToolsが圧倒的に便利です。

一応ネットワークタブで監視をスタートしてF5すれば、読み込まれるファイルとその中身は確認できるけど、それは他でもできるし。


ただし、JSファイルに限れば一覧できる。


f:id:htsign:20140201234312p:plain
なぜかChakraエンジン内でのみ実行されるコードも列挙される

7.圧縮されたソースコードを整形

f:id:htsign:20140201225701p:plain
before

f:id:htsign:20140201225709p:plain
after

右上の{三}みたいなところクリックすれば見やすくなる。

その右隣のabcって書かれたやつは、画面端でコードを折り返すかどうか。
見やすい方をお好みで。

8.JavaScriptデバッグする

これは余裕でできます。
というかこんな基本的な機能もないやつが開発者向けのツール名乗っちゃいかんでしょ。

f:id:htsign:20140201230711p:plain
ブレークポイント打ったり、一時停止・再開、ステップイン、ステップオーバー、ステップアウトなど、当たり前のことは当たり前にできる。


f:id:htsign:20140201231045p:plain
ウォッチ式一覧と、コールスタック、ブレークポイント

コールスタックとブレークポイントはタブ切り替え方式で、選択した方がその下に表示される。
もちろん自分でウォッチ式を追加することもできる。

9.コンソールでJavaScriptを実行

これは言わずもがな。
f:id:htsign:20140201231838p:plain
もちろんできる

ただ、IE10まではJavaScriptの補完が効かなかったので、ここに関してはやっと他ブラウザに追いついた感じ。

10.JavaScriptのパフォーマンスチェック

f:id:htsign:20140201232539p:plain
パフォーマンスの統計と


f:id:htsign:20140201232548p:plain
どの機能がどれだけ呼ばれてどれだけ時間を使ったかと


f:id:htsign:20140201232556p:plain
メモリの使用量

以上、まとめ

うーん、こうやって見ると開発者ツールって割と柔軟性がないな…。
まぁ俺はこっちのが慣れてるから好きだけどね!

あ、あと開発者ツールは完全日本語化されてるから機能の理解はしやすいと思う。
開発者ならある程度は英語読めるだろうから関係ないかもしんないけど。


エントリ執筆当初は文体の9割をパクって書いてたけど、流石にどうなの?と思ってかなり雑に書き直した。
小見出しが丸パクリなのはその名残。