Hatena::ブログ(Diary)

latest log このページをアンテナに追加 RSSフィード

2011-01-28

uu.node.add(source, context, position) のpositionに数値を指定可能に

uu.node.add(source, context, position) の position に数値を指定すると、ノードの挿入位置を指定可能になりました。従来通り文字列("first", "prev", "./first", "./last", "next", "last")も指定可能です。

詳しくはこちら http://code.google.com/p/uupaa-js/wiki/uu_node_add

<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8" />
<title>uu.node.add(NodeArray)</title>
<style>
.div1 { background-color: #111; color: white; }
.div2 { background-color: #333; color: white; }
.div3 { background-color: #555; color: white; }
#contextNode { background-color: blue; }
</style>
<script src="../../src/uupaa.js"></script>
<script>
uu.ready(function(uu, doc) {
    var nodeArray = [uu.div({ "class": "div1" }, "div1"),
                     uu.div({ "class": "div2" }, "div2"),
                     uu.div({ "class": "div3" }, "div3")];
    var ctx = uu.id("contextNode");

    var pos = [
        "first", "prev", "./first", "./last", "next", "last"
    ];

//    uu.add(nodeArray, ctx, pos[3]);
    uu.add(nodeArray, ctx, 4);
});
</script>
</head><body>

<div id="parentNode">

    <div id="firstSibling">    first(0)   </div>
    <div id="prevSibling">     prev(1)    </div>
    <ul id="contextNode">(2)
        <li id="firstChild">  ./first(.0) </li>
        <li>(.1)</li>
        <li id="lastChild">   ./last(.2)  </li>
    </ul>
    <div id="nextSibling">     next(3)    </div>
    <div id="lastSibling">     last(4)    </div>

</div>

</body></html>

2011-01-19

uu.ready("href:url/dispatcher", callback, ...) impl

条件成立でコールバックする関数を登録しておく機能 uu.ready() の条件に、ページのURLが一致する場合にコールバックする機能を追加しました。

このようにして利用します。同じものを http://jsdo.it/uupaa/2011-01-19 にあげてあります。

// jsdo.it のコードは <iframe> 内で動作するため、
// DOMContentLoaded の発火タイミングが <html> 内に設置した場合と
// 異なります。ご注意ください。
<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8" />
<script src="src/uupaa.js"></script>
<script>
uu.ready(function() {
  alert("DOMContentLoaded - this location.href = " + location.href);
});

uu.ready("href:/http://jsdo.it/nguser", function(uu, doc) {
    // この関数は指定されたURLにマッチしないためコールバックされません
    alert("NG - http://jsdo.it/nguser...");
  
}, /* 条件を省略 */ function() {
    // この関数は指定されたURLにマッチしないためコールバックされません
    // uu.ready(callback, callback, ...)のように関数を連続して記述すると、
    // 直前の条件の評価に基づいて関数を連続でコールバックします
    alert("NG - http://jsdo.it/nguser...");
  
}, "href:uupaa/2011-01-19", function(uu, doc) {
    // 最初にコールバックされます。DOMContentLoaded前に呼ばれる可能性があります
    alert("OK1 - uupaa/2011-01-19...");
  
}, "href:uupaa/2011-01-19", function(uu, doc) {
    // 2番目にコールバックされます。DOMContentLoaded前に呼ばれる可能性があります
    alert("OK2 - uupaa/2011-01-19...");
  
}, /* 条件を省略 */ function() {
    // 条件が省略されているため、直前の条件の評価に基づき、
    // この関数は3番目にコールバックされます
    alert("OK3 - uupaa/2011-01-19...");
  
}, "dom", function(uu, doc) {
    // DOMContentLoaded のタイミングでコールバックされます。
    alert("DOMReady(DOMContentLoaded)");
  
}, "window", function(uu, doc) {
    // window.onload のタイミングでコールバックされます。
    alert("WindowReady(window.onload)");
  
}, "storage", function(uu, storage) {
    // WebStorage(または互換機能)が利用可能になったタイミングでコールバックされます。
    alert("StorageReady");

}, "audio", function(uu, doc) {
    // <audio>(または互換機能)が利用可能になったタイミングでコールバックされます。
    alert("AudioReady");
  
}, "canvas", function(uu) {
    // <canvas>(または互換機能)が利用可能になったタイミングでコールバックされます。
    alert("CanvasReady");

}, "svg", function(uu) {
    // <svg>(または互換機能)が利用可能になったタイミングでコールバックされます。
    alert("SVGReady");
});
</script></head><body></body></html>

2010-10-29

IE9pp6 で -ms-transform が実装されたようなので

f:id:uupaa:20101029035908j:image

-ms-transform を使ったデモをどうぞ

http://uupaa-js.googlecode.com/svn/trunk/0.8/test/ui/gesture_drag.htm

PC, iPhone, iPad で動作します。PCなら、ホイールで拡大縮小, ホイールクリックで回転(または SHIFT + ホイールで回転), iOS なら タッチドラッグやピンチやトリプルタップで色々とサクサクできます。

まだ、縮小時に輪郭部分(ボーダー)のゴミが残ることがあるようですが、IE9pp5 + filter と比較するとレンダリング結果が改善されています。

uupaa.js なら IE6 〜 IE8 でも動くよ

uu.css.transform2d(node, param) を使うことで、CSS3 2D Transform をサポートしていないIE6〜IE8 でも CSS3 な最新ブラウザと同様のことが可能になります。

2010-10-24

イベントハンドリングなら handleEvent を使えば、Function#bind や $.proxy はたぶん要らない

タイトル変えました

uupaa.js の個々の機能をちょっとずつ紹介しています。

h2ham さんの記事を拝見して

http://h2ham.seesaa.net/article/142734325.html

uupaa.js では、 クラスオブジェクトの handleEvent にイベントを束縛できるため、

jQuery の、この(↓)ようなコードは

$(function() {
    var obj01 = {
        somevar : 'jQuery',
        doSomething : function() {
            alert(this.somevar); // alert( "jQuery" )
        }
    };
    $('button#test02').click($.proxy(obj01.doSomething, obj01)); // ココ!!
});

uupaa.js だと、この(↓)ように記述できます。

uu.ready(function(uu) {
    var obj01 = {
        somevar : 'uupaa.js',
        handleEvent: function(event) {
            alert(this.somevar); // alert( "uupaa.js" )
        }
    };
    uu('button#test02').click(obj01);  // ココ!!
});

もう一歩進んで、しっかり書くとなると、こう(↓)なるでしょうか。

uu.ready(function(uu) {

    uu.Class.singleton("Object1", {
        somevar: "uupaa.js - ClassObject",
        handleEvent: function(event) {  // ココ!!
            alert(this.somevar); // alert( "uupaa.js - ClassObject" )
        }
    });

    uu('button#test02').click(uu("Object1"));  // ココ!!
});

USE MESSAGE

イベントではなく、uupaa.js のメッセージングでこの(↓)ように代用することもできます。

# uu().post() は近々追加される予定の機能です。

<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8" />
<title></title>
<script src="uupaa.js"></script>
<script>
uu.ready(function(uu) {

    uu.Class.singleton("Object1", {
        ident: "uupaa.js - ClassObject",
        handleEvent: function(event) { // DOMイベントハンドラ
            alert(this.ident);
        },
        msgbox: function(msg, param1, param2) { // メッセージボックス(引数を2つまで渡せる, 型は自由)
            alert(this.ident);
            return "hello"; // uu.msg.send() なら値を返せる
        }
    });

    uu('button#test02').click(uu("Object1")); // クリックイベントをDOM Event経由で通知
    uu('button#test02').post(uu("Object1")); // クリックイベントをメッセージング経由で通知
});
</script>
</head><body>
<button id="test02">click me!</button>

</body></html>

handleEvent は DOM 標準の機能

handleEventDOM 標準の機能です。

例により、handleEvent によるイベントハンドリングは IE8以下で利用できないため、そのへんは uupaa.js がちょっとだけ面倒をみています。

メッセージング は uupaa.js の機能

handleEvent はそもそもイベント用なので(カスタムイベントを作れば handleEvent をイベント以外でも使えるけど)、イベント以外の通知を行うメッセージングという仕組みが uupaa.js にはあります。

uupaa.js のメッセージングは postMessage() メソッドと名前が似ていますが、ちょっと違う機能(クラスオブジェクトに、ユニ/マルチ/ブロードキャストや同期/非同期通信が可能)です。

イベントとメッセージングは責務/用途で棲み分けがされていますが、メッセージングは多機能かつ値も渡せる/返せるため、カスタムイベントで無理やりシステムっぽい事をするよりも、自然にコーディングできます。

まとめ

えーと、イベントハンドリングに関しては、Function#bind や $.proxy() でゴニョゴニョせず、 handleEvent ベースで思考すると JavaScript をもっと楽しめると思います。

IE以外ならDOM標準の機能を使うため、内部で余計なクロージャを何個も作ったりせずにすみますし、JavaScript に限らず、イベントハンドリング周りはボトルネックになりがちなので、本来はできるだけ軽く仕上げなきゃだめな部分です。

そこにクロージャーを挟むという考え方は、モバイルデバイスのUXを妨げる発想(モッサリの元)になると考えてます。

おまけ

mousemove や touchmove を $.proxy でハンドリングした場合と、uupaa.js の handleEvent でハンドリングした場合のベンチをだれかがやってくれることを期待。

2010-10-21

uu.ajax(), uu.jsonp()

uupaa.js の個々の機能をちょっとずつ紹介しています。

uu.ajax(url, option, callback) は Ajax, uu.jsonp(url, option, callback) は JSONP の機能です。

// uu.ajax - Async request
function uuajax(url,        // @param String: url
                option,     // @param Hash: { xml, data, ifmod, method, timeout,
                            //                header, binary, before, after }
                            //    option.xml     - Boolean(= false): true is xml.responseXML, false is xml.responseText
                            //    option.data    - Mix(= null): upload data
                            //    option.ifmod   - Boolean(= false): true is apply/looup "If-Modified-Since" header
                            //    option.method  - String(= "GET"): "GET", "POST", "PUT"
                            //    option.timeout - Number(= 10): timeout sec
                            //    option.header  - Hash(= {}): { key: "value", ... }
                            //    option.binary  - Boolean(= false): true is binary data
                            //    option.before  - CallbackFunction(= void): before({ option }, xhr)
                            //    option.after   - CallbackFunction(= void): after({ option, ok, rv, status }, xhr)
                callback) { // @param CallbackFunction: callback(response)
                            //    response        - Hash: { ok, rv, date, cached, option, status }
                            //    response.ok     - Boolean(= false): true is status = 20x, false is status = 30x, 40x, 50x
                            //    response.rv     - String(= null): result value. xhr.responseText or xhr.responseXML
                            //    response.date   - DateHash(= null): uu.date(If-Modified-Since) value (option.iftMode)
                            //    response.cached - Boolean(= false): true is Not Modified(xhr.status = 304)
                            //    response.option - Hash(= option): option argument
                            //    response.status - Number(= 400): xhr.status
}
// uu.jsonp - Async JSONP request
function uujsonp(url,        // @param String: "http://example.com/api?callback=@"
                 option,     // @param Hash: { timeout, method }
                             //    option.timeout - Number(= 10): timeout sec
                             //    option.method  - String(= "callback"): callback method name
                             //    option.before  - CallbackFunction(= void): before({ option }, <script>)
                             //    option.after   - CallbackFunction(= void): after({ option, ok, rv, status }, <script>)
                 callback) { // @param CallbackFunction: callback(response)
                             //    response        - Hash: { ok, rv, option, status }
                             //    response.ok     - Boolean(= false): true is status = 20x, false is status = 30x, 40x, 50x
                             //    response.rv     - Mix(= null): result value
                             //    response.option - Hash(= option): option argument
                             //    response.status - Number(= 408): 200 or 408
}

uu.ajax と uu.jsonp の第三引数は、処理完了または失敗で callback(response) の形でコールバックします。

コールバック関数に任意の値を渡す

response には option が含まれるため、uu.ajax() の第二引数(option)に何か値を渡しておくことで、callback 関数内から response.option として参照可能になります。

uu.ajax("http://example.com/api", { timeout: 60, oreore: 123 }, function(resp) {
  if (resp.ok) {
    // resp.option.oreore で参照する
    uu.puff("success oreore=@", resp.option.oreore); // alert("success oreore=123");
    uu.puff(resp.rv.length); // alert(responseText.length);
  } else {
    uu.puff("fail");
  }
});

uu.jsonp("http://example.com/jsonp?callback=@", { timeout: 60, oreore: 123 }, function(resp) {
  if (resp.ok) {
    // resp.option.oreore で参照する
    uu.puff("success oreore=@", resp.option.oreore); // alert("success oreore=123");
  } else {
    uu.puff("fail");
  }
});