html5、CSS3、JavaScriptなどなど、Web開発者のためのフレームワーク10

それぞれ、特定の用途に特化していて、いつか使いそうなJavaScriptやCSSのフレームワークに関するメモ。

もし実際に使った感想があれば教えてください。

TimeGlider

年表という表現でいいのかな?

JSONデータからグリグリ動く年表を作るためのフレームワークです。

treesaver

デジタルカタログ風のコンテンツを作成するためのフレームワーク。

スマフォへの対応をメインにしているらしく、よくある「めくる」演出ではなくスライドでページを移動します。

LimeJS

HTML5でネイティブアプリに近いゲームを作成するためのフレームワーク。

Wink Toolkit

スマフォ対応サイトを作るためのフレームワーク。

jqTouchに近い印象。よさげなんですけど、サーバー死んでます。^^;

xui.js

HTML5に特化したjQueryみたいな感じ?

x$()という記述が、気になります。^^

Baker Ebook Framework

iPhone、iPad向けの電子書籍を作るためのフレームワーク。

サンプルはApp Storeへのリンクが貼られています。ということは…

ActiveJS

jQueryとかprototype.jsのようなJavaScriptフレームワーク。

ソースをパッと見しただけですが、これといった特徴をつかめませんでした。

RightJS

jQuery UIとかExt.jsなどのように様々なUIを簡単に実装するためのフレームワーク。

これはいいかもしれない。

EZ-CSS

CSSでレイアウトを組む際に手助けしてくれるフレームワーク。

あらかじめ用意されたレイアウトのバリエーションからクラス属性をコピペするだけで使用できるようです。

Atatonic CSS

横方向の罫線に対してきれいに揃えたいみたいなことをやってくれるCSSフレームワーク。

jQueryでドロップダウンメニューをつくるまでの4ステップ

WordPressのメニューなどを、jQueryを使ってちょっとかっこいいドロップダウンメニューにするためのメモ。

あまり凝ったデザインや演出はありませんが、実はほとんどがCSSで対処できますのでノンプログラマーの人におすすめです。

ステップ1: メニューのHTMLを準備する。

メニューのHTMLは以下のようなネストしたリストを前提としています。

<ul id="nav">
    <li><a href="a.html">製品案内</a></li>
    <li><a href="b.html">会社概要</a>
        <ul>
            <li><a href="c.html">交通アクセス</a></li>
        </ul>
    </li>
<ul>

ステップ2: CSSを準備する。

CSSは以下のような感じで。背景などの装飾は一切加えていないテンプレートのようなものです。

#nav, #nav ul
{
    margin: 0;
    padding: 0;
    list-style-type: none;
}
#nav > li
{
    float: left;
    position: relative;
    height: 40px;
    line-height: 40px;
}
#nav a
{
    display: block;
    white-space: nowrap;
}
#nav ul
{
    display: none;
    position: absolute;
    top: 40px;
    left: 0px;
    z-index: 10;
}

ステップ3: JavaScriptを用意する。

意外なことにJavaScriptは、とてもシンプル。
以下のソースを</body>の直前にコピペしてください。

jQueryはあらかじめ読んでおいてくださいね。

$('#nav > li').each(function(){
    if ($('ul', this).length) {
        $(this).addClass('has_child');
    }
    $(this).bind('mouseenter', function(){
        $('ul', this).slideDown(200);
    });
    $(this).bind('mouseleave', function(){
        $('ul', this).hide();
    });
});

ステップ4: かっこよくする。

ここから先はデザインに応じてCSSを試行錯誤することになります。

  • #navに背景を設定する。
  • #nav ulに背景を設定する。
  • a要素に背景を設定する。
  • a:hoverで背景を変える。
  • 行の高さや文字サイズ、余白などの微調整。(特に孫となるリスト要素などに注意。)
  • このJavaScriptではサブメニューがあるli要素にhas_childという値を持つクラス属性をつけていますので、たとえば三角のアイコンを設置するなどのCSSを設定する。

はい、実はステップ4が最も大変なのでした。^^

以下のようなCSSと組み合わせると幸せになれると思います。

CSS3 Fancy Menu / LavaLamp Menu

JavaScriptは苦手だけどCSSはいけるぜ!という人はぜひ挑戦を。^^

JavaScriptでsprintf

グーグル先生に聞いたらたくさん出てくるのですが、どれも多機能で私の頭にはソースが難しいので自分で作っちゃった。

ダウンロード

業界用語で言う「車輪の再発明」です。
ただし、以下のパターンのみの低機能な奴です。

使い方及び置換パターン

もっともシンプルな置換。

var str = "%sは%sで%sです。"
alert(str.sprintf('わたし', '仕事', '東京')); // わたしは仕事で東京です。

置換文字列がひとつの場合は、すべて同じ文字列で置き換えられます。

var str = "%sは%sで%sです。"
alert(str.sprintf('わたし')); // わたしはわたしでわたしです。

置換文字列が複数あって、さらに%sの数にたいして置換文字列が少ない場合は、その部分だけ置換されません。

var str = "%sは%sで%sです。"
alert(str.sprintf('わたし', '仕事')); // わたしは仕事で%sです。

プレースホルダーも使用できます。

var str = "%1$sは%3$sで%2$sです。"
alert(str.sprintf('わたし', '仕事', '東京')); // わたしは東京で仕事です。

ソース

String.prototype.sprintf = function()
{
    var str = this + '';
    var args = Array.prototype.slice.call(arguments);

    var ph = true;
    if (str.indexOf('%s', 0) != -1) {
        ph = false;
    }

    if (args.length === 1) {
        if (ph) {
            return str.replace(/%1$s/g, args[0]);
        } else {
            return str.replace(/%s/g, args[0]);
        }
    } else {
        for (var i=0; i<args.length; i++) {
            var n = i + 1;
            if (ph) {
                str = str.replace('%'+n+'$s', args[i]);
            } else {
                str = str.replace('%s', args[i]);
            }
        }
    }
    return str;
}

JavaScript+jQueryでソートいろいろ

先ほど、アップデートしたchromeの拡張機能の中でXMLのノードのソートや、大文字小文字を区別しないソートなどをする必要があって、意外と簡単だったんだけど、いちおうメモ。

DOMノードのソート

XMLのDOM要素を、その子ノードの値の文字列順でソートする。
(大文字小文字は無視する。)

以下は、<bookmark>要素の中の<title>要素の値で、<bookmark>要素を並べ替えする。

var bookmarks = $('bookmark', data).sort(function(a, b){
    a = $('title', a).text().toLowerCase();
    b = $('title', b).text().toLowerCase();
    if(a > b)  return 1;
    if(a < b)  return -1;
    return 0;
});

jQueryを使っているので、シンプル。

当然HTMLでも同じなので、tableなどのソートは意外と楽かも。

大文字小文字を無視した文字列のソート

単純に sort() としてしまうと、[A, B, a, b] みたいになってしまうので、以下のようにする。

strings = strings.sort(function(a,b){
    a = a.toString().toLowerCase();
    b = b.toString().toLowerCase();
    if(a > b)  return 1;
    if(a < b)  return -1;
    return 0;
});

以上で、[A, a, b, B] みたいになる。
ただし、Aとaの並び順はこれだけでは、コントロール出来ない。

Google MAPS API v3でdistanceFrom(二点間の距離を求める)

Google MAPS API V3では、V2で実装されていた二点間の距離を計算するためのメソッドdistanceFrom()が実装されていない。

そこで、Google MAPS API v3に、distanceFrom()を実装するためのソース。

以下のソースをJavaScript内にコピペ。

google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
   var lat1 = this.lat();
   var radianLat1 = lat1 * ( Math.PI  / 180 );
   var lng1 = this.lng();
   var radianLng1 = lng1 * ( Math.PI  / 180 );
   var lat2 = newLatLng.lat();
   var radianLat2 = lat2 * ( Math.PI  / 180 );
   var lng2 = newLatLng.lng();
   var radianLng2 = lng2 * ( Math.PI  / 180 );
   var earth_radius = 6378.1;
   var diffLat =  ( radianLat1 - radianLat2 );
   var diffLng =  ( radianLng1 - radianLng2 );
   var sinLat = Math.sin( diffLat / 2  );
   var sinLng = Math.sin( diffLng / 2  );
   var a = Math.pow(sinLat, 2.0) + Math.cos(radianLat1) * Math.cos(radianLat2) * Math.pow(sinLng, 2.0);
   var distance = earth_radius * 2 * Math.asin(Math.min(1, Math.sqrt(a)));
   return distance;
}

以上で以下のようにpoint0とpoint1の距離が求められる。と思う。

var distance = point0.distanceFrom(point1);

point0とpoint1は、google.maps.LatLngオブジェクトである必要があります。

計算式そのものは、もう、わけわかんないので、間違ってたら教えてください。

JavaScript でカウントダウン

特定の日時までのカウントダウンをリアルタイムに表示する JavaScript のクラスを作った。

サンプル – JavaScript によるカウントダウン

サンプルのソース

<div id="countdown">
    <div><span id="time">2011/01/01</span> まで</div>
    <div id="timer"></div>
</div><!--end #countdown-->
 --中略--
<script type="text/javascript">
var datetime = document.getElementById('time').childNodes[0].nodeValue;
var cd = new countDown(datetime);
cd.message = 'あけおめ!';
cd.display('timer');
</script>
  1. var cd = new countDown() で日時を渡して cd オブジェクトを生成。
  2. cd.message プロパティにカウントダウン終了時のメッセージを設定。
  3. cd.display() メソッドで、タイマーを挿入したい要素の ID 属性を指定。
  4. タイマーの数値に指定された、counter というクラス属性に対して、CSS で文字サイズを拡大。

countdown.class.js のソース

countDown クラスのソースは以下のとおり。 (ダウンロードはこちら

適当にカスタマイズしてご利用下さい。

function countDown(time) {
    var day = new Date(time);
    this.period = day.getTime();
}

countDown.prototype.message = '終了しました!';

countDown.prototype.display = function(ele){
    this.obj = document.getElementById(ele);
    this._getCounter(this);
}

countDown.prototype._getCounter = function(_this){
    var timer = setTimeout(function(){_this._getCounter(_this);}, 1000);

    var now = new Date();
    var total = parseInt((this.period - now.getTime()) / 1000);
    if (0 >= parseInt(total)) {
        _this.obj.innerHTML = _this.message;
        clearTimeout(timer);
        return;
    }
    var sec = total % 60;
    var min = ((total - sec) % 3600) / 60;
    var hour = (total - min * 60 - sec) / 3600;

    _this.obj.innerHTML = '';

    var data = {
        '時間': hour,
        '分':   min,
        '秒':   sec
    };

    for (var i in data) {
        var node = document.createElement('span');
        node.className = 'counter';
        var value = document.createTextNode(data[i]);
        node.appendChild(value);
        _this.obj.appendChild(node);
        _this.obj.appendChild(document.createTextNode(i));
    }
}

setTImeout() のあたりが、いまいちエレガントじゃない気がする。ていうかよくわからん。

JavaScriptでHTMLエスケープ

昨日、公開した WordPress プラグイン “mce_preformatted” は、整形済みテキストを本文に挿入するために、 textarea 内に入力されたテキストの HTML エスケープを行っている。

通常、HTML のエスケープには正規表現を使用するが、このプラグインでは違うアプローチで HTML をエスケープしている。

通常の方法

以下は正規表現を使用した方法。

function htmlEscape(s){
	s=s.replace(/&/g,'&amp;');
	s=s.replace(/>/g,'&gt;');
	s=s.replace(/</g,'&lt;');
	return s;
}

今回使用した方法

obj.innerText (Firefox では obj.textContent)を使用した方法。

function htmlEscape(s){
    var obj = document.createElement('pre');
    if (typeof obj.textContent != 'undefined') {
        obj.textContent = s;
    } else {
        obj.innerText = s;
    }
    return obj.innerHTML;
}

結果は全く同じ。
たいした根拠はないのだが、正規表現よりもエコな気がするんだけど、どうなんだろう?

String 型のメソッドとして登録する

以下のようにすると、さらにエレガントかもしれない。

String.prototype.htmlEscape = function(){
    var obj = document.createElement('pre');
    if (typeof obj.textContent != 'undefined') {
        obj.textContent = this;
    } else {
        obj.innerText = this;
    }
    return obj.innerHTML;
}

こうしておくと、以下のように書けるので、ちょっとだけかっこいい。

var str = '<strong>Cool!</strong>';
alert(str.htmlEscape());

JavaScriptでUTCからローカル時間に変換

JavaScript で任意の日付をUTCとみなして、ローカル時間に変換するメソッドを作った。(ってほどでもないけど。。。)

せっかくなので、Date オブジェクトのメソッドとしてコール可能なようにした。

ソース

以下のソースを適当にコピペしてご利用下さい。

Date.prototype.utc2local = function()
{
    this.setTime(
        this.getTime()-(this.getTimezoneOffset()*60*1000)
    );
}

使い方

以下のような感じで。

Date.utc2local() を実行した後は、Date オブジェクトにセットされている時間が UTC になります。

var d = new Date('2010/9/1 00:00:00'); // UTCの日時
d.utc2local();
alert(d.getHours()); // ローカルな時間

ページのタイトルを取得するブックマークレット

こんなものは、たくさんあると思うのですが。。。

表示されているページにリンクを貼るためのHTMLを取得するためのブックマークレット。

リンクを取得する

上記のリンクをブックマークバーあるいは右クリックでお気に入りに追加しておけば、任意のページへリンクを貼るためのHTMLが入力されたTEXTAREAがページの右上に表示される。

ちなみにブックマークレットのソースは以下。

ソースをダウンロード

その他

こういう方法もある。

innerHTMLとremoveChild()

IEとfirefoxでinnerHTMLとremoveChildを使用した際の挙動が違っていたのでメモ。

以下のソースは、DIV要素を作成してoBodyオブジェクトに挿入した後で、oBodyの中身を空にする処理を行っている。(実際にはこんなことありませんが。。。)

var oDiv = document.createElement('DIV');
oDiv.innerHTML = 'おはよう';
oBody.insertBefore(oDiv, null);
oBody.innerHTML = '';
alert(oDiv.innerHTML); // IEでは何も出ない

この処理の後、firefoxではoDivはまだDIV要素として存在しているが、IEでは空のオブジェクトになってしまう。

一方で、oBody.innerHTMLの行を以下のように変更してやると、IEでもoDivオブジェクトの値が残る。

var oDiv = document.createElement('DIV');
oDiv.innerHTML = 'おはよう';
oBody.insertBefore(oDiv, null);
oBody.removeChild(oBody.firstChild);
alert(oDiv.innerHTML); // おはよう

意味分かりにくいですよね?

とにかく、ある要素の中身を空にしたい場合は、inerHTML = ”みたいな安易な方法を使うよりも、まじめにremoveChild()を使用した方がいいということです。