CSS3なライブラリxcss.jsを作ってみました

デモの結果はオリジナルと同じでよく分からないかもしれませんが、CSSが違います。xcss.jsを読み込むとベンダープリフィックスは記述不要です。

つまり、どういうことかというと

.rotate10 {
  transform: rotate(-10deg);
}

CSSで書いておき、xcss.jsを読み込むと、

.rotate10 {
  -moz-transform: rotate(-10deg);
  -webkit-transform: rotate(-10deg);
  -o-transform: rotate(-10deg);
  -ms-transform: rotate(-10deg);
}

というCSSを動的に追加するライブラリです(実際はブラウザの対応状況見て追加する感じです)。

特徴

  • xcss.js読み込んだら、勝手に実行されます。
    • 全てのCSSの後にscriptタグは置いてください。
  • グローバル変数はxcssしか汚染しないです。
    • jQueryとかと共存できます。
  • セレクタの面倒は見ません。
    • 子供セレクタとか使えるようにはならないです。
  • HTMLノードを改変しません。
    • デザイン用の要素を突っ込んだりはしません。
  • document.styleSheets[N].addRuleとかで頑張って、CSSを追加します。
    • 逆にこっちをJSで弄ると干渉します。
  • CSSハックと割と共存します。
    • というか無視します。つまり、現状のウェブサイトに読み込ませたら、ベンダープリフィックスが抜けている要素も勝手に追加してくれます。

これ読みこめば、ベンダープリフィックスいらない!勝つる!って気分になります(ぇ 現行のモダンブラウザのレベルに足を引っ張っているIなんとかってブラウザを引き上げる!的なライブラリではなく、未来に登場するCSS3をフルサポートしたブラウザXのレベルに、無理することなく現行のブラウザを引き上げる感じのライブラリです。

ライブラリがやっていること

  1. ブラウザとは別の枠組みでCSSをかき集める。
    • cssTextは改変されているので。
  2. ブラウザとは別の枠組みでCSSをパースする。
    • 未知のプロパティーとかrulesに追加されていないので。
  3. サポートしていないプロパティーを変換する。
    • 変換する必要のないプロパティーは無視します。
  4. 変換したプロパティーをそのCSSの先頭に挿入する。
    • セレクタの優先順位は出来る限り壊さないようになっています。

TODO

  • @mediaとか@pageがまだ対応していないので作る。
  • jQueryプラグインとして、cssメソッド的な奴をベンダープリフィックスをつけなくても読み込めるような拡張を作る。
  • グラデーション関連が適当なので直す。

まとめ

CSSがすごくスッキリします。こういうJavaScriptすら使わない環境が登場すると楽しいでしょうね。

BigInteger作った

ちょっと使おうと思ったのだけど、負数が使えない実装が多かったりしたので、自作してみた。

四則演算しかないし、遅いので、まだ改良する予定。

使おうと思った他のライブラリのメモ。

Jimmy Walesがあまりに的確に出現するので調査した

Jimmy Walesが出現するChrome拡張に大ウケした。ニコ動とかITMediaとかいまいちなページもあるが、割と的確に挿入されるのがなんかすごい。

というわけで、さっそく解体してみた

chrome-extension://{ID}/ でChrome拡張はファイルにアクセスできるので chrome-extension://idkjdjficifbfjjkdkiimioljbloddpl/manifest.json を早速調べると、 sitenoticediv.js、 contentscript.js という二つのスクリプトで実現されていることがわかる。同様にそれぞれのファイルを覗く。

sitenoticediv.js
var getInnerHTML = function() {
    var d = Math.random();
    var str;
    if (d < 1/3) {
        : // 中略
    }
    return str;
};

ランダムで三種類のHTMLを返すgetInnerHTMLという関数が定義されているだけで、挿入位置の決定はしていない。ハズレ。

contentscript.js
// XPathResult.ORDERED_NODE_SNAPSHOT_TYPE で取得されたノード配列を返す
function getElementsByXPath(a, b)
{
    b || (b = document);
    for (var g = [], c = document.evaluate(a, b, null, 7, null), e = 0; e < c.snapshotLength; e++) {
        g.push(c.snapshotItem(e));
    }
    return g
}
var init = function ()
{
    if (!document.getElementById("siteNotice")) //< Wikipediaへの過剰挿入を避ける狙い
    {
        var a = getElementsByXPath("//div");
        if (a.length != 0) //< div要素が無いページには挿入しない
        {
            for (
                // getBoundingClientRect は要素の位置とサイズを返してくれるメソッド
                // jQuery.fn.offset の実質的な中身みたいなもの
                var b = document.body.getBoundingClientRect(),
                // 下で使っているが以下の正規表現に適合するID、クラスの要素を挿入の対象とする
                g = /(main|body|center|articles|columns|content)/i, 
                c, e = 0, h = 0;
                h < a.length;
                h++
            ) //< div要素の数だけループ
            {
                var f = a[h], d = f.getBoundingClientRect(), i = false;
                // 注目すべき要素であるか判定
                if (f.id) if (g.test(f.id)) i = true;
                if (f.className) if (g.test(f.className)) i = true;
                // 注目すべき要素の中で、
                // - bodyのサイズの中に収まっている
                // - 幅が500px以上
                // - 上から800px以内に要素上部が存在
                // - 今まで選択された条件の要素の中で最も面積が大きい
                // 要素が選択され格納される
                if (i) if (d.height * d.width > e && d.height < b.height && d.width < b.width && d.width > 500 && d.top < 800) {
                    c = f;
                    e = d.height * d.width;
                }
            }
            // 適当な要素がない場合はbody直下に挿入することに
            if (!c) {
                c = document.body;
            }
            // 要素の生成
            a = document.createElement("div");
            a.id = "siteNotice";
            a.style.zIndex = "9999";
            a.innerHTML = getInnerHTML();
            // 要素の先頭に挿入。空ならappendChild。
            b = c.childNodes;
            b.length > 0 ? c.insertBefore(a, b[0]) : c.appendChild(a)
        }
    }
};
init();

コード整形とコメントを書き加えました。全部コメントに書いてしまったが、結局、ある程度幅があって、ある程度画面の上の方に存在する要素の中で、一番大きな要素を本文が存在する要素と見なして、挿入している感じとなる。

それにしても、これだけのコードなのに中々それっぽく挿入してくるのが悔しく思う。すごいな。

Windows XPからUbuntu10.04に移って半年ぐらい経ったので良いところと悪いところをまとめてみた

表題の通り。この半年はHTML, CSS, JS, PHP, Ruby, Java辺りを書いて過ごしましたがUbuntu使って良かったところと悪かったところをまとめてみました。この記事ではOSそのものの善し悪しは置いておいて(僕はUbuntuの方が好みです)、個々のアプリケーションについて書いておきます。ちなみに長らくWindows使っていたので、環境の移行が中々できなかったというかできていない人の意見です。VMWare PlayerでWindows XP使っているけど、マシンスペックが豊かじゃない(CF-W7)から悲しい感じです。

Ubuntuの良かったアプリ

Terminal

ぶっちゃけこれのために入れたと言っても過言ではない。というかWindowsにまともに使えるこういうのが無いから困っている。

VMWare Player

WindowsUbuntu使うために入れていたときよりも快適な気がした。気がしているだけかもしれないけど。最大化すると元に戻せないときが多いのが悲しいけど、全体的に満足。

OpenOffice.org

Windowsで動かしているときよりも全体的に快適に動いてくれるような気がしました。気がしているだけの気もしますけど。

ワークスペース切替器

Ctrl+Altでデスクトップ切り替えれる奴。画面周りはWindowsよりも好きでした。

あれ? これだけ? あんまり書いていませんが、Terminalのために入れたので、これぐらいしかなかったです。

Windowsの方が良かったアプリ

萌ディタ

俺が死ね。HTML+CSS+JS+PHP+Ruby(erb)が混ぜ書きできるエディタとして使っているため、現在、移動先が無い状態。暇になったらどうにかしようと思っているのだけど、暇ができない。俺の問題です。

Internet Explorer

Windowsでしか動かないから困る。使いたくないけど、使わないといけないソフトだから困る。滅びればいいのに。

NextFTP

これと比較すると酷すぎるかもしれないけど、FFFTPよりもgFTPの出来が悪くて悲しい。ftpコマンドという発想は無い。というかそれは避けたい。

Photoshop

Wine環境でも動いたんですが、VMで動かすより重たかったです。

Adobe Reader

WindowsでPDF読むよりも重たくて難儀します。これは酷いと思いました。

GOM Player

VLCメディアプレイヤーよりも遥かに出来がいいです。VLCはflvのシークがまともにできないです。あと、再生できないのもいくつかありました。

Google日本語入力

mozcの辞書が少ないのと、なんか挙動が怪しい時があるのが悲しかったです。

JaneStyle

2chブラウザのJDじゃ代替になりませんでした。

Skype

Linux版の古さが泣けます。

iTunesEvernote

無くて困りました。

まとめ

プログラミング以外だと、Ubuntuの方がいいってことはまず無いんじゃないのかってことがわかった気がします。ウェブプログラミングもエディタの問題は個人の問題なので置いておくとして、IEというネックが存在する限り、Windowsでやる方が効率的な気がしました。

というわけですが、IEなんて愛があれば解決できるので、マルチメディア関連が強いUNIXであれば、なんら問題はないことになります。MacBook Airのお時間ですね!という冗句は置いておいて、Windows環境でターミナルの代わりになるものがあれば教えてください。と言っても、coLinuxという選択肢ぐらいしかなさそうだけど。

とりあえず、MBA買って落ち着いたら、今のマシンはWindowsに戻そうかと思います。

スクロールバーの幅を取得するコード

JavaScriptでスクロールバーの幅を取得したいと思ったのでさくっと書いてみた。

スクロールバーが表示されるiframeを生成して、offset〜を取得することで、iframeサイズとの差がスクロールバーの幅となることを利用して計算します。

IE7ではDOMの構築が終わっておらず正常に計算できませんが、僕はFxとChromeでしか使わないので、問題なしです。

function scrollBarSize() {
	var W = 1000, H = 1000;

	var iframe = document.createElement("iframe");
	    iframe.frameBorder = 0;
	    iframe.width = W;
	    iframe.height = H;

	with (iframe.style) {
		position = "absolute";
		top = "0px";
		left = "-" + (W * 2) + "px";
	}

	document.body.appendChild(iframe);
	var win = iframe.contentWindow,
	    doc = win.document;
	doc.open();
	doc.write('<!DOCTYPE html><html><head><style type="text/css">html,body,div{margin:0;padding:0;}div{width:'+(W*2)+'px;height:'+(H*2)+'px;}</style></head><body><div></div></body></html>');
	doc.close();

	var res = {
		width: W - doc.documentElement.clientHeight,
		height: H - doc.documentElement.clientWidth
	};

	document.body.removeChild(iframe);

	return res;
}

ニコニコ動画七月版プレイヤーのAPI

http://blog.nicovideo.jp/2010/07/post_257.phpで告知されていたプレイヤーのAPIを確認しました。

document.getElementById("flvplayer").ext_*()

で実行します。

ext_play(boolean)
trueなら再生。falseなら停止。
ext_setPlayheadTime(number)
number秒に頭だし。
ext_setMute(boolean)
ミュートのオンオフ。
ext_setVolume(number)
ボリューム設定(0〜100)。
ext_setCommentVisible(boolean)
コメント表示のオンオフ。
ext_setRepeat(boolean)
リピートのオンオフ。
ext_setVideoSize(string)
fitなら全画面、normalなら通常画面。
ext_isMute()
ミュート状態をbooleanで。
ext_getVolume()
ボリュームを0〜100で。
ext_isCommentVisible()
コメント表示状態をbooleanで。
ext_isRepeat()
リピート状態をbooleanで。
ext_getVideoSize()
画面の表示をfitかnormalという文字列で。
ext_getStatus()
ビデオの状況を文字列で。映像が終了していたらend、ポーズ状態ならpaused、再生中ならplaying、シーク中ならseeking、読み込み中(再生中ではない)ならload、それ以外はstoppedになります。昔は状態が少しバグっていた気がします(要確認)。
ext_getPlayheadTime()
現在の再生位置を秒単位の整数で返します。
ext_getTotalTime()
動画の長さを秒単位の整数で返します。
ext_isEditedOwnerThread()
投稿者コメントが投稿可能かどうかをbooleanで。
ext_sendLocalMessage(string, string, number)
内容、コマンド、書き込み時間でコメント投稿します。
ext_getLoadedRatio()
ダウンロードの進行状況を0〜100で返します。
ext_sendOwnerMessage(string, string, number)
内容、コマンド、書き込み時間で投稿者コメント投稿します。
ext_setInputMessage(string, string)
内容、コマンドをプレイヤーの入力枠に挿入します。
ext_getThreads(string)
動画の情報をwindow[string]という関数をコールバック引数に取って返します。
ext_getComments(string, number)
動画のコメントをwindow[string]という関数をコールバック引数に取って指定件数分返します。

なんかもっと面白いAPIがあるかと思っていた。

プレイヤーから呼び出される使えそうなコールバック

  • onNicoPlayerReady
  • setPlayerStatus
  • onNicoPlayerStatus
  • toggleMaximizePlayer

適当なラッパー

javascript:(function(){function NP(){this.fp=document.getElementById("flvplayer")}function NPG(g,s){return function(v){if(!s||v===void 0)return this.fp["ext_"+g]();this.fp["ext_"+s](v)}}NP.prototype={play:NPG("getStatus","play"),seek:NPG("getPlayheadTime","setPlayheadTime"),mute:NPG("isMute","setMute"),volume:NPG("getVolume","setVolume"),resize:NPG("getVideoSize","setVideoSize"),length:NPG("getTotalTime"),repleat:NPG("isRepeat","setRepeat"),comment:NPG("isCommentVisible","setCommentVisible"),loaded:NPG("getLoadedRatio")};this.np=new NP})();