Created
March 22, 2011 22:19
-
-
Save ne-sachirou/882213 to your computer and use it in GitHub Desktop.
#js 舊字←→新字変換ライブラリ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* convApp.js 20110203 | |
* 正字俗字変換エンジン | |
* ne_Sachirou [email protected] | |
* | |
* ==History | |
* 0.1 http://d.hatena.ne.jp/Kureduki_Maari/20090519/1242715608 | |
* 0.2 http://d.hatena.ne.jp/Kureduki_Maari/20090817/1250464485 | |
* 0.3 http://d.hatena.ne.jp/Kureduki_Maari/20100212/1265937568 | |
* 0.4 http://d.hatena.ne.jp/Kureduki_Maari/20100413/1271113925 | |
* 0.5 | |
*/ | |
try { | |
detectFont; | |
} catch (e) { | |
//throw Error('convApp.js: We depend on detectFont.js; ' + e.message); | |
} | |
convApp = (function(){ | |
// [正, 俗, 正の実体参照] | |
// 正は、複数の場合も文字列 | |
// 正の実体参照は、単一の場合は文字列、複数の場合は文字列の配列 | |
var jis = [ | |
['亞', '亜', '4e9e'], ['櫻', '桜', '6afb'], ['惡', '悪', '60e1'], ['壓', '圧', '58d3'], ['醫医', '医', ['91ab', '533b']], ['壹', '壱', '58f9'], ['飮', '飲', '98ee'], | |
['隱', '隠', '96b1'], ['榮', '栄', '69ae'], ['營', '営', '71df'], ['搖', '揺', '6416'], ['遙', '遥', '9059'], ['謠', '謡', '8b20'], ['驛', '駅', '9a5b'], | |
['鹽', '塩', '9e7d'], ['歐', '欧', '6d50'], ['毆', '殴', '6bc6'], ['應', '応', '61c9'], ['價', '価', '50f9'], ['假', '仮', '5047'], ['屆', '届', '5c46'], | |
['效', '効', '6548'], ['號', '号', '865f'], ['殼', '殻', '6bbc'], ['覺', '覚', '89ba'], ['學', '学', '5b78'], ['嶽', '岳', '5dbd'], ['陷', '陥', '9677'], | |
['顏', '顔', '984f'], ['氣', '気', '6c23'], ['歸', '帰', '6b78'], ['戲', '戯', '6232'], ['僞', '偽', '50de'], ['犧', '犠', '72a7'], ['舊', '旧', '820a'], | |
['卻', '却', '537b'], ['據', '拠', '64da'], ['擧', '挙', '64e7'], ['區', '区', '5340'], ['驅', '駆', '9a45'], ['畫', '画', '756b'], ['會', '会', '6703'], | |
['繪', '絵', '7e6a'], ['囘', '回', '56d8'], ['壞', '壊', '58de'], ['懷', '懐', '61f7'], ['廣', '広', '5ee3'], ['鑛', '鉱', '945b'], ['擴', '拡', '64f4'], | |
['卷', '巻', '5377'], ['關', '関', '95dc'], ['勸', '勧', '52f8'], ['歡', '歓', '6b61'], ['觀', '観', '89c0'], ['勳', '勲', '52f3'], ['繼', '継', '7e7c'], | |
['攜', '携', '651c'], ['徑', '径', '5f91'], ['莖', '茎', '8396'], ['經', '経', '7d93'], ['輕', '軽', '8f15'], ['溪', '渓', '6eaa'], ['鷄', '鶏', '9dc4'], | |
['惠', '恵', '60e0'], ['螢', '蛍', '87a2'], ['藝', '芸', '85dd'], ['県', '県', '770c'], ['曉', '暁', '66c9'], ['缺欠', '欠', ['7f3a', '6b20']], ['挾', '挟', '633e'], | |
['狹', '狭', '72f9'], ['峽', '峡', '5cfd'], ['劵', '券', '52b5'], ['獻', '献', '737d'], ['儉', '倹', '5109'], ['驗', '験', '9a57'], ['檢', '検', '6aa2'], | |
['險', '険', '96aa'], ['劍', '剣', '528d'], ['縣', '県', '7e23'], ['圈', '圏', '5708'], ['顯', '顕', '986f'], ['權', '権', '6b0a'], ['嚴', '厳', '56b4'], | |
['恆', '恒', '6046'], ['國', '国', '570b'], ['齊', '斉', '9f4a'], ['濟', '済', '6fdf'], ['齋', '斎', '9f4b'], ['碎', '砕', '788e'], ['劑', '剤', '5291'], | |
['爭', '争', '722d'], ['壯', '壮', '58ef'], ['莊', '荘', '838a'], ['裝', '装', '88dd'], ['騷', '騒', '9a37'], ['雙', '双', '96d9'], ['藏', '蔵', '85cf'], | |
['臟', '臓', '81df'], ['册', '冊', '518c'], ['雜', '雑', '96dc'], ['插', '挿', '63d2'], ['贊', '賛', '8d0a'], ['參', '参', '53c3'], ['慘', '惨', '6158'], | |
['棧', '桟', '68e7'], ['殘', '残', '6b98'], ['蠶蚕', '蚕', ['8836', '8695']], ['絲糸', '糸', ['7d72', '7cf8']], ['齒', '歯', '9f52'], ['兒', '児', '5152'], ['辭', '辞', '6fad'], | |
['收', '収', '6536'], ['獸', '獣', '7378'], ['濕', '湿', '6fd5'], ['實', '実', '5be6'], ['澁', '渋', '6f81'], ['舍', '舎', '820d'], ['寫', '写', '5beb'], | |
['將', '将', '5c07'], ['奬', '奨', '596c'], ['壤', '壌', '58e4'], ['淨', '浄', '6de8'], ['讓', '譲', '8b93'], ['釋', '釈', '91cb'], ['壽', '寿', '58fd'], | |
['從', '従', '5f9e'], ['縱', '縦', '7e31'], ['肅', '粛', '8085'], ['處', '処', '8655'], ['敍', '叙', '654d'], ['稱', '称', '7a31'], ['證証', '証', ['8b49', '8a3c']], | |
['乘', '乗', '4e58'], ['剩', '剰', '5269'], ['繩', '縄', '7e69'], ['觸', '触', '89f8'], ['囑', '嘱', '56d1'], ['寢', '寝', '5be2'], ['眞', '真', '771e'], | |
['愼', '慎', '613c'], ['盡', '尽', '76e1'], ['粹', '粋', '7cb9'], ['醉', '酔', '9189'], ['穗', '穂', '7a57'], ['隨', '随', '96a8'], ['髓', '髄', '9ad3'], | |
['數', '数', '6578'], ['樞', '枢', '6a1e'], ['聲', '声', '8072'], ['靜', '静', '9751'], ['燒', '焼', '71d2'], ['攝', '摂', '651d'], ['竊', '窃', '7aca'], | |
['專', '専', '5c08'], ['戰', '戦', '6230'], ['淺', '浅', '6dfa'], ['踐', '践', '8e10'], ['錢', '銭', '9322'], ['潛', '潜', '6f5b'], ['纖', '繊', '7e96'], | |
['禪', '禅', '79aa'], ['總', '総', '7e3d'], ['搜', '捜', '641c'], ['屬', '属', '5c6c'], ['續', '続', '7e8c'], ['墮', '堕', '58ae'], ['體', '体', '9ad4'], | |
['對', '対', '5c0d'], ['帶', '帯', '5e36'], ['滯', '滞', '6eef'], ['臺台', '台', ['81fa', '53f0']], ['當', '当', '7576'], ['黨', '党', '9ee8'], ['稻', '稲', '7a3b'], | |
['盜', '盗', '76dc'], ['擇', '択', '64c7'], ['澤', '沢', '6fa4'], ['單', '単', '55ae'], ['擔', '担', '64d4'], ['膽', '胆', '81bd'], ['團', '団', '5718'], | |
['彈', '弾', '5f48'], ['斷', '断', '65b7'], ['癡', '痴', '7661'], ['遲', '遅', '9072'], ['晝', '昼', '665d'], ['鑄', '鋳', '9444'], ['聽', '聴', '807d'], | |
['廳', '庁', '5ef3'], ['孃', '嬢', '5b43'], ['釀', '醸', '91c0'], ['蟲', '虫', '87f2'], ['敕', '勅', '6555'], ['鎭', '鎮', '93ad'], ['圖', '図', '5716'], | |
['遞', '逓', '905e'], ['條', '条', '689d'], ['鐵', '鉄', '9435'], ['疊', '畳', '758a'], ['點', '点', '9ede'], ['轉', '転', '8f49'], ['傳', '伝', '50b3'], | |
['燈', '灯', '71c8'], ['鬪', '闘', '9b2a'], ['讀', '読', '8b80'], ['獨', '独', '7368'], ['惱', '悩', '60f1'], ['腦', '脳', '8166'], ['貳', '弐', '8cb3'], | |
['霸', '覇', '9738'], ['拜', '拝', '62dc'], ['廢', '廃', '5ee2'], ['賣', '売', '8ce3'], ['麥', '麦', '9ea5'], ['發', '発', '767c'], ['髮', '髪', '9aee'], | |
['拔', '抜', '62d4'], ['蠻', '蛮', '883b'], ['祕', '秘', '7955'], ['濱', '浜', '6ff1'], ['拂', '払', '62c2'], ['佛', '仏', '4f5b'], ['竝', '並', '7add'], | |
['變', '変', '8b8a'], ['邊', '辺', '908a'], ['弁辨瓣辮辯', '弁', ['5f01', '8fa8', '74e3', '8fae', '8faf']], ['舖', '舗', '8216'], ['寶', '宝', '5bf6'], ['襃' , '褒', '8943'], ['豐', '豊', '8c50'], | |
['冐', '冒', '5190'], ['沒', '没', '6c92'], ['飜', '翻', '98dc'], ['萬', '万', '842c'], ['滿', '満', '6eff'], ['彌', '弥', '5f4c'], ['默', '黙', '9ed8'], | |
['樣', '様', '6a23'], ['譯', '訳', '8b6f'], ['藥', '薬', '85e5'], ['豫予', '予', ['8c6b', '4e88']], ['餘余', '余', ['9918', '4f59']], ['與', '与', '8207'], ['譽', '誉', '8b7d'], | |
['來', '来', '4f86'], ['瀧', '滝', '7027'], ['勞', '労', '52de'], ['樂', '楽', '6a02'], ['覽', '覧', '89bd'], ['亂', '乱', '4e82'], ['兩', '両', '5169'], | |
['龍', '竜', '9f8d'], ['壘', '塁', '58d8'], ['禮', '礼', '79ae'], ['勵', '励', '52f5'], ['隸', '隷', '96b8'], ['靈', '霊', '9748'], ['齡', '齢', '9f61'], | |
['獵', '猟', '7375'], ['戀', '恋', '6200'], ['爐', '炉', '7210'], ['樓', '楼', '6a13'], ['灣', '湾', '7063'], ['爲', '為', '7232'], ['圍', '囲', '570d'], | |
['衞', '衛', '885e'], ['圓', '円', '5713'], ['奧', '奥', '5967'], ['穩', '穏', '7a69'] | |
], | |
unicode = [ | |
['視', '視', 'fa61'], ['曆', '暦', '66c6'], ['歷', '歴', '6b74'], ['穀', '穀', 'fa54'], ['者', '者', 'fa5b'], ['强', '強', '5f3a'], ['淸', '清', '6df8'], | |
['黑', '黒', '9ed1'], ['噓', '嘘', '5653'], ['都', '都', 'fa26'], ['殺', '殺', 'f970'], ['靑', '青', '9751'], ['綠', '緑', '7da0'], ['黃', '黄', '9ec4'], | |
['形', '形', '5f62'] | |
], | |
all = jis.concat(unicode); | |
function char_simpl2ortho(chr) { // @param String: 新字(一文字) | |
// @return Array: 可能性の有る舊字(一文字)の配列 | |
var i = -1, elm; | |
while (elm = all[++i]) { | |
if (chr === elm[1]) { | |
return elm[0].split(''); | |
} | |
} | |
return []; | |
}; | |
function char_ortho2simpl(chr) { // @param String: 舊字(一文字) | |
// @return String: 新字(一文字) | |
var i = -1, elm; | |
while (elm = all[++i]) { | |
if (elm[0].indexOf(chr) !== -1) { | |
return elm[1]; | |
} | |
} | |
return chr; | |
} | |
function str_sinpl2ortho(str) { // @param String: 新字文字列 | |
// @return String: 舊字文字列 | |
// 舊字の選択肢が一つのみの字を、舊字へ | |
var i = -1, chr, char_s2o = char_simpl2ortho; | |
str = str.split(''); | |
while (chr = str[++i]) { | |
str[i] = char_s2o(chr); | |
} | |
return str.join(''); | |
} | |
function str_ortho2simpl(str) { // @param String: 舊字文字列 | |
// @return String: 新字文字列 | |
var i = -1, chr, char_o2s = char_ortho2simpl; | |
str = str.split(''); | |
while (chr = str[++i]) { | |
str[i] = char_o2s(chr); | |
} | |
return str.join(''); | |
} | |
function str_ortho2simplByFont(str, // @param String: 舊字文字列 | |
font) { // @param String: Font名。 | |
// 此のFontに舊字が無い文字丈を、新字にする。 | |
// Fontに新字が有るかは保証しない。 | |
// @return String: 新字文字列 | |
var i = -1, chr, | |
char_o2s = char_ortho2simpl, | |
detectCharByFont = detectFont.detectCharByFont; | |
str = str.split(''); | |
while (chr = str[++i]) { | |
if (!detectCharByFont(chr, font)) { | |
str[i] = char_o2s(chr); | |
} | |
} | |
return str.join(''); | |
} | |
return { | |
jis: jis, | |
unicode: unicode, | |
char_simpl2ortho: char_simpl2ortho, | |
//char_ortho2simpl: char_ortho2simpl, | |
str_simpl2ortho: str_simpl2ortho, | |
str_ortho2simpl: str_ortho2simpl, | |
str_ortho2simplByFont: str_ortho2simplByFont | |
}; | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//depend: uu.font.js | |
(function(){ | |
//export detectFont | |
var _cashe = {}; | |
/* | |
* @paran char :String | |
* @param font :String | |
* @return :Boolean | |
*/ | |
var detectCharByFont = function(char, font){ | |
var chash_font, zenkaku; | |
if(char.length !== 1){throw Error('detectCharByFont(): <char> must be 1 charactor (not charactors or blank)')}; | |
if(char.charCodeAt(0) < 2000){return true}; | |
if(!_cashe.font){_cashe.font = {infont:[], nofont:[]}}; | |
cashe_font = _cashe.font; | |
if(cashe_font.infont.indexOf(char) !== -1){return true} | |
else if(cashe_font.nofont.indexOf(char) !== -1){return false} | |
else{ | |
zenkaku = uu.font.metric('144pt '+font, 'あ').w; | |
//return window.getComputedStyle(detectElm).width; | |
if(uu.font.metric('144pt '+font, char).w <= zenkaku/2){ | |
cashe_font.nofont.push(char); | |
return false; | |
}else{ | |
cashe_font.infont.push(char); | |
return true; | |
}; | |
}; | |
}; | |
/* | |
* @paran char :String | |
* @param element :Element | |
* @return :Boolean | |
*/ | |
var detectCharByElement = function(char, element){ | |
return detectCharCodeByFont(char, uu.font.detect(element)); | |
}; | |
detectFont = { | |
detectFontByElement: uu.font.detect, | |
detectCharByFont: detectCharByFont, | |
detectCharByElement: detectCharByElement | |
}; | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//レンダリングに使われているフォントと、ブラウザで使えるフォントを取得する - latest log - http://d.hatena.ne.jp/uupaa/20100128/1264630442 | |
// === Core === | |
// * WebKit based Cording-Style ( doc/cording-style.txt ) | |
// | |
// * User configrations ( doc/user-configrations.txt ) | |
// | |
// - uu.config = { aria, debug, right, altcss, storage, visited } | |
// | |
// * User callback functions ( doc/user-callback-functions.txt ) | |
// | |
// - window.xboot(uu:Function) | |
// - window.xwin(uu:Function) | |
// - window.xcanvas(uu:Function, canvasNodeArray:NodeArray) | |
// - window.xstorage(uu:Function, storage:StorageObject) | |
// | |
// * Predefined types ( doc/predefined-types.txt ) | |
// | |
// - ColorHash, RGBAHash, HSLAHash, HSVAHash, W3CNamedColor | |
// - EventObjectEx, DateHash, AjaxOptionHash, AjaxResultHash | |
// - JSONPOptionHash, FlashOptionHash | |
// | |
// * Version and plugin detection ( doc/version-detection.txt ) | |
// | |
// - uu.ver = { library, browser, render, silverlight, flash, as3, | |
// ie, ie6, ie7, ie8, ie9, ie67, ie678, ie89, | |
// opera, gecko, webkit, chrome, safari, iphone, | |
// quirks, xml, win, mac, unix, advanced, major, jit } | |
var uu; // window.uu - uupaa.js library namespace | |
uu || (function(win, doc) { | |
// --- LIBRARY STRUCTURE --- | |
uu = uumix(uufactory, { // uu(expression:Jam/Node/NodeArray/String/window, arg1:Jam/Node/Mix = void, arg2:Mix = void, arg3:Mix = void, arg4:Mix = void):Jam/Instance | |
// [1][Class factory] uu("MyClass", arg1, arg2) -> new uu.Clas.MyClass(arg1, arg2) | |
// [2][NodeSet factory] uu("div>ul>li", <body>) -> Jam | |
ver: _version(0.7), // uu.ver - Hash: detected version and plugin informations | |
plugin: uuplugin, // uu.plugin():Array | |
require: uurequire, // uu.require(url:String):AjaxResultHash | |
// --- TYPE --- | |
like: uulike, // uu.like(lhs:Date/Hash/Fake/Array, rhs:Date/Hash/Fake/Array):Boolean | |
type: uumix(uutype, { // uu.type(search:Mix, match:Number = 0):Boolean/Number | |
HASH: 0x001, // uu.type.HASH - Hash (Object) | |
NODE: 0x002, // uu.type.NODE - Node (HTMLElement) | |
FAKEARRAY: 0x004, // uu.type.FAKEARRAY - FakeArray (Arguments, NodeList, ...) | |
DATE: 0x008, // uu.type.DATE - Date | |
NULL: 0x010, // uu.type.NULL - null | |
VOID: 0x020, // uu.type.VOID - undefined / void | |
UNDEFINED: 0x020, // uu.type.UNDEFINED - undefined / void | |
BOOLEAN: 0x040, // uu.type.BOOLEAN - Boolean | |
FUNCTION: 0x080, // uu.type.FUNCTION - Function | |
NUMBER: 0x100, // uu.type.NUMBER - Number | |
STRING: 0x200, // uu.type.STRING - String | |
ARRAY: 0x400, // uu.type.ARRAY - Array | |
REGEXP: 0x800, // uu.type.REGEXP - RegExp | |
CSS: 0x1000 // uu.type.CSS - CSSProperties (getComputedStyle result) | |
}), | |
isNumber: uuisnumber, // uu.isNumber(search:Mix):Boolean | |
isString: uuisstring, // uu.isString(search:Mix):Boolean | |
isFunction: uuisfunction, // uu.isFunction(search:Mix):Boolean | |
// --- HASH / ARRAY --- | |
arg: uuarg, // uu.arg(arg1:Hash = {}, arg2:Hash, arg3:Hash = void):Hash | |
mix: uumix, // uu.mix(base:Hash, flavor:Hash, aroma:Hash = void, override:Boolean = true):Hash | |
each: uueach, // uu.each(source:Hash/Array, callback:Function) | |
keys: uukeys, // uu.keys(source:Hash/Array):Array | |
values: uuvalues, // uu.values(source:Hash/Array):Array | |
hash: uumix(uuhash, { // uu.hash(key:Hash/String, value:Mix = void):Hash | |
has: uuhas, // uu.hash.has(source:Hash, search:Array):Boolean | |
nth: uunth, // uu.hash.nth(source:Hash, index:Number):Array | |
size: uusize, // uu.hash.size(source:Hash):Number | |
clone: uuclone, // uu.hash.clone(source:Hash):Hash | |
indexOf: uuindexof // uu.hash.indexOf(source:Hash, search:Mix):String/void | |
}), | |
array: uumix(uuarray, { // uu.array(source:Array/Mix/NodeList/Arguments):Array | |
has: uuhas, // uu.array.has(source:Array, search:Array):Boolean | |
nth: uunth, // uu.array.nth(source:Array, index:Number):Array | |
size: uusize, // uu.array.size(source:Array):Number | |
sort: uusort, // uu.array.sort(source:Array, method:String/Function = "0-9"):Array | |
clean: uuclean, // uu.array.clean(source:Array):Array | |
clone: uuclone, // uu.array.clone(source:Array):Array | |
toHash: uutohash, // uu.array.toHash(key:Array, value:Array/Mix, toNumber:Boolean = false):Hash | |
unique: uuunique // uu.array.unique(source:Array, literalOnly:Boolean = false):Array | |
}), | |
// --- ATTRIBUTE --- | |
attr: uumix(uuattr, { // uu.attr(node:Node, key:Hash/String, value:String = void):String/Hash/Node | |
// [1][get one attr ] uu.attr(node, "attr") -> "value" | |
// [2][get some attrs] uu.attr(node, "attr1,attr2") -> { attr1: "val", attr2: "val" } | |
// [3][set one attr ] uu.attr(node, "attr", "val") -> node | |
// [4][set some attrs] uu.attr(node, { attr: "val" }) -> node | |
get: uuattrget, // uu.attr.get(node:Node, attrs:String):String/Hash | |
// [1][get one attr ] uu.attr.get(node, "attr") -> String | |
// [2][get some attrs] uu.attr.get(node, "attr,...") -> Hash | |
set: uuattrset, // uu.attr.set(node:Node, key:String/Hash, value:String = void):Node | |
// [1][set one attr ] uu.attr.set(node, key, val ) -> node | |
// [2][set some attrs] uu.attr.set(node, { key: val, ... }) -> node | |
getAll: uuattrgetall // uu.attr.getAll(node:Node, filter:Boolean = false):Hash | |
// [1][get all] uu.attr(node) -> { all: attrs } | |
// [2][use filter] uu.attr(node, true) -> { many: attrs } | |
}), | |
// --- CSS --- | |
css: uumix(uucss, { // uu.css(node:Node, key:Hash/String, value:String = void):String/Hash/Node | |
// [1][get one style ] uu.css(node, "color") -> "red" | |
// [2][get some styles] uu.css(node, "color,width") -> { color: "red", width: "20px" } | |
// [3][set one style ] uu.css(node, "color", "red") -> node | |
// [4][set some styles] uu.css(node, { color: "red" }) -> node | |
get: uucssget, // uu.css.get(node:Node, styles:String):String/Hash | |
// [1][get one style ] uu.css.get(node, "color") -> "red" | |
// [2][get some styles] uu.css.get(node, "color,text-align") -> {color:"red", textAlign:"left"} | |
set: uucssset, // uu.css.set(node:Node, key:String/Hash, value:String = void):Node | |
// [1][set one style ] uu.css.set(node, "color", "red") -> node | |
// [2][set some styles] uu.css.set(node, { color: "red" }) -> node | |
opacity: | |
uumix(uucssopacity, { // uu.css.opacity(node:Node, opacity:Number = void, isRelativeValue:Boolean = false):Number/node | |
// [1][get opacity] uu.css.opacity(node) -> Number(0.0~1.0) | |
// [2][set opacity] uu.css.opacity(node, opacity, isRelativeValue = false) -> node | |
get: uucssopacityget,// uu.css.opacity.get(node:Node):Number | |
set: uucssopacityset // uu.css.opacity.set(node:Node, opacity:Number, isRelativeValue:Boolean = false):Node | |
}) | |
}), | |
// --- getComputedStyle / currentStyle wrapper --- | |
style: uumix(uustyle, { // uu.style(node:Node, mode:Number = 0):Hash | |
quick: uustylequick // uu.style.quick(node:Node):Hash | |
}), | |
// --- QUERY --- | |
id: uuid, // uu.id(expression:String, context:Node = document):Node/null | |
tag: uutag, // uu.tag(expression:String, context:Node = document):NodeArray | |
query: uuquery, // uu.query(expression:String, context:NodeArray/Node = document):NodeArray | |
// --- Node.className --- | |
klass: uumix(uuklass, { // uu.klass(expression:String, context:Node = document):NodeArray | |
has: uuklasshas, // uu.klass.has(node:Node, classNames:String):Boolean | |
add: uuklassadd, // uu.klass.add(node:Node, classNames:String):Node | |
sub: uuklasssub, // uu.klass.sub(node:Node, classNames:String):Node | |
toggle: uuklasstoggle // uu.klass.toggle(node:Node, classNames:String):Node | |
}), | |
// --- OOP --- | |
Class: uumix(uuclass, { // uu.Class(className:String, proto:Hash = void) | |
// [1][base] uu.Class("A", { proto: ... }) | |
// [2][inherit] uu.Class("B:A", { proto: ... }) | |
guid: uuclassguid, // uu.Class.guid():Number | |
singleton: uuclasssingleton// uu.Class.singleton(className:String, proto:Hash = void) | |
}), | |
// --- EVENT --- | |
event: uumix(uuevent, { // uu.event(node:Node, eventTypeEx:String, evaluator:Function, detach:Boolean = false):Node | |
// [1][bind a event] uu.event(node, "click", fn) -> node | |
// [2][bind multi events] uu.event(node, "click,dblclick", fn) -> node | |
// [3][bind a capture event] uu.event(node, "mousemove+", fn) -> node | |
// [4][bind a namespace.event] uu.event(node, "MyNameSpace.click", fn) -> node | |
has: uueventhas, // uu.event.has(node:Node, eventTypeEx:String):Boolean | |
fire: uueventfire, // uu.event.fire(node:Node, eventType:String, param:Mix = void):Node | |
stop: uueventstop, // uu.event.stop(eventObject:EventObject):EventObject | |
unbind: uueventunbind, // uu.event.unbind(node:Node, eventTypeEx:String = void):Node | |
attach: uueventattach, // uu.event.attach(node:Node, eventType:String, evaluator:Function, capture:Boolean = false) | |
detach: uueventdetach // uu.event.detach(node:Node, eventType:String, evaluator:Function, capture:Boolean = false) | |
}), | |
// --- Node / NodeList --- | |
node: uumix(uunode, { // uu.node(tagName:String = "div", attr:Hash = void):Node | |
add: uunodeadd, // uu.node.add(source:Node/DocumentFragment/HTMLFragment/TagName = "div", context:Node = <body>, position:Number = 6):Node | |
// [1][add div node] uu.node.add() -> <body><div /></body> | |
// [2][from tagName] uu.node.add("p") -> <body><p /></body> | |
// [3][from node] uu.node.add(uu.div()) -> <body><div /></body> | |
// [4][from HTMLFragment] uu.node.add("<div><p>txt</p></div>") -> <body><div><p>txt</p></div></body> | |
// [5][from DocumentFragment] uu.node.add(DocumentFragment) -> <body>{{fragment}}</body> | |
has: uunodehas, // uu.node.has(node:Node, context:Node):Boolean | |
root: doc.documentElement || doc.html, | |
// root node, documentElement or <html>(in IE quirks) | |
bulk: uunodebulk, // uu.node.bulk(source:Node/HTMLFragment, context:Node/TagString = "div"):DocumentFragment | |
swap: uunodeswap, // uu.node.swap(swapin:Node, swapout:Node):Node (swapout node) | |
wrap: uunodewrap, // uu.node.wrap(innerNode:Node, outerNode:Node):Node (innerNode) | |
build: uunodebuild, // uu.node.build(node:Node/String, args:Mix):Node | |
// [1][add node] uu.div(uu.div()) | |
// [2][add text node] uu.div("hello") | |
// [3][add text node] uu.div(uu.text("hello")) | |
// [4][id callback] uu.div("@buildid") - window.xnode(uu, <div>, {{"buildid"}}, nodeid) | |
// [5][number callback] uu.div(1) - window.xnode(uu, <div>, {{1}}, nodeid) | |
// [6][set attr by string] uu.div("title,hello") - first String is uu.attr("title,hello") | |
// [7][set attr by hash] uu.div({ title: "hello" }) - first Hash is uu.attr({ title: "hello" }) | |
// [8][set css by string] uu.div("", "color,red") - second String is uu.css("color,red") | |
// [9][set css by hash] uu.div("", { color: "red" }) - second Hash is uu.css({ color: "red" }) | |
clear: uunodeclear, // uu.node.clear(context:Node):Node | |
clone: uunodebulk, // [alias] | |
remove: uunoderemove // uu.node.remove(node:Node):Node | |
}), | |
nodeid: uumix(uunodeid, { // uu.nodeid(node:Node):Number (nodeid) | |
toNode: uunodeidtonode, // uu.nodeid.toNode(nodeid:Number):Node | |
remove: uunodeidremove // uu.nodeid.remove(node:Node):Node (removed node) | |
}), | |
html: uuhtml, // uu.html(node, attr, style, buildid) -> <html> | |
head: uuhead, // uu.head(node, attr, style, buildid) -> <head> | |
body: uubody, // uu.body(node, attr, style, buildid) -> <body> | |
text: uutext, // uu.text(node:Node/String, text:String(= void)):Array/String/Node | |
// [1][create node] uu.text("text") -> createTextNode("text") | |
// [2][get text] uu.text(node) -> text or [text, ...] | |
// [3][set text] uu.text(node, "text") -> node | |
// --- STRING --- | |
fix: uufix, // uu.fix(source:String):String | |
// [1][css-prop to js-css-prop] uu.fix("background-color") -> "backgroundColor" | |
// [2][std-name to ie-name] uu.fix("float") -> "cssFloat" or "styleFloat"(IE) | |
// [3][html-attr to js-attr] uu.fix("for") -> "htmlFor" | |
// [4][through] uu.fix("-webkit-shadow") -> "-webkit-shadow" | |
trim: uumix(uutrim, { // uu.trim(" has space ") -> "has space" | |
tag: uutrimtag, // uu.trim.tag(" <h1>A</h1> B <p>C</p> ") -> "A B C" | |
url: uutrimurl, // uu.trim.url(' url("http://...") ') -> "http://..." | |
inner: uutriminner, // uu.trim.inner(" diet inner space ") -> "diet inner space" | |
quote: uutrimquote, // uu.trim.quote(' "quote string" ') -> 'quote string' | |
bracket: uutrimbracket // uu.trim.bracket(" <bracket> (this) [and] {this} ") -> "bracket this and this" | |
}), | |
split: uumix(uusplit, { // uu.split(" A B C ") -> ["A", "B", "C"] | |
comma: uusplitcomma, // uu.split.comma(",,, ,,A,,,B,C,, ") -> ["A","B","C"] | |
toHash: uusplittohash // uu.split.toHash(source:String, splitter:String = ",", toNumber:Boolean = false):Hash | |
// [1][hash from string] uu.split.toHash("key,1,key2,1", ",") -> { key: 0, key2: 1 } | |
}), | |
format: uuformat, // uu.format(format:String, var_args, ...):String | |
// [1][placeholder] uu.format("? dogs and ?", 101, "cats") -> "101 dogs and cats" | |
// --- JSON --- | |
json: uumix(uujson, { // uu.json(source:Mix, useNativeJSON:Boolean = false, callback:Function = void):JSONString | |
decode: uujsondecode // uu.json.decode(jsonString:JSONString, useNativeJSON:Boolean = false):Mix/Boolean | |
}), | |
// --- DATE --- | |
date: uudate, // uu.date(source:DateHash/Date/Number/String= void):DateHash | |
// [1][get now] uu.date() -> DateHash | |
// [2][DateHash] uu.date(DateHash) -> cloned DateHash | |
// [2][date to hash] uu.date(Date) -> DateHash | |
// [3][time to hash] uu.date(milliseconds) -> DateHash | |
// [4][DateString to hash] uu.date("2000-01-01T00:00:00[.000]Z") -> DateHash | |
// [5][ISO8601String to hash] uu.date("2000-01-01T00:00:00[.000]Z") -> DateHash | |
// [6][RFC1123String to hash] uu.date("Wed, 16 Sep 2009 16:18:14 GMT") -> DateHash | |
// --- DEBUG --- | |
puff: uupuff, // uu.puff(source:Mix) | |
trace: uumix(uutrace, { // uu.trace(titleOrSource:String/Mix, source:Mix = void) | |
clear: uutraceclear // uu.trace.clear() | |
}), | |
// --- READY EVENT --- | |
ready: uumix(uuready, { // uu.ready(evaluator:Function = void, order:Number = 0) | |
gone: { // ready event state | |
dom: 0, // 1 is [DOMReady] DOMContentLoaded event fired | |
win: 0, // 1 is [WindowReady] window.onload event fired | |
audio: 0, // 1 is [AudioReady] <audio> ready event fired | |
video: 0, // 1 is [VideoReady] <video> ready event fired | |
canvas: 0, // 1 is [CanvasReady] <canvas> ready event fired | |
storage: 0, // 1 is [LocalStroageReady] LocalStorage ready event fired | |
blackout: 0 // 1 is [BlackOut] blackout (css3 cache reload) | |
} | |
}), | |
// --- LAZY EVALUATION --- | |
lazy: uumix(uulazy, { // uu.lazy(id:String, evaluator:Function, order:Number = 0) | |
fire: uulazyfire // uu.lazy.fire(id:String) | |
}), | |
// --- OTHER --- | |
js: uujs, // uu.js(javascriptExpression:String):Mix | |
win: { | |
size: uuwinsize // uu.win.size():Hash { innerWidth, innerHeight, pageXOffset, pageYOffset } | |
}, | |
nop: function() {}, // uu.nop() | |
dmz: {}, // uu.dmz - DeMilitarized Zone(proxy) | |
guid: uuguid // uu.guid():Number | |
}); | |
// --- MessagePump class --- | |
MessagePump.prototype = { | |
send: uumsgsend, // MessagePump.send(address:Array/Mix, message:String, param:Mix = void):Array/Mix | |
// [1][multicast] MessagePump.send([instance, ...], "hello") -> ["world!", ...] | |
// [2][unicast ] MessagePump.send(instance, "hello") -> ["world!"] | |
// [3][broadcast] MessagePump.send(null, "hello") -> ["world!", ...] | |
post: uumsgpost, // MessagePump.post(address:Array/Mix, message:String, param:Mix = void) | |
// [1][multicast] MessagePump.post([instance, ...], "hello") | |
// [2][unicast ] MessagePump.post(instance, "hello") | |
// [3][broadcast] MessagePump.post(null, "hello") | |
register: uumsgregister, // MessagePump.register(instance:Instance) | |
unregister: uumsgunregister // MessagePump.unregister(instance:Instance) | |
}; | |
uu.msg = new MessagePump(); // uu.msg - MessagePump instance | |
// --- ECMAScript-262 5th --- | |
Array.isArray || (Array.isArray = uuisarray); | |
//{{{!mb | |
uumix(Array.prototype, { | |
map: arraymap, // map(evaluator:Function, that:this = void):Array | |
some: arraysome, // some(evaluator:Function, that:this = void):Boolean | |
every: arrayevery, // every(evaluator:Function, that:this = void):Boolean | |
filter: arrayfilter, // filter(evaluator:Function, that:this = void):Array | |
forEach: arrayforeach, // forEach(evaluator:Function, that:this = void) | |
indexOf: arrayindexof, // indexOf(search:Mix, fromIndex:Number = 0):Number | |
lastIndexOf: arraylastindexof// lastIndexOf(search:Mix, fromIndex:Number = this.length):Number | |
}, 0, 0); | |
//}}}!mb | |
uumix(Array.prototype, { | |
reduce: arrayreduce, // reduce(evaluator:Function, initialValue:Mix = void):Mix | |
reduceRight: arrayreduceright// reduceRight(evaluator:Function, initialValue:Mix = void):Mix | |
}, 0, 0); | |
uumix(Boolean.prototype, { | |
toJSON: numbertojson // toJSON():String | |
}, 0, 0); | |
uumix(Date.prototype, { | |
toISOString: datetoisostring,// toISOString():String | |
toJSON: datetoisostring // toJSON():String | |
}, 0, 0); | |
uumix(Number.prototype, { | |
toJSON: numbertojson // toJSON():String | |
}, 0, 0); | |
uumix(String.prototype, { | |
trim: stringtrim, // trim():String | |
toJSON: stringtojson // toJSON():String | |
}, 0, 0); | |
//{{{!mb | |
uu.ver.gecko && win.HTMLElement && !win.HTMLElement.prototype.innerText && | |
(function(proto) { | |
proto.__defineGetter__("innerText", innertextgetter); | |
proto.__defineSetter__("innerText", innertextsetter); | |
proto.__defineGetter__("outerHTML", outerhtmlgetter); | |
proto.__defineSetter__("outerHTML", outerhtmlsetter); | |
})(win.HTMLElement.prototype); | |
//}}}!mb | |
// --- construction --- | |
uu.ie = uu.ver.ie; | |
uu.opera = uu.ver.opera; | |
uu.gecko = uu.ver.gecko; | |
uu.webkit = uu.ver.webkit; | |
uu.config = uuarg(win.xconfig, { // uu.config - Hash: user configurations | |
aria: false, | |
debug: false, | |
right: false, | |
altcss: 0, | |
storage: 0, | |
visited: false, | |
baseDir: uutag("script").pop().src.replace(/[^\/]+$/, "") | |
}); | |
doc.html || (doc.html = uutag("html")[0]); // document.html = <html> | |
doc.head || (doc.head = uutag("head")[0]); // document.head = <head> | |
// =================================================================== | |
// [1][Class factory] uu("MyClass", arg1, arg2) -> new uu.Clas.MyClass(arg1, arg2) | |
// [2][NodeSet factory] uu("div>ul>li", <body>) -> Jam | |
// uu - factory | |
function uufactory(expression, // @param Jam/Node/NodeArray/String/window: expression or ClassName | |
arg1, // @param Jam/Node/Mix(= void): context or ClassName.init arg1 | |
arg2, // @param Mix(= void): ClassName.init arg2 | |
arg3, // @param Mix(= void): ClassName.init arg3 | |
arg4) { // @param Mix(= void): ClassName.init arg4 | |
// @return Jam/Instance: | |
// class factory | |
if (typeof expression === "string" && uuclass[expression]) { | |
return new uuclass[expression](arg1, arg2, arg3, arg4); | |
} | |
// jam factory | |
return new uu.jam(expression, arg1, arg2, arg3, arg4); // depend: uu.jam | |
} | |
// --- plugin / plugin name space --- | |
// uu.plugin - enum plugins | |
function uuplugin() { // @return Array: ["plugin-name", ...] | |
return uukeys(uuplugin); | |
} | |
// uu.require - require file | |
function uurequire(url) { // @param String: url | |
// @return AjaxResultHash: | |
var xhr, status = 400, ok = false; | |
try { | |
xhr = win.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : | |
win.XMLHttpRequest ? new XMLHttpRequest() : 0; | |
xhr.open("GET", url, false); // sync | |
xhr.send(null); | |
if (!xhr.status || (xhr.status >= 200 && xhr.status < 300)) { | |
ok = true; | |
status = xhr.status || 200; | |
} | |
} catch (err) { | |
xhr = xhr || { responseText: "", responseXML: "", status: 400 }; | |
} | |
return { | |
ok: ok, | |
url: url, | |
xhr: xhr, | |
guid: uuguid(), | |
status: status, | |
isXMLContent: function() { | |
return /xml/i.test(this.xhr.getResponseHeader("Content-Type") || ""); | |
} | |
}; | |
} | |
// --- type --- | |
// [1][literal like literal] uu.like("abcdef", "abcdef") -> true | |
// [2][Date like Date] uu.like(new Date(123), new Date(123)) -> true | |
// [3][Hash like Hash] uu.like({ a: { b: 1 }}, { a: { b: 1 }}) -> true | |
// [4][Array like Array] uu.like([1, [2, 3]], [1, [2, 3]]) -> true | |
// [5][FakeArray like FakeArray] uu.like(document.links, document.links) -> true | |
// uu.like - like and deep matching | |
function uulike(lhs, // @param Date/Hash/Fake/Array: lhs | |
rhs) { // @param Date/Hash/Fake/Array: rhs | |
// @return Boolean: | |
var type1 = uutype(lhs); | |
if (type1 !== uutype(rhs)) { | |
return false; | |
} | |
switch (type1) { | |
case uutype.FUNCTION: return false; | |
case uutype.DATE: return uudate(lhs).ISO() === | |
uudate(rhs).ISO(); | |
case uutype.HASH: return (uusize(lhs) === uusize(rhs) && uuhas(lhs, rhs)); | |
case uutype.FAKEARRAY: // http://d.hatena.ne.jp/uupaa/20091223 | |
case uutype.ARRAY: return uuarray(lhs) + "" == uuarray(rhs); | |
} | |
return lhs === rhs; | |
} | |
// [1][typeof] uu.type("str") -> 0x100(uu.type.STRING) | |
// [2][typeof matched bits] uu.type("str", uu.type.STRING | uu.type.NUMBER) -> true | |
// uu.type - type detection | |
function uutype(search, // @param Mix: search literal/object | |
match) { // @param Number(= 0): match types | |
// @return Boolean/Number: true is match, | |
// false is unmatch, | |
// Number is matched bits | |
var rv = uutype._TYPEOF[typeof search] || | |
uutype._TYPEOF[Object.prototype.toString.call(search)] || | |
(!search ? uutype.NULL : search.nodeType ? uutype.NODE : | |
"length" in search ? uutype.FAKEARRAY : uutype.HASH); | |
return match ? !!(match & rv) : rv; | |
} // [OPTIMIZED] | |
uutype._TYPEOF = { | |
"undefined": uutype.VOID, | |
"[object Boolean]": uutype.BOOLEAN, "boolean": uutype.BOOLEAN, | |
"[object Number]": uutype.NUMBER, "number": uutype.NUMBER, | |
"[object String]": uutype.STRING, "string": uutype.STRING, | |
"[object Function]":uutype.FUNCTION, "function": uutype.FUNCTION, | |
"[object RegExp]": uutype.REGEXP, | |
"[object Array]": uutype.ARRAY, | |
"[object Date]": uutype.DATE, | |
"[object CSSStyleDeclaration]": uutype.CSS, // [WebKit][Opera] | |
"[object ComputedCSSStyleDeclaration]": uutype.CSS // [Gecko] | |
}; | |
// uu.isNumber - is number | |
function uuisnumber(search) { // @param Mix: search | |
// @return Boolean: | |
return typeof search === "number"; | |
} | |
// uu.isString - is string | |
function uuisstring(search) { // @param Mix: search | |
// @return Boolean: | |
return typeof search === "string"; | |
} | |
// inner - is array | |
function uuisarray(search) { // @param Mix: search | |
// @return Boolean: | |
return Object.prototype.toString.call(search) === "[object Array]"; | |
} | |
// inner - is date | |
function uuisdate(search) { // @param Mix: search | |
// @return Boolean: | |
return Object.prototype.toString.call(search) === "[object Date]"; | |
} | |
// uu.isFunction - is function | |
function uuisfunction(search) { // @param Mix: search | |
// @return Boolean: | |
return Object.prototype.toString.call(search) === "[object Function]"; | |
} | |
// --- hash / array --- | |
// [1][supply args] uu.arg({ a: 1 }, { b: 2 }) -> { a: 1, b: 2 } | |
// uu.arg - supply default arguments | |
function uuarg(arg1, // @param Hash(= {}): arg1 | |
arg2, // @param Hash: arg2 | |
arg3) { // @param Hash(= void): arg3 | |
// @return Hash: new Hash(mixed arg) | |
return uumix(uumix({}, arg1 || {}), arg2, arg3, 0); | |
} | |
// [1][override value] uu.mix({a:9, b:9}, {a:1}, {b:2}) -> { a: 1, b: 2 } | |
// [2][stable value] uu.mix({a:9, b:9}, {a:1}, {b:2}, 0) -> { a: 9, b: 9 } | |
// uu.mix - mixin | |
function uumix(base, // @param Hash: mixin base | |
flavor, // @param Hash: add flavor | |
aroma, // @param Hash(= void): add aroma | |
override) { // @param Boolean(= true): true is override | |
// @return Hash: base | |
var i; | |
if (override === void 0 || override) { // [1][3] | |
for (i in flavor) { | |
base[i] = flavor[i]; | |
} | |
} else { // [2] | |
for (i in flavor) { | |
i in base || (base[i] = flavor[i]); | |
} | |
} | |
return aroma ? uumix(base, aroma, 0, override) : base; | |
} | |
// [1][Array.forEach] uu.each([1, 2], function(v, i) {...}) | |
// [2][Hash.forEach ] uu.each({ a: 1, b: 2 }, function(v, i) {...}) | |
// uu.each - for each | |
function uueach(source, // @param Hash/Array: source | |
callback) { // @param Function: callback | |
if (Array.isArray(source)) { | |
source.forEach(callback); | |
} else { | |
for (var i in source) { | |
callback(source[i], i); // callback(value, index) | |
} | |
} | |
} | |
// [1][Hash.keys] uu.keys({ a: 1, b: 2 }) -> ["a", "b"] | |
// [2][Array.keys] uu.keys([1, 2]) -> [0, 1] | |
// uu.keys - enum keys | |
function uukeys(source, // @param Hash/Array: source | |
_enumValues) { // @hidden Boolean(= false): true is enum values | |
// @return Array: [key, ... ] | |
var rv = [], ri = -1, i, iz; | |
if (Array.isArray(source)) { | |
for (i = 0, iz = source.length; i < iz; ++i) { | |
i in source && (rv[++ri] = _enumValues ? source[i] : i); | |
} | |
} else { | |
if (!_enumValues && Object.keys) { | |
return Object.keys(source); | |
} | |
for (i in source) { | |
if (source.hasOwnProperty(i)) { | |
rv[++ri] = _enumValues ? source[i] : i; | |
} | |
} | |
} | |
return rv; | |
} | |
// [1][Hash.values] uu.keys({ a: 1, b: 2 }) -> [1, 2] | |
// [2][Array.values] uu.keys([1, 2]) -> [1, 2] | |
// uu.values - enum values | |
function uuvalues(source) { // @param Hash/Array: source | |
// @return Array: [value, ... ] | |
return uukeys(source, true); | |
} | |
// [1][hash to hash(through)] uu.hash({ key: "val" }) -> { key: "val" } | |
// [2][key/value pair to hash] uu.hash("key", mix) -> { key: mix } | |
// uu.hash - to hash, convert hash from key value pair | |
function uuhash(key, // @param Hash/String: key | |
value) { // @param Mix(= void): value | |
// @return Hash: { key: value, ... } | |
if (arguments.length === 1) { // [1] | |
return key; | |
} | |
var rv = {}; | |
rv[key] = value; // [2] | |
return rv; | |
} | |
// uu.hash._dd2num = { "00": 0 , ... "99": 99 }; Zero-filled dec string -> Number | |
// uu.hash._num2dd = { 0: "00", ... 99: "99" }; Number -> Zero-filled dec string | |
_makeMapping("0123456789", uuhash._dd2num = {}, uuhash._num2dd = {}); | |
// uu.hash._hh2num = { "00": 0 , ... "ff": 255 }; Zero-filled hex string -> Number | |
// uu.hash._num2hh = { 0: "00", ... 255: "ff" }; Number -> Zero-filled hex string | |
_makeMapping("0123456789abcdef", uuhash._hh2num = {}, uuhash._num2hh = {}); | |
// [1][ary to ary (through)] uu.ary([1, 2]) -> [1, 2] | |
// [2][mix to ary] uu.ary(mix) -> [mix] | |
// [3][NodeList to ary] uu.ary(NodeList) -> [node, ...] | |
// [4][arguments to ary] uu.ary(arguments) -> [arg, ...] | |
// uu.array - to array, convert array | |
function uuarray(source) { // @param Array/Mix/NodeList/Arguments: source | |
// @return Array: | |
var type = uutype(source), rv, i, iz; | |
if (type === uutype.FAKEARRAY) { // [3][4] | |
for (rv = [], i = 0, iz = source.length; i < iz; ++i) { | |
rv[i] = source[i]; | |
} | |
return rv; | |
} | |
return (type === uutype.ARRAY) ? source : [source]; // [1][2] | |
} | |
// [1][Hash has Hash] uu.has({ a: 1, b: 2 }, { a: 1 }) -> true | |
// [2][Array has Array] uu.has([1, 2], [1]) -> true | |
// uu.has - has | |
function uuhas(source, // @param Hash/Array: source | |
search) { // @param Hash/Array: search element | |
// @return Boolean: | |
if (source && search) { | |
var i, iz; | |
if (Array.isArray(source)) { | |
search = uuarray(search); | |
for (i = 0, iz = search.length; i < iz; ++i) { | |
if (i in search && source.indexOf(search[i]) < 0) { | |
return false; | |
} | |
} | |
return true; | |
} | |
for (i in search) { | |
if (!(i in source)) { | |
return false; | |
} | |
if (source[i] !== search[i] | |
&& _jsoninspect(source[i]) !== _jsoninspect(search[i])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
return false; | |
} | |
// [1][Hash nth ] uu.nth({ a: 1, b: 2 }, 1) -> ["b", 2] | |
// [2][Array nth] uu.nth(["a", 100], 1) -> [1, 100] | |
// uu.nth - nth pair | |
function uunth(source, // @param Hash/Array: source | |
index) { // @param Number: index | |
// @return Array: [key, value] | |
// or [void, void] (not found) | |
var i, j = 0; | |
if (Array.isArray(source)) { | |
if (i in source) { | |
return [i, source[i]]; | |
} | |
} else { | |
for (i in source) { | |
if (j++ === index) { | |
return [i, source[i]]; | |
} | |
} | |
} | |
return [void 0, void 0]; | |
} | |
// [1][Hash.length] uu.size({ a: 1, b: 2 }) -> 2 | |
// [2][Array.length] uu.size([1,2]) -> [1,2] | |
// uu.size - get length | |
function uusize(source) { // @param Hash/Array: source | |
// @return Number: | |
return Array.isArray(source) ? source.length : uukeys(source).length; | |
} | |
// [1][Hash.clone] uu.clone({ a: 1, b: 2 }) -> { a: 1, b: 2 } | |
// [2][Array.clone] uu.clone([1,2]) -> [1,2] | |
// uu.clone - clone hash, clone array | |
function uuclone(source) { // @param Hash/Array: source | |
// @return Hash/Array: cloned hash/array | |
return Array.isArray(source) ? source.concat() : uumix({}, source); | |
} | |
// [1][Hash.indexOf] uu.hash.indexOf({ a: 1, b: 2, c: 2 }, 2) -> "b" | |
// uu.hash.indexOf - find first key from value | |
function uuindexof(source, // @param Hash: source | |
search) { // @param Mix: search value | |
// @return String/void: "found-key" or void | |
for (var i in source) { | |
if (source.hasOwnProperty(i) && source[i] === search) { | |
return i; // String | |
} | |
} | |
return void 0; | |
} | |
// [1][numeric sort 0-9] uu.sort([0,1,2], "0-9") -> [0, 1, 2] | |
// [2][numeric sort 9-0] uu.sort([0,1,2], "9-0") -> [2, 1, 0] | |
// [3][ascii sort a-z] uu.sort(["a","z"], "A-Z") -> ["a", "z"] | |
// [4][ascii sort a-z] uu.sort(["a","z"], "Z-A") -> ["z", "a"] | |
// [5][callback] uu.sort(["a","z"], callback) -> ["z", "a"] | |
// uu.sort - sort array | |
function uusort(source, // @param Array: source | |
method) { // @param String/Function(= "0-9"): method | |
// sort method or callback-function | |
// @return Array: | |
function _numericsort(a, b) { | |
return a - b; | |
} | |
if (Array.isArray(source)) { | |
switch (method || "0-9") { | |
case "0-9": source.sort(_numericsort); break; // [1] | |
case "9-0": source.sort(_numericsort).reverse(); break; // [2] | |
case "A-Z": source.sort(); break; // [3] | |
case "Z-A": source.sort().reverse(); break; // [4] | |
default: source.sort(method); // [5] | |
} | |
} | |
return source; | |
} | |
// [1][Array.clean] uu.clone([,,1,2,,]) -> [1,2] | |
// uu.clean - array compaction, trim null and undefined elements | |
function uuclean(source) { // @param Array: source | |
// @return Array: clean Array | |
if (Array.isArray(source)) { | |
var rv = [], i = 0, iz = source.length; | |
for (; i < iz; ++i) { | |
if (i in source) { | |
if (source[i] != null) { // null and undefined | |
rv.push(source[i]); | |
} | |
} | |
} | |
return rv; | |
} | |
return source; | |
} | |
// [1][unique elements] uu.unique([<body>, <body>]) -> [<body>] | |
// [2][unique literals] uu.unique([0,1,2,1,0], true) -> [0,1,2] | |
// uu.unique - make array from unique element( trim null and undefined elements) | |
function uuunique(source, // @param Array: source | |
literalOnly) { // @param Boolean(= false): true is literal only(quickly) | |
// @return Array: | |
literalOnly = literalOnly ? true : false; | |
if (Array.isArray(source)) { | |
var rv = [], ri = -1, v, i = 0, j, iz = source.length, | |
found, | |
unique = {}; | |
for (; i < iz; ++i) { | |
v = source[i]; | |
if (v != null) { // null and undefined | |
if (literalOnly) { // [2] | |
unique[v] || (unique[v] = 1, rv[++ri] = v); | |
} else { // [1] | |
for (found = 0, j = i - 1; !found && j >= 0; --j) { | |
found = (v === source[j]); | |
} | |
!found && (rv[++ri] = v); | |
} | |
} | |
} | |
return rv; | |
} | |
return source; | |
} | |
// [1][Array x 2 = Hash] uu.array.toHash(["a", "b"], [1, 2]) -> { a: 1, b: 2 } | |
// [2][Array + Mix = Hash] uu.array.toHash(["a", "b"], 1) -> { a: 1, b: 1 } | |
// uu.array.toHash - make { key: value } pair from array | |
function uutohash(key, // @param Array: key array | |
value, // @param Array/Mix: value array or a mix value | |
toNumber) { // @param Boolean(= false): true is numeric value | |
// false is original value | |
// @return Hash: { key: value, ... } | |
var rv = {}, i = 0, iz = key.length, val; | |
if (Array.isArray(value)) { // [1] | |
for (; i < iz; ++i) { | |
rv[key[i]] = toNumber ? +(value[i]) : value[i]; | |
} | |
} else { // [2] | |
val = toNumber ? +(value) : value; | |
for (; i < iz; ++i) { | |
rv[key[i]] = val; | |
} | |
} | |
return rv; | |
} | |
// --- attribute --- | |
// [1][get one attr ] uu.attr(node, "attr") -> "value" | |
// [2][get some attrs] uu.attr(node, "attr1,attr2") -> { attr1: "val", attr2: "val" } | |
// [3][set one attr ] uu.attr(node, "attr", "val") -> node | |
// [4][set some attrs] uu.attr(node, { attr: "val" }) -> node | |
// uu.attr - attribute accessor | |
function uuattr(node, // @param Node: | |
key, // @param Hash/String: key | |
value) { // @param String(= void): value | |
// @return String/Hash/Node: | |
return (value === void 0 && uuisstring(key) ? uuattrget // [1][2] | |
: uuattrset)(node, key, value); // [3][4] | |
} | |
uuattr._HASH = uusplittohash( | |
uu.ver.ie67 ? "for,htmlFor,className,class" | |
: ("class,className,for,htmlFor,colspan,colSpan," + | |
"accesskey,accessKey,rowspan,rowSpan,tabindex,tabIndex") | |
); | |
// [1][get one attr ] uu.attr.get(node, "attr") -> String | |
// [2][get some attrs] uu.attr.get(node, "attr,...") -> Hash | |
// uu.attr.get - get attribute | |
function uuattrget(node, // @param Node: | |
attrs) { // @param String: "attr1,..." | |
// @return String/Hash: "value" (one attr) | |
// or { attr1: "value", ... } | |
var rv = {}, ary = attrs.split(","), v, w, i = 0, iz = ary.length, | |
HASH = uuattr._HASH; // [IE67] for -> htmlFor, className -> class | |
// [OTHER] for -> htmlFor, class -> className | |
for (; i < iz; ++i) { | |
v = ary[i]; | |
w = HASH[v] || v; | |
if (uu.ie) { | |
if (uu.ver.ie89 || v === "href" || v === "src") { | |
// [IE6][IE7][FIX] a[href^="#"] -> full path | |
rv[v] = node.getAttribute(v, 2) || ""; | |
} else { | |
rv[v] = node[w] || ""; | |
} | |
} else { | |
rv[v] = node.getAttribute(w) || ""; | |
} | |
} | |
return (ary.length === 1) ? rv[ary[0]] : rv; // [3][4] | |
} | |
// [1][set one attr ] uu.attr.set(node, key, val ) -> node | |
// [2][set some attrs] uu.attr.set(node, { key: val, ... }) -> node | |
// uu.attr.set - set attribute | |
function uuattrset(node, // @param Node: | |
key, // @param String/Hash: key | |
value) { // @param String(= void): value | |
// @return Node: | |
var hash, i, HASH = uuattr._HASH; | |
uuisstring(key) ? (hash = {}, hash[key] = value) : (hash = key); | |
for (i in hash) { | |
node.setAttribute(HASH[i] || i, hash[i]); | |
} | |
return node; | |
} | |
// [1][get all] uu.attr(node) -> { all: attrs } | |
// [2][use filter] uu.attr(node, true) -> { many: attrs } | |
// uu.attr.getAll - get all attributes | |
function uuattrgetall(node, // @param Node: | |
filter) { // @param Boolean(= false): true is filter | |
// (ignore style and uu prefix keywords) | |
// @return Hash: | |
filter = filter ? true : false; | |
var rv = {}, ary = node.attributes, v, w, i = -1; | |
while ( (v = ary[++i]) ) { | |
w = v.name; | |
if (!filter) { // [1] | |
rv[w] = v.value; | |
} else if (v.specified && w !== "style" && w.indexOf("uu")) { // [2] | |
// ignore: style keywords | |
// ignore: uu prefix keywords | |
rv[w] = v.value; | |
} | |
} | |
return rv; | |
} | |
// --- css / style --- | |
// [1][get one style ] uu.css(node, "color") -> "red" | |
// [2][get some styles] uu.css(node, "color,width") -> { color: "red", width: "20px" } | |
// [3][set one style ] uu.css(node, "color", "red") -> node | |
// [4][set some styles] uu.css(node, { color: "red" }) -> node | |
// uu.css - css accessor | |
function uucss(node, // @param Node: | |
key, // @param Hash/String: key | |
value) { // @param String(= void): value | |
// @return String/Hash/Node: | |
return (value === void 0 && uuisstring(key) ? uucssget // [1][2] | |
: uucssset)(node, key, value); // [3][4] | |
} | |
// [1][get one style ] uu.css.get(node, "color") -> "red" | |
// [2][get some styles] uu.css.get(node, "color,text-align") -> {color:"red", textAlign:"left"} | |
// uu.css.get - get getComputedStyle(node) value | |
function uucssget(node, // @param Node: | |
styles) { // @param String: "cssProp,..." or "css-prop,..." | |
// @return String/Hash: "value" | |
// or { cssProp: "value", ... } | |
var rv = {}, ary = styles.split(","), v, i = -1, | |
ns = uustyle(node), fixdb = uufix._db; | |
while ( (v = ary[++i]) ) { | |
rv[v] = ns[fixdb[v] || v] || ""; | |
} | |
return (ary.length === 1) ? rv[ary[0]] : rv; | |
} | |
// [1][set one style ] uu.css.set(node, "color", "red") -> node | |
// [2][set some styles] uu.css.set(node, { color: "red" }) -> node | |
// uu.css.set | |
function uucssset(node, // @param Node: | |
key, // @param String/Hash: | |
value) { // @param String(= void): | |
// @return Node: | |
var hash = uuhash(key, value), // make { cssProp: value } | |
ns = node.style, p, v, i, n, | |
fixdb = uufix._db, hook = uucssset._hook; | |
for (i in hash) { | |
v = hash[i]; | |
p = fixdb[i] || i; | |
if (typeof v === "string") { | |
ns[p] = v; // backgroundColor = "transparent" | |
} else { | |
n = hook[p]; | |
if (n === 2) { | |
uucssopacityset(node, v); | |
} else { | |
ns[p] = n ? v : (v + "px"); // zoom = 1, width = 100 + "px" | |
} | |
} | |
} | |
return node; | |
} | |
uucssset._hook = { opacity: 2, lineHeight: 1, fontWeight: 1, | |
fontSizeAdjust: 1, zIndex: 1, zoom: 1 }; | |
// [1][get opacity] uu.css.opacity(node) -> Number(0.0~1.0) | |
// [2][set opacity] uu.css.opacity(node, opacity, isRelativeValue = false) -> node | |
// uu.css.opacity | |
function uucssopacity(node, // @param Node: | |
opacity, // @param Number(= void): opacity 0.0 - 1.0 | |
isRelativeValue) { // @param Boolean(= false): true is relative value | |
// @return Number/Node: | |
return (opacity === void 0 ? uucssopacityget | |
: uucssopacityset)(node, opacity, isRelativeValue); | |
} | |
// uu.css.opacity.get - get opacity value(from 0.0 to 1.0) | |
function uucssopacityget(node) { // @param Node: | |
// @return Number: float(from 0.0 to 1.0) | |
if (uu.ie) { | |
var v = node.uucssopacity; // void or 1.0 ~ 2.0 | |
return v === void 0 ? 1 : (v - 1); | |
} | |
return parseFloat(node.style.opacity || | |
win.getComputedStyle(node, null).opacity); | |
} | |
// uu.css.opacity.set - set opacity value(from 0.0 to 1.0) | |
function uucssopacityset(node, // @param Node: | |
opacity, // @param Number: opacity, float(from 0.0 to 1.0) | |
isRelativeValue) { // @param Boolean(= false): true is relative value | |
// @return Node: | |
var ns; // node.style alias | |
if (uu.ver.ie678) { | |
ns = node.style; | |
if (node.uucssopacity === void 0) { | |
// at first time | |
if (uu.ver.ie67) { // [FIX][IE] | |
if ((node.currentStyle || {}).width === "auto") { | |
ns.zoom = 1; | |
} | |
} | |
} | |
} | |
isRelativeValue && (opacity += uucssopacityget(node)); | |
// normalize | |
opacity = (opacity > 0.999) ? 1 | |
: (opacity < 0.001) ? 0 : opacity; | |
node.style.opacity = opacity; | |
if (uu.ver.ie678) { | |
node.uucssopacity = opacity + 1; // (1.0 ~ 2.0) | |
ns.visibility = opacity ? "" : "hidden"; | |
ns.filter = ((opacity > 0 && opacity < 1) | |
? "alpha(opacity=" + (opacity * 100) + ") " : "") | |
+ ns.filter.replace(uucssopacityset._alpha, ""); | |
} | |
return node; | |
} | |
uucssopacityset._alpha = /^alpha\([^\x29]+\) ?/; | |
// --- getComputedStyle --- | |
// [1][get all computedStyle] uu.style(node) -> { width: "100px", ... } | |
// [2][get more computedStyle] uu.style(node, 0x1) -> { width: "100px", ... } | |
// [3][get some computedStyle] uu.style(node, 0x2) -> { width: "100px", ... } | |
// uu.style - getComputedStyle, currentStyle wrapper | |
function uustyle(node, // @param Node: | |
mode) { // @param Number(= 0): | |
// 0: enum full properties | |
// 1: enum more properties | |
// 2: enum some properties | |
// 4: currentStyle (IE6,IE7,IE8 only) | |
// @return Hash: { prop: "val", ... } | |
//{{{!mb | |
// http://d.hatena.ne.jp/uupaa/20091212 | |
if (uu.ver.ie678) { | |
if (mode === 4) { | |
return node.currentStyle; | |
} | |
if (!node.currentStyle) { | |
return {}; | |
} | |
var rv = {}, | |
ns = node.style, | |
cs = node.currentStyle, | |
rs = node.runtimeStyle, | |
box = uustyle._HASH.box, UNITS = uustyle._UNITS, | |
RECTANGLE = uustyle._RECTANGLE, | |
em, rect, ut, v, w, x, i = -1, j = -1, m1, m2, | |
ary = !mode ? uustyle._HASH.full | |
: (mode === 1) ? uustyle._HASH.more | |
: 0, | |
stock = { "0px": "0px", "1px": "1px", "2px": "2px", "5px": "5px", | |
thin: "1px", medium: "3px", thick: uustyle._THICK_FIX }; | |
if (ary) { | |
while ( (w = ary[++j]) ) { | |
rv[w] = cs[w]; | |
} | |
} | |
em = parseFloat(cs.fontSize) * | |
(uustyle._UNIT_PT.test(cs.fontSize) ? 4 / 3 : 1); | |
rect = node.getBoundingClientRect(); | |
// calc border, padding and margin size | |
while ( (w = box[++i]) ) { | |
v = cs[w]; | |
if (!(v in stock)) { | |
x = v; | |
switch (ut = UNITS[v.slice(-1)]) { | |
case 1: x = parseFloat(v) * em; break; // "12em" | |
case 2: x = parseFloat(v) * 4 / 3; break; // "12pt" | |
case 3: m1 = ns.left, m2 = rs.left; // %, auto | |
rs.left = cs.left, ns.left = v; | |
x = ns.pixelLeft, ns.left = m1, rs.left = m2; | |
} | |
stock[v] = ut ? x + "px" : x; | |
} | |
rv[w] = stock[v]; | |
} | |
for (w in RECTANGLE) { | |
v = cs[w]; | |
switch (ut = UNITS[v.slice(-1)]) { | |
case 1: v = parseFloat(v) * em; break; // "12em" | |
case 2: v = parseFloat(v) * 4 / 3; break; // "12pt" | |
case 3: // %, auto | |
switch (RECTANGLE[w]) { | |
case 1: v = node.offsetTop; break; // style.top | |
case 2: v = node.offsetLeft; break; // style.left | |
case 3: v = (node.offsetWidth || rect.right - rect.left) // style.width | |
- parseInt(rv.borderLeftWidth) | |
- parseInt(rv.borderRightWidth) | |
- parseInt(rv.paddingLeft) | |
- parseInt(rv.paddingRight); | |
v = v > 0 ? v : 0; | |
break; | |
case 4: v = (node.offsetHeight || rect.bottom - rect.top) // style.height | |
- parseInt(rv.borderTopWidth) | |
- parseInt(rv.borderBottomWidth) | |
- parseInt(rv.paddingTop) | |
- parseInt(rv.paddingBottom); | |
v = v > 0 ? v : 0; | |
} | |
} | |
rv[w] = ut ? v + "px" : v; | |
} | |
rv.fontSize = em + "px"; | |
rv.cssFloat = cs.styleFloat; // compat alias | |
return rv; | |
} | |
//}}}!mb | |
return win.getComputedStyle(node, null); | |
} | |
//{{{!mb | |
uustyle._HASH = uu.ver.ie678 ? _builduustylehash() : {}; | |
uustyle._UNITS = { m: 1, t: 2, "%": 3, o: 3 }; // em, pt, %, auto | |
uustyle._UNIT_PT = /pt$/; | |
uustyle._THICK_FIX = uu.ver.ie89 ? "5px" : "6px"; | |
uustyle._RECTANGLE = { top: 1, left: 2, width: 3, height: 4 }; | |
//}}}!mb | |
// uu.style.quick - getComputedStyle or currentStyle | |
function uustylequick(node) { // @param Node: | |
// @return Hash: { prop: "val", ... } | |
return uustyle(node, 4); | |
} | |
//{{{!mb inner - build uu.style hash | |
function _builduustylehash() { | |
// http://d.hatena.ne.jp/uupaa/20091212 | |
var rv = { full: [], more: [], box: [] }, | |
ary = [" "], i, w, trim = /^\s+|\s+$/g, | |
cs = doc.html.currentStyle; | |
for (i in cs) { | |
ary.push(i); | |
} | |
ary.sort(); | |
w = ary.join(" ").replace(/ (?:accelerator|behavior|hasLayout|zoom)/g, ""); | |
rv.full = w.replace(trim, "").split(" "); | |
rv.more = w.replace(/ (?:lay\w+|rub\w+|text\w+|pageB\w+|ms\w+|scr\w+)/g, ""). | |
replace(/ (?:blockDirection|orphans|quotes|widows|filter|styleFloat)/g, ""). | |
replace(/ (?:imeMode|writingMode|unicodeBidi|emptyCells|tableLayout)/g, ""). | |
replace(/ (?:border(?:Color|Style|Width)|margin|padding|outline) /g, " "). | |
replace(/ (border\w+Width|margin\w+|padding\w+)/g, function(_, m) { | |
return rv.box.push(m), _; | |
}).replace(trim, "").concat(" textAlign textOverflow textIndent"). | |
split(" ").sort(); | |
return rv; | |
} | |
//}}}!mb | |
// --- className(klass) --- | |
// uu.klass.has - has className | |
function uuklasshas(node, // @param Node: | |
classNames) { // @param String: "class1 class2 ..." (joint space) | |
// @return Boolean: | |
var m, ary, cn = node.className; | |
if (!classNames || !cn) { | |
return false; | |
} | |
if (classNames.indexOf(" ") < 0) { | |
return (" " + cn + " ").indexOf(" " + classNames + " ") >= 0; // single | |
} | |
ary = uusplit(classNames); // multi | |
m = cn.match(_classNameMatcher(ary)); | |
return m && m.length >= ary.length; | |
} | |
// [1][add className] uu.klass.add(node, "class1 class2") -> node | |
// uu.klass.add - add className | |
function uuklassadd(node, // @param Node: | |
classNames) { // @param String: "class1 class2 ..." | |
// @return Node: | |
node.className += " " + classNames; // [OPTIMIZED] // uutriminner() | |
return node; | |
} | |
// [1][sub className] uu.klass.sub(node, "class1 class2") -> node | |
// uu.klass.sub - remove className | |
function uuklasssub(node, // @param Node: | |
classNames) { // @param String(= ""): "class1 class2 ..." | |
// @return Node: | |
node.className = uutriminner( | |
node.className.replace(_classNameMatcher(uusplit(classNames)), "")); | |
return node; | |
} | |
// uu.klass.toggle - toggle(add / sub) className property | |
function uuklasstoggle(node, // @param Node: | |
classNames) { // @param String: "class1 class2 ..." | |
// @return Node: | |
(uuklasshas(node, classNames) ? uuklasssub : uuklassadd)(node, classNames); | |
return node; | |
} | |
// --- oop --- | |
// uu.Class - create a generic class | |
function uuclass(className, // @param String: "Class" | |
// or "Class:SuperClass" | |
// or "Class<SuperClass" | |
proto) { // @param Hash(= void): prototype object | |
// http://d.hatena.ne.jp/uupaa/20100129 | |
var ary = className.split(/\s*[\x3a-\x40]\s*/), tmp, i, | |
Class = ary[0], Super = ary[1] || ""; | |
uuclass[Class] = function uuClass() { | |
var that = this, | |
Super = that.superClass || 0, | |
SuperSuper = Super ? Super.superClass : 0; | |
// register MessagePump | |
uuclassguid(that); | |
that.msgbox || (that.msgbox = uu.nop); | |
uu.msg.register(that); | |
// constructor(order: SuperSuper -> Super -> that) | |
if (SuperSuper && SuperSuper.init) { | |
SuperSuper.init.apply(that, arguments); | |
} | |
if (Super && Super.init) { | |
Super.init.apply(that, arguments); | |
} | |
if (that.init) { | |
that.init.apply(that, arguments); | |
} | |
// setup destructor(order: ~that -> ~Super -> ~SuperSuper) | |
that["~fin"] = that.fin || uu.nop; | |
if (that.fin) { | |
uu.event.attach(win, "unload", function() { | |
that.fin && that.fin(); | |
}); | |
} | |
that.fin = function wrapper() { | |
that["~fin"](); | |
Super && Super.fin && Super.fin.call(that); | |
SuperSuper && SuperSuper.fin && SuperSuper.fin.call(that); | |
// destroy them all | |
for (var i in that) { | |
that[i] = null; | |
} | |
}; | |
}; | |
uuclass[Class].prototype = proto || {}; | |
if (Super) { // [2] | |
tmp = function() {}; | |
tmp.prototype = uu.Class[Super].prototype; | |
uuclass[Class].prototype = new tmp; | |
for (i in proto) { | |
uuclass[Class].prototype[i] = proto[i]; | |
} | |
uuclass[Class].prototype.constructor = uuclass[Class]; | |
uuclass[Class].prototype.superClass = uu.Class[Super].prototype; | |
uuclass[Class].prototype.superMethod = superMethod; | |
} | |
// call superClass method | |
function superMethod(from, // @param Function: caller | |
method // @param String: method name | |
/* var_args */) { // @param Mix: args | |
var obj = this.superClass; | |
// recurtion guard | |
if (from === obj[method] || superMethod.caller === obj[method]) { | |
obj = obj.superClass; | |
} | |
return obj[method].apply(this, uu.array(arguments).slice(2)); | |
} | |
} | |
// uu.Class.guid - get instance id | |
function uuclassguid(instance) { // @param Instance: | |
// @return Number: instance id, from 1 | |
return instance.uuguid || (instance.uuguid = uu.guid()); | |
} | |
// uu.Class.singleton - create a singleton class | |
function uuclasssingleton(className, // @param String: class name | |
proto) { // @param Hash(= void): prototype object | |
// @return Object: singleton class instance | |
uuclass[className] = function() { | |
var that = this, arg = arguments, self = arg.callee; | |
if (self.instance) { | |
that.stable && that.stable.apply(that, arg); // after the second | |
} else { | |
uuclassguid(that); | |
that.init && that.init.apply(that, arg); | |
that.fin && uu.event.attach(win, "unload", function() { | |
that.fin(); | |
}); | |
that.msgbox || (that.msgbox = uu.nop); | |
uu.msg.register(that); | |
} | |
return self.instance || (self.instance = that); | |
}; | |
uuclass[className].prototype = proto || {}; | |
} | |
// --- message pump --- | |
// MessagePump | |
function MessagePump() { | |
this._addressMap = {}; // AddressMap { guid: instance, ... } | |
this._broadcast = []; // Broadcast AddressMap [guid, ...] | |
} | |
// [1][multicast] MessagePump.send([instance, ...], "hello") -> ["world!", ...] | |
// [2][unicast ] MessagePump.send(instance, "hello") -> ["world!"] | |
// [3][broadcast] MessagePump.send(null, "hello") -> ["world!", ...] | |
// MessagePump.send - send a message synchronously | |
function uumsgsend(address, // @param Array/Mix: address or guid | |
// [instance, ...] is multicast | |
// instance is unicast | |
// null is broadcast | |
message, // @param String: message | |
param) { // @param Mix(= void): | |
// @return Arra: [result, ...] | |
var rv = [], ri = -1, to, obj, i = -1, | |
ary = address ? uu.array(address) : this._broadcast; | |
while ( (to = ary[++i]) ) { | |
obj = this._addressMap[to.uuguid || to || 0]; | |
obj && (rv[++ri] = obj.msgbox(message, param)); | |
} | |
return rv; | |
} | |
// [1][multicast] MessagePump.post([instance, ...], "hello") | |
// [2][unicast ] MessagePump.post(instance, "hello") | |
// [3][broadcast] MessagePump.post(null, "hello") | |
// MessagePump.post - send a message asynchronously | |
function uumsgpost(address, // @param Array/Mix: address or guid | |
// [instance, ...] is multicast | |
// instance is unicast | |
// null is broadcast | |
message, // @param String: message | |
param) { // @param Mix(= void): param | |
var that = this; | |
setTimeout(function() { | |
that.send(address ? uu.array(address) : that._broadcast, message, param); | |
}, 0); | |
} | |
// MessagePump.register - register the destination of the message | |
function uumsgregister(instance) { // @param Instance: class instance | |
this._addressMap[uuclassguid(instance)] = instance; | |
this._broadcast = uu.keys(this._addressMap); | |
} | |
// MessagePump.unregister | |
function uumsgunregister(instance) { // @param Instance: class instance | |
delete this.db[uuclassguid(instance)]; | |
this._broadcast = uu.keys(this._addressMap); | |
} | |
// --- event --- | |
// [1][bind a event] uu.event(node, "click", fn) -> node | |
// [2][bind multi events] uu.event(node, "click,dblclick", fn) -> node | |
// [3][bind a capture event] uu.event(node, "mousemove+", fn) -> node | |
// [4][bind a namespace.event] uu.event(node, "MyNameSpace.click", fn) -> node | |
// uu.event - bind event | |
function uuevent(node, // @param Node: | |
eventTypeEx, // @param EventTypeExString: some EventTypeEx, "click,click+,..." | |
evaluator, // @param Function/Instance: callback function | |
unbind) { // @param Boolean(= false): true is unbind, false is bind | |
// @return Node: | |
function _uueventclosure(evt, fromCustomEvent) { | |
evt = evt || win.event; | |
if (!fromCustomEvent && !evt.code) { | |
var src = evt.srcElement || evt.target, // [IE] srcElement | |
iebody; | |
// make EventObjectEx { code, node, src, px, py, ox, oy } | |
src = (uu.webkit && src.nodeType === 3) ? src.parentNode : src; | |
evt.code = (EVENT_CODE[evt.type] || 0) & 255; | |
evt.node = node; | |
evt.src = src; | |
if (uu.ie) { | |
iebody = uu.quirks ? doc.body : uu.node.root; | |
evt.px = evt.clientX + iebody.scrollLeft; | |
evt.py = evt.clientY + iebody.scrollTop; | |
} else { | |
evt.px = evt.pageX; | |
evt.py = evt.pageY; | |
} | |
evt.ox = evt.offsetX || evt.layerX || 0; // [IE][Opera][WebKit] offsetX | |
evt.oy = evt.offsetY || evt.layerY || 0; // [Gecko][WebKit] layerX | |
} | |
isInstance ? handler.call(evaluator, evt, node, src) | |
: evaluator(evt, node, src); | |
} // [OPTIMIZED] | |
// --- setup event database --- | |
if (!("uuEventTypeExString" in node)) { | |
node.uuEventTypeExString = ","; | |
node.uuEventEvaluatorHash = {}; | |
} | |
var eventTypeExArray = eventTypeEx.split(","), | |
ex, token, | |
bound, | |
evaluatorArray, | |
ns, eventType, capture, closure, handler, i = -1, pos, | |
isInstance = false, EVENT_CODE = uuevent._CODE; // for closure | |
if (unbind) { | |
closure = evaluator.uueventclosure || evaluator; | |
} else { | |
handler = uuisfunction(evaluator) | |
? evaluator | |
: (isInstance = true, evaluator.handleEvent); | |
closure = evaluator.uueventclosure = _uueventclosure; | |
} | |
while ( (ex = eventTypeExArray[++i]) ) { // ex = "namespace.click+" | |
// split token | |
// "namespace.click+" | |
// v | |
// ["namespace.click+", "namespace", "click", "+"] | |
token = uuevent._PARSE.exec(ex); | |
ns = token[1]; // "namespace" | |
eventType = token[2]; // "click" | |
capture = token[3]; // "+" | |
// IE mouse capture | |
if (uu.ie678) { | |
if (capture && eventType === "mousemove") { | |
uuevent(node, "losecapture", closure, unbind); | |
} | |
} | |
bound = node.uuEventTypeExString.indexOf("," + ex + ",") >= 0; | |
// IE mouse capture | |
if (uu.ie678) { | |
if (eventType === "losecapture") { | |
if (node.setCapture) { | |
bound ? node.setCapture() | |
: node.releaseCapture(); | |
} | |
} | |
} | |
if (unbind) { | |
if (bound) { | |
evaluatorArray = node.uuEventEvaluatorHash[ex]; | |
pos = evaluatorArray.indexOf(ex); | |
if (pos >= 0) { | |
evaluatorArray.splice(pos, 1); // remove evaluator | |
if (!evaluatorArray.length) { | |
// ",dblclick," <- ",namespace.click+,dblclick,".replace(",namespace.click+,", ",") | |
node.uuEventTypeExString = | |
node.uuEventTypeExString.replace("," + ex + ",", ","); | |
} | |
uueventdetach(node, eventType, closure, capture); | |
} | |
} | |
} else { | |
// ",namespace.click+,dblclick," <- ",namespace.click+," + "dblclick" + ," | |
if (!bound) { | |
node.uuEventTypeExString += ex + ","; | |
node.uuEventEvaluatorHash[ex] = []; // init evaluatorArray | |
} | |
node.uuEventEvaluatorHash[ex].push(closure); // evaluatorArray.push() | |
uueventattach(node, eventType, closure, capture); | |
} | |
} | |
return node; | |
} | |
uuevent._PARSE = /^(?:(\w+)\.)?(\w+)(\+)?$/; // ^[NameSpace.]EvntType[Capture]$ | |
uuevent._LIST = ("mousedown,mouseup,mousemove,mousewheel,click,dblclick," + | |
"keydown,keypress,keyup,change,submit,focus,blur,contextmenu").split(","); | |
uuevent._CODE = { | |
mousedown: 1, mouseup: 2, mousemove: 3, mousewheel: 4, click: 5, | |
dblclick: 6, keydown: 7, keypress: 8, keyup: 9, mouseenter: 10, | |
mouseleave: 11, mouseover: 12, mouseout: 13, contextmenu: 14, | |
focus: 15, blur: 16, resize: 17, | |
losecapture: 0x102, DOMMouseScroll: 0x104 | |
}; | |
// uu.event.has - has event | |
function uueventhas(node, // @param Node: target node | |
eventTypeEx) { // @param EventTypeExString: namespace and event types, "click", "namespace.mousemove+" | |
// @return Boolean: | |
return (node.uuEventTypeExString || "").indexOf("," + eventTypeEx + ",") >= 0; | |
} | |
// uu.event.fire - fire event / fire custom event(none capture event only) | |
function uueventfire(node, // @param Node: target node | |
eventType, // @param String: "click", "custom" | |
param) { // @param Mix(= void): param | |
// @return Node: | |
if (uu.event.has(node, eventType)) { | |
var fakeEventObjectEx = { | |
stopPropagation: uu.nop, | |
preventDefault: uu.nop, | |
node: node, // current target | |
name: eventType, // event name | |
code: 0, // 0: unknown | |
src: node, // event source | |
rel: node, | |
px: 0, | |
py: 0, | |
ox: 0, | |
oy: 0, | |
type: eventType, // event type | |
param: param | |
}; | |
node.uuEventEvaluatorHash[eventType].forEach(function(evaluator) { | |
evaluator.call(node, fakeEventObjectEx, true); // fromCustomEvent = true | |
}); | |
} | |
return node; | |
} | |
// uu.event.stop - stop stopPropagation and preventDefault | |
function uueventstop(eventObject) { // @param EventObject: | |
// @return EventObject: | |
uu.ie ? (eventObject.cancelBubble = true) : eventObject.stopPropagation(); | |
uu.ie ? (eventObject.returnValue = false) : eventObject.preventDefault(); | |
return eventObject; | |
} | |
// [1][unbind all] uu.event.unbind(node) -> node | |
// [2][unbind some] uu.event.unbind(node, "click+,dblclick") -> node | |
// [3][unbind namespace all] uu.event.unbind(node, "namespace.*") -> node | |
// [4][unbind namespace some] uu.event.unbind(node, "namespace.click+,namespace.dblclick") -> node | |
// uu.event.unbind - unbind event | |
function uueventunbind(node, // @param Node: target node | |
eventTypeEx) { // @param EventTypeExString(= void): namespace and event types, "click,click+,..." | |
// @return Node: | |
function _unbindall(ex) { // @param EventTypeExString: "MyNamespace.mousemove+" | |
// closure vars: node, ns | |
if (!ex.indexOf(ns)) { | |
node.uuEventEvaluatorHash[ex].forEach(function(evaluator) { | |
uuevent(node, ex, evaluator, true); // unbind mode | |
}); | |
} | |
} | |
if (eventTypeEx === void 0) { // [1] | |
eventTypeEx = node.uuEventTypeExString; // ",click,MyNamespace.mousemove+," | |
} | |
var ns, ary = uusplitcomma(eventTypeEx), ex, i = -1; | |
while ( (ex = ary[++i]) ) { | |
if (ex.lastIndexOf(".*") > 1) { // [3] "namespace.*" | |
ns = ex.slice(0, -1); // "namespace.*" -> "namespace." | |
uusplitcomma(eventTypeEx).forEach(_unbindall); | |
} else { // [2][4] | |
if (eventTypeEx.indexOf("," + ex + ",") >= 0) { | |
node.uuEventEvaluatorHash[ex].forEach(function(evaluator) { | |
uuevent(node, ex, evaluator, true); // unbind mode | |
}); | |
} | |
} | |
} | |
return node; | |
} | |
// uu.event.attach - attach event - Raw Level API wrapper | |
function uueventattach(node, // @param Node: | |
eventType, // @param String: event type | |
evaluator, // @param Function: evaluator | |
capture) { // @param Boolean(= false): | |
eventType = uueventattach._FIX[eventType] || eventType; | |
if (node.addEventListener) { | |
node.addEventListener(eventType, evaluator, !!(capture || 0)); | |
} else { | |
node.attachEvent("on" + eventType, evaluator); | |
} | |
} | |
uueventattach._FIX = uu.gecko ? { mousewheel: "DOMMouseScroll" } : | |
uu.opera ? { contextmenu: "mousedown" } : {}; | |
// uu.event.detach - detach event - Raw Level API wrapper | |
function uueventdetach(node, // @param Node: | |
eventType, // @param String: event type | |
evaluator, // @param Function: evaluator | |
capture) { // @param Boolean(= false): | |
eventType = uueventattach._FIX[eventType] || eventType; | |
if (node.removeEventListener) { | |
node.removeEventListener(eventType, evaluator, !!(capture || 0)); | |
} else { | |
node.detachEvent("on" + eventType, evaluator); | |
} | |
} | |
// uu.ready - hook DOMContentLoaded event | |
function uuready(evaluator, // @param Function(= void): callback function | |
order) { // @param Number(= 0): 0=low, 1=mid, 2=high(system) | |
if (evaluator !== void 0 && !uuready.gone.blackout) { | |
uuready.gone.dom ? evaluator(uu) // fired -> callback | |
: uulazy("boot", evaluator, order || 0); // [1] stock | |
} | |
} | |
// --- node --- | |
// uu.node - createElement wrapper | |
function uunode(tagName, // @param String(= "div"): | |
attr) { // @param Hash(= void): | |
// @return Node: <node> | |
var rv = doc.createElement(tagName || "div"); | |
return attr === void 0 ? rv : uumix(rv, attr); | |
} | |
// [1][add div node] uu.node.add() -> <body><div /></body> | |
// [2][from tagName] uu.node.add("p") -> <body><p /></body> | |
// [3][from node] uu.node.add(uu.div()) -> <body><div /></body> | |
// [4][from HTMLFragment] uu.node.add("<div><p>txt</p></div>") -> <body><div><p>txt</p></div></body> | |
// [5][from DocumentFragment] uu.node.add(DocumentFragment) -> <body>{{fragment}}</body> | |
// uu.node.add - create element, add node, add node to context | |
function uunodeadd(source, // @param Node/DocumentFragment/HTMLFragment/TagName(= "div"): | |
context, // @param Node(= <body>): add to context | |
position) { // @param Number(= 6): insert position | |
// 1: first sibling | |
// 2: prev sibling | |
// 3: next sibling | |
// 4: last sibling | |
// 5: first child | |
// 6: last child | |
// @return Node: node or first node | |
context = context || doc.body; | |
var node = !source ? doc.createElement("div") // [1] uu.node.add() | |
: source.nodeType ? source // [3][5] uu.node.add(Node or DocumentFragment) | |
: !source.indexOf("<") ? uunodebulk(source, context) // [4] uu.node.add(HTMLFragmentString) | |
: doc.createElement(source), // [2] uu.node.add("p") | |
parentNode = context.parentNode, | |
rv = (node.nodeType === 11) ? node.firstChild : node; // 11: DocumentFragment | |
// <div id="parent"> | |
// <div id="first">(position = 1) first sibling</div> | |
// <div id="prev"> (position = 2) prev sibling</div> | |
// <div id="ctx">context node | |
// | |
// <div id="firstChild">(position = 5) first child</div> | |
// <div></div> | |
// <div id="lastChild"> (position = 6) last child</div> | |
// | |
// </div> | |
// <div id="next"> (position = 3) next sibling</div> | |
// <div id="last"> (position = 4) last sibling</div> | |
// </div> | |
switch (position || 6) { | |
case 1: parentNode.insertBefore(node, parentNode.firstChild); break; // first sibling | |
case 2: parentNode.insertBefore(node, context); break; // prev sibling | |
case 3: parentNode.insertBefore(node, context.nextSibling); break; // next sibling | |
case 4: parentNode.appendChild(node); break; // last sibling | |
case 5: context.insertBefore(node, context.firstChild); break; // first child | |
case 6: context.appendChild(node); // last child | |
} | |
return rv; | |
} | |
// uu.nodeid - get nodeid | |
function uunodeid(node) { // @param Node: | |
// @return Number: nodeid, from 1 | |
if (!node.uuguid) { | |
uunodeid._db[node.uuguid = ++uunodeid._num] = node; | |
} | |
return node.uuguid; | |
} | |
uunodeid._num = 0; // node id counter | |
uunodeid._db = {}; // { nodeid: node, ... } | |
// uu.nodeid.toNode - get node by nodeid | |
function uunodeidtonode(nodeid) { // @param String: nodeid | |
// @return Node/void: | |
return uunodeid._db[nodeid]; | |
} | |
// uu.nodeid.remove - remove from node db | |
function uunodeidremove(node) { // @param Node: | |
// @return Node: removed node | |
node.uuguid && (uunodeid._db[node.uuguid] = null, node.uuguid = null); | |
return node; | |
} | |
// uu.node.has - has child node | |
function uunodehas(node, // @param Node: child node | |
context) { // @param Node: context(parent) node | |
// @return Boolean: | |
for (var c = node; c && c !== context;) { | |
c = c.parentNode; | |
} | |
return node !== context && c === context; | |
} | |
// [1][clone] uu.node.bulk(Node) -> DocumentFragment | |
// [2][build] uu.node.bulk("<p>html</p>") -> DocumentFragment | |
// uu.node.bulk - convert HTMLString into DocumentFragment | |
function uunodebulk(source, // @param Node/HTMLFragment: source | |
context) { // @param Node/TagString(= "div"): context | |
// @return DocumentFragment: | |
context = context || "div"; | |
var rv = doc.createDocumentFragment(), | |
placeholder = context.nodeType ? context : uunode(context); | |
placeholder.innerHTML = source.nodeType ? source.outerHTML // [1] node | |
: source; // [2] "<p>html</p>" | |
while (placeholder.firstChild) { | |
rv.appendChild(placeholder.removeChild(placeholder.firstChild)); | |
} | |
return rv; | |
} | |
// uu.node.swap - swap node | |
function uunodeswap(swapin, // @param Node: swapin | |
swapout) { // @param Node: swapout | |
// @return Node: swapout | |
return swapout.parentNode.replaceChild(swapin, swapout); | |
} | |
// [1][wrap] uu.node.wrap(<span>target</span>, <p>) | |
// <span>target</span> -> <p><span>target</span></p> | |
// uu.node.wrap - wrapper | |
function uunodewrap(innerNode, // @param Node: inner node | |
outerNode) { // @param Node: wrapper, outer node | |
// @return Node: innerNode | |
return outerNode.appendChild(uunodeswap(outerNode, innerNode)); | |
} | |
// uu.node.build - node builder | |
// [1][add node] uu.div(uu.div()) | |
// [2][add text node] uu.div("hello") | |
// [3][add text node] uu.div(uu.text("hello")) | |
// [4][id callback] uu.div("@buildid") - window.xnode(uu, <div>, {{"buildid"}}, nodeid) | |
// [5][number callback] uu.div(1) - window.xnode(uu, <div>, {{1}}, nodeid) | |
// [6][set attr by string] uu.div("title,hello") - first String is uu.attr("title,hello") | |
// [7][set attr by hash] uu.div({ title: "hello" }) - first Hash is uu.attr({ title: "hello" }) | |
// [8][set css by string] uu.div("", "color,red") - second String is uu.css("color,red") | |
// [9][set css by hash] uu.div("", { color: "red" }) - second Hash is uu.css({ color: "red" }) | |
function uunodebuild(node, // @param Node/String: | |
args) { // @param Mix: arguments(nodes, attr/css) | |
// @return Node: | |
node.nodeType || (node = uu.node(node)); // "div" -> <div> | |
var arg, isString, w, i = 0, j = 0, iz = args.length, | |
xnode = uuisfunction(win.xnode) ? win.xnode : uu.nop; | |
for (; i < iz; ++i) { | |
w = 1; | |
arg = args[i]; | |
isString = typeof arg === "string"; | |
if (arg) { | |
if (isString) { // [2][4][6][8] | |
if (arg.indexOf(",") < 0 && w--) { // [2] | |
node.appendChild(doc.createTextNode(arg)); | |
} else if (arg.charAt(0) === "@" && w--) { // [4] | |
xnode(uu, node, arg.slice(1), uu.nodeid(node)); | |
} | |
} else if (arg.nodeType && w--) { | |
node.appendChild(arg); // [1][3] | |
} else if (typeof arg === "number" && w--) { // [5] | |
xnode(uu, node, arg, uu.nodeid(node)); | |
} | |
} | |
if (w) { | |
if (++j === 1) { | |
arg && uu.attr.set(node, isString ? uu.split.toHash(arg) : arg); // [6][7] | |
} else if (j === 2) { | |
arg && uu.css.set(node, isString ? uu.split.toHash(arg) : arg); // [8][9] | |
} | |
} | |
} | |
return node; | |
} | |
// [1][clear children] uu.node.clear(<body>) | |
// uu.node.clear - clear all children | |
function uunodeclear(context) { // @param Node: parent node | |
// @return Node: context | |
var rv = uutag("*", context), v, i = -1; | |
while ( (v = rv[++i]) ) { | |
uunodeidremove(v); | |
uueventunbind(v); | |
} | |
rv = []; // gc | |
while (context.firstChild) { | |
context.removeChild(context.firstChild); | |
} | |
return context; | |
} | |
// uu.node.remove - remove node | |
function uunoderemove(node) { // @param Node: | |
// @return Node: node | |
if (node && node.parentNode) { | |
uunodeidremove(node); | |
return node.parentNode.removeChild(node); | |
} | |
return node; | |
} | |
// uu.html | |
function uuhtml(/* var_args */) { // @param Mix: var_args | |
// @return Node: <html> node | |
return uunodebuild(doc.html, arguments); | |
} | |
// uu.head | |
function uuhead(/* var_args */) { // @param Mix: var_args | |
// @return Node: <head> node | |
return uunodebuild(doc.head, arguments); | |
} | |
// uu.body | |
function uubody(/* var_args */) { // @param Mix: var_args | |
// @return Node: <body> node | |
return uunodebuild(doc.body, arguments); | |
} | |
// [1][get text] uu.text(node) -> text or [text, ...] | |
// [2][set text] uu.text(node, "text") -> node | |
// uu.text - node.text / node.innerText accessor | |
function uutext(node, // @param Node/String: node or text string | |
text) { // @param String(= void): | |
// @return Array/String/Node: | |
if (uuisstring(node)) { | |
return doc.createTextNode(node); | |
} | |
if (text === void 0) { | |
return node[uu.gecko ? "textContent" : "innerText"]; | |
} | |
uunodeadd(doc.createTextNode(Array.isArray(text) ? text.join("") : text), | |
uunodeclear(node)); | |
return node; | |
} | |
// --- query --- | |
// uu.query - querySelectorAll | |
function uuquery(expression, // @param String: expression, "css > expr" | |
context) { // @param NodeArray/Node(= document): query context | |
// @return NodeArray: [Node, ...] | |
if (context && doc.querySelectorAll && context.nodeType | |
&& !uuquery._NGWORD.test(expression)) { // [:scope] guard | |
try { | |
var rv = [], | |
nodeList = (context || doc).querySelectorAll(expression), | |
i = 0, iz = nodeList.length; | |
for (; i < iz; ++i) { | |
rv[i] = nodeList[i]; | |
} | |
return rv; | |
} catch(err) {} // case: extend pseudo class / operators | |
} | |
return uuquery.selectorAll(expression, context || doc); // depend: uu.query | |
} | |
uuquery._NGWORD = /(:(a|b|co|dig|first-l|li|mom|ne|p|sc|t|v))|!=|\/=|<=|>=|&=|x7b/; | |
// uu.id - query id | |
function uuid(expression, // @param String: id | |
context) { // @param Node(= document): query context | |
// @return Node/null: | |
return (context || doc).getElementById(expression); | |
} | |
// uu.tag - query tagName | |
function uutag(expression, // @param String: "*" or "tag" | |
context) { // @param Node(= document): query context | |
// @return NodeArray: [Node, ...] | |
var nodeList = (context || doc).getElementsByTagName(expression), | |
rv = [], ri = -1, v, i = 0, iz = nodeList.length; | |
if (uu.ie && expression === "*") { // [IE] getElementsByTagName("*") has comment nodes | |
for (; i < iz; ++i) { | |
(v = nodeList[i]).nodeType === 1 && (rv[++ri] = v); // 1: ELEMENT_NODE | |
} | |
} else { | |
for (; i < iz; ++i) { | |
rv[i] = nodeList[i]; | |
} | |
} | |
return rv; | |
} | |
uutag.HTML4 = ("a,b,br,dd,div,dl,dt,h1,h2,h3,h4,h5,h6,i,img,iframe," + | |
"input,li,ol,option,p,pre,select,span,table,tbody,tr," + | |
"td,th,tfoot,textarea,u,ul").split(","); // exclude <html><head><body> | |
uutag.HTML5 = ("abbr,article,aside,audio,bb,canvas,datagrid,datalist," + | |
"details,dialog,eventsource,figure,footer,header,hgroup," + | |
"mark,menu,meter,nav,output,progress,section,time,video").split(","); | |
// uu.klass - query className | |
function uuklass(expression, // @param String: "class", "class1, ..." | |
context) { // @param Node(= document): query context | |
// @return NodeArray: [Node, ...] | |
context = context || doc; | |
var rv = [], ri = -1, i = 0, iz, v, | |
nodeList, match, cn, nz, rex, name; | |
if (context.getElementsByClassName) { | |
// Advanced browser route | |
nodeList = context.getElementsByClassName(expression); | |
for (iz = nodeList.length; i < iz; ++i) { | |
rv[i] = nodeList[i]; | |
} | |
} else { | |
// Legacy browser route | |
nodeList = context.getElementsByTagName("*"); | |
name = uusplit(expression); // "class1 class2" -> ["class1", "class2"] | |
name.length > 1 && (name = uuunique(name, 1)); // [FIX] W3C TestSuite #170b | |
rex = _classNameMatcher(name); | |
for (nz = name.length, iz = nodeList.length; i < iz; ++i) { | |
v = nodeList[i]; | |
cn = v.className; | |
if (cn) { | |
match = cn.match(rex); // [!] KEEP IT | |
(match && match.length >= nz) && (rv[++ri] = v); | |
} | |
} | |
} | |
return rv; | |
} | |
// --- string --- | |
// [1][css-prop to js-css-prop] uu.fix("background-color") -> "backgroundColor" | |
// [2][std-name to ie-name] uu.fix("float") -> "cssFloat" or "styleFloat"(IE) | |
// [3][html-attr to js-attr] uu.fix("for") -> "htmlFor" | |
// [4][through] uu.fix("-webkit-shadow") -> "-webkit-shadow" | |
// uu.fix - fix style property, attribute name | |
function uufix(source) { // @param String: source | |
// @return String: | |
return uufix._db[source] || source; | |
} | |
uufix._db = {}; // { "background-color": "backgroundColor", ... } | |
// uu.trim - trim both side whitespace | |
function uutrim(source) { // @param String: " has space " | |
// @return String: "has space" | |
return source.replace(uutrim._TRIM, ""); | |
} | |
uutrim._TAG = /<\/?[^>]+>/g; // <div> or </div> | |
uutrim._TRIM = /^\s+|\s+$/g; | |
uutrim._QUOTE = /^\s*["']?|["']?\s*$/g; //' | |
uutrim._SPACES = /\s\s+/g; | |
uutrim._BRACKET = /^\s*[\(\[\{<]?|[>\}\]\)]?\s*$/g; // [br](ac){ke}<ts> | |
// uu.trim.tag - trim.inner + strip tags | |
function uutrimtag(source) { // @param String: " <h1>A</h1> B <p>C</p> " | |
// @return String: "A B C" | |
return source.replace(uutrim._TRIM, ""). | |
replace(uutrim._TAG, ""). | |
replace(uutrim._SPACES, " "); | |
} | |
// uu.trim.url - trim.inner + strip "url(" ... ")" + trim.quote | |
function uutrimurl(source) { // @param String: ' url("http://...") ' | |
// @return String: "http://..." | |
return (!source.indexOf("url(") && source.indexOf(")") === source.length - 1) ? | |
source.slice(4, -1).replace(uutrim._QUOTE, "") : source; | |
} | |
// uu.trim.inner - trim + diet inside multi spaces | |
function uutriminner(source) { // @param String: " diet inner space " | |
// @return String: "diet inner space" | |
return source.replace(uutrim._TRIM, "").replace(uutrim._SPACES, " "); | |
} | |
// uu.trim.quote - trim + strip "double" 'single' quote | |
function uutrimquote(source) { // @param String: ' "quote string" ' | |
// @return String: 'quote string' | |
return source.replace(uutrim._QUOTE, ""); | |
} | |
// uu.trim.bracket - trim + strip brackets () [] {} <> | |
function uutrimbracket(source) { // @param String: " <bracket> (this) [and] {this} " | |
// @return String: "bracket this and this" | |
return source.replace(uutrim._BRACKET, ""); | |
} | |
// uu.split - split space | |
function uusplit(source) { // @param String: " split space token " | |
// @return Array: ["split", "space", "token"] | |
return source.replace(uutrim._SPACES, " "). | |
replace(uutrim._TRIM, "").split(" "); | |
} | |
uusplit._MANY_COMMAS = /,,+/g; // many commas | |
uusplit._TRIM_SPACE_AND_COMMAS = /^[ ,]+|[ ,]+$/g; // trim space and comma | |
// uu.split.comma - split commas | |
function uusplitcomma(source) { // @param String: ",,, ,,A,,,B,C,, " | |
// @return Array: ["A", "B", "C"] | |
return source.replace(uusplit._MANY_COMMAS, ","). | |
replace(uusplit._TRIM_SPACE_AND_COMMAS, "").split(","); | |
} | |
// [1][hash from string] uu.split.toHash("key,1,key2,1", ",") -> { key: 0, key2: 1 } | |
// uu.split.toHash - split to hash | |
function uusplittohash(source, // @param String: "key,0,key2,1" | |
splitter, // @param String(= ","): splitter | |
toNumber) { // @param Boolean(= false): convert value to number | |
// @return Hash: { key: "0", key2: "1" } | |
var rv = {}, ary = source.split(splitter || ","), i = 0, iz = ary.length, | |
num = toNumber ? true : false; | |
for (; i < iz; i += 2) { | |
rv[ary[i]] = num ? +(ary[i + 1]) : ary[i + 1]; | |
} | |
return rv; | |
} | |
// [1][placeholder] uu.format("? dogs and ?", 101, "cats") -> "101 dogs and cats" | |
// uu.format - placeholder( "?" ) replacement | |
function uuformat(format) { // @param String: formatted string with "?" placeholder | |
// @return String: "formatted string" | |
var i = 0, args = arguments; | |
return format.replace(uuformat._PLACEHOLDER, function() { | |
return args[++i]; | |
}); | |
} | |
uuformat._PLACEHOLDER = /\?/g; | |
// --- debug --- | |
// uu.puff - uu.puff(mix) -> alert( uu.json(mix) ) | |
function uupuff(source) { // @param Mix: source object | |
alert(_jsoninspect(source)); | |
} | |
// <div id="trace">msg<div> | |
// [1][with title] uu.trace(title, mix) -> <p>title{mix}</p> | |
// [2][without title] uu.trace(mix) -> <p>{mix}</p> | |
// uu.trace - add trace | |
function uutrace(titleOrSource, // @param String/Mix: title or source | |
source) { // @param Mix(= void): source (with title) | |
var output = uuid("trace"), json, title = ""; | |
if (output) { | |
if (source !== void 0) { | |
title = titleOrSource; | |
json = _jsoninspect(source); | |
} else { | |
json = _jsoninspect(titleOrSource); | |
} | |
if (output.tagName.toLowerCase() === "textarea") { | |
output.value += title + json; | |
} else { | |
output.innerHTML += "<p>" + title + json + "</p>"; | |
} | |
} | |
} | |
// uu.trace.clear - clear | |
function uutraceclear() { | |
var output = uuid("trace"); | |
if (output) { | |
if (output.tagName.toLowerCase() === "textarea") { | |
output.value = ""; | |
} else { | |
output.innerHTML = ""; | |
} | |
} | |
} | |
// --- JSON --- | |
// uu.json - mix to JSONString | |
function uujson(source, // @param Mix: | |
useNativeJSON, // @param Boolean(= false): switch native impl or js impl | |
// true is use native JSON | |
// false is use js JSON | |
callback) { // @param Function(= void): error callback | |
// @return JSONString: | |
return useNativeJSON && win.JSON ? win.JSON.stringify(source) || "" | |
: _jsoninspect(source, callback); | |
} | |
// uu.json.decode - decode JSONString | |
function uujsondecode(jsonString, // @param JSONString: | |
useNativeJSON) { // @param Boolean(= false): switch native impl or js impl | |
// true is use native JSON | |
// false is use js JSON | |
// @return Mix/Boolean: false is error | |
var str = uutrim(jsonString); | |
if (useNativeJSON && win.JSON) { | |
return win.JSON.parse(str); | |
} | |
return uujsondecode._NGWORD.test(str.replace(uujsondecode._UNESCAPE, "")) | |
? false : uujs("return " + str + ";"); | |
} | |
uujsondecode._NGWORD = /[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/; | |
uujsondecode._UNESCAPE = /"(\\.|[^"\\])*"/g; | |
// inner - convert string to JSON formatted string | |
function _str2json(str, // @param String: | |
addQuote) { // @param Number(= 0): 1 is add quote(") | |
// @return String: '\u0000' or '"\u0000"' | |
function _swap(m) { | |
return _str2json._SWAP[m]; | |
} | |
function _ucs2(str, c) { | |
c = str.charCodeAt(0); | |
// '\uffff' | |
return "\\u" + uuhash._num2hh[(c >> 8) & 255] + | |
uuhash._num2hh[ c & 255]; | |
} | |
var rv = str.replace(_str2json._ESCAPE, _swap). | |
replace(_str2json._ENCODE, _ucs2); | |
return addQuote ? '"' + rv + '"' : rv; | |
} | |
_str2json._SWAP = uusplittohash('",\\",\b,\\b,\f,\\f,\n,\\n,\r,\\r,\t,\\t,\\,\\\\'); | |
_str2json._ESCAPE = /(?:\"|\\[bfnrt\\])/g; // escape //" | |
_str2json._ENCODE = /[\x00-\x1F\u0080-\uFFEE]/g; | |
// inner - json inspect | |
function _jsoninspect(mix, fn) { | |
var ary, type = uutype(mix), w, ai = -1, i, iz; | |
if (mix === win) { | |
return '"window"'; // window -> String("window") | |
} | |
switch (type) { | |
case uutype.CSS: | |
case uutype.HASH: ary = []; break; | |
case uutype.NODE: return '"uuguid":' + uunodeid(mix); | |
case uutype.NULL: return "null"; | |
case uutype.VOID: return "undefined"; | |
case uutype.DATE: return uudate(mix).ISO(); | |
case uutype.BOOLEAN: | |
case uutype.FUNCTION: | |
case uutype.NUMBER: return mix.toString(); | |
case uutype.STRING: return _str2json(mix, 1); | |
case uutype.ARRAY: | |
case uutype.FAKEARRAY: | |
for (ary = [], i = 0, iz = mix.length; i < iz; ++i) { | |
ary[++ai] = _jsoninspect(mix[i], fn); | |
} | |
return "[" + ary + "]"; | |
default: | |
return fn ? (fn(mix) || "") : ""; | |
} | |
if (type === uutype.CSS) { | |
w = uu.webkit; | |
for (i in mix) { | |
if (typeof mix[i] === "string" && (w || i != (+i + ""))) { // !isNaN(i) | |
w && (i = mix.item(i)); | |
ary[++ai] = '"' + i + '":' + _str2json(mix[i], 1); | |
} | |
} | |
} else { // type === uutype.HASH | |
// if (mix.hasOwnProperty("toString")) { | |
// return _str2json(mix.toString(), 1); | |
// } | |
for (i in mix) { | |
ary[++ai] = _str2json(i, 1) + ":" + _jsoninspect(mix[i], fn); | |
} | |
} | |
return "{" + ary + "}"; | |
} | |
// --- date --- | |
// [1][get now] uu.date() -> DateHash | |
// [2][DateHash] uu.date(DateHash) -> cloned DateHash | |
// [2][date to hash] uu.date(Date) -> DateHash | |
// [3][time to hash] uu.date(milliseconds) -> DateHash | |
// [4][DateString to hash] uu.date("2000-01-01T00:00:00[.000]Z") -> DateHash | |
// [5][ISO8601String to hash] uu.date("2000-01-01T00:00:00[.000]Z") -> DateHash | |
// [6][RFC1123String to hash] uu.date("Wed, 16 Sep 2009 16:18:14 GMT") -> DateHash | |
// uu.date - date accessor | |
function uudate(source) { // @param DateHash/Date/Number/String(= void): | |
// @return DateHash: | |
return source === void 0 ? _date2hash(new Date()) // [1] uu.date() | |
: uuisdate(source) ? _date2hash(source) // [3] uu.date(new Date()) | |
: uuisnumber(source) ? _date2hash(new Date(source)) // [4] uu.date(1234567) | |
: source.GMT ? uuclone(source) // [2] uu.date(DateHash) | |
: _date2hash(_str2date(source) || new Date(source)); // [5][6][7] | |
} | |
// inner - convert Date to DateHash | |
function _date2hash(date) { // @param Date: | |
// @return Hash: { Y: 2010, M: 12, D: 31, | |
// h: 23, m: 59, s: 59, ms: 999, | |
// time: xxxxxxx, ISO, RFC, GMT } | |
return { | |
Y: date.getUTCFullYear(), M: date.getUTCMonth() + 1, | |
D: date.getUTCDate(), h: date.getUTCHours(), | |
m: date.getUTCMinutes(), s: date.getUTCSeconds(), | |
ms: date.getUTCMilliseconds(), time: date.getTime(), | |
ISO: datehashiso, | |
RFC: datehashrfc, | |
GMT: datehashrfc | |
}; | |
} | |
// "2000-01-01T00:00:00[.000]Z" -> Date | |
// "Wed, 16 Sep 2009 16:18:14 GMT" -> Date | |
// inner - DateString to Date | |
function _str2date(str) { // @param ISO8601DateString/RFC1123DateString: | |
// @return Date: | |
function _toDate(_, dayOfWeek, day, month) { | |
return dayOfWeek + " " + month + " " + day; | |
} | |
var m = _str2date._PARSE.exec(str); | |
if (m) { | |
return new Date(Date.UTC(+m[1], +m[2] - 1, +m[3], // yyyy-mm-dd | |
+m[4], +m[5], +m[6], +m[7])); // hh:mm:ss.ms | |
} | |
if (uu.ie && str.indexOf("GMT") > 0) { | |
str = str.replace(/GMT/, "UTC"); | |
} | |
return new Date(str.replace(",", ""). | |
replace(_str2date._DATE, _toDate)); | |
} | |
_str2date._PARSE = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.(\d*))?Z$/; | |
_str2date._DATE = /^([\w]+) (\w+) (\w+)/; | |
// DateHash.ISO - encode DateHash To ISO8601String | |
function datehashiso() { // @return ISO8601DateString: "2000-01-01T00:00:00.000Z" | |
var padZero = (this.ms < 10) ? "00" : (this.ms < 100) ? "0" : "", | |
dd = uuhash._num2dd; | |
return uuformat("?-?-?T?:?:?.?Z", this.Y, dd[this.M], dd[this.D], | |
dd[this.h], dd[this.m], dd[this.s], | |
padZero + this.ms); | |
} | |
// DateHash.RFC - encode DateHash To RFC1123String | |
function datehashrfc() { // @return RFC1123DateString: "Wed, 16 Sep 2009 16:18:14 GMT" | |
var rv = (new Date(this.time)).toUTCString(); | |
if (uu.ie && rv.indexOf("UTC") > 0) { | |
// http://d.hatena.ne.jp/uupaa/20080515 | |
rv = rv.replace(/UTC/, "GMT"); | |
(rv.length < 29) && (rv = rv.replace(/, /, ", 0")); // [IE] fix format | |
} | |
return rv; | |
} | |
// --- other --- | |
// uu.js("JavaScript Expression") -> eval result | |
// uu.js - eval js | |
function uujs(javascriptExpression) { // @param String: | |
// @return Mix: new Function(expression) result | |
return (new Function(javascriptExpression))(); | |
} | |
// uu.win.size | |
function uuwinsize() { // @return Hash: { innerWidth, innerHeight, | |
// pageXOffset, pageYOffset } | |
// innerWidth - Number: | |
// innerHeight - Number: | |
// pageXOffset - Number: | |
// pageYOffset - Number: | |
if (uu.ie) { | |
var iebody = uu.quirks ? doc.body : uu.node.root; | |
return { innerWidth: iebody.clientWidth, | |
innerHeight: iebody.clientHeight, | |
pageXOffset: iebody.scrollLeft, | |
pageYOffset: iebody.scrollTop }; | |
} | |
return { innerWidth: win.innerWidth, | |
innerHeight: win.innerHeight, | |
pageXOffset: win.pageXOffset, // [WebKit][Alias] document.body.scrollLeft | |
pageYOffset: win.pageYOffset }; // [WebKit][Alias] document.body.scrollTop | |
} | |
// uu.guid - get unique number | |
function uuguid() { // @return Number: unique number, from 1 | |
return ++uuguid._num; | |
} | |
uuguid._num = 0; // guid counter | |
// uu.lazy - lazy evaluate | |
function uulazy(id, // @param String: id | |
evaluator, // @param Function: callback function | |
order) { // @param Number(= 0): 0=low, 1=mid, 2=high(system) | |
uulazy._db[id] || (uulazy._db[id] = [[], [], []]); | |
uulazy._db[id][order || 0].push(evaluator); | |
} | |
uulazy._db = {}; // { id: [[low], [mid], [high]], ... } job db | |
// uu.lazy.fire | |
function uulazyfire(id) { // @param String: lazy id | |
if (uulazy._db[id]) { | |
var fn, i = -1, db = uulazy._db[id], | |
ary = db[2].concat(db[1], db[0]); // join | |
// pre clear | |
uulazy._db[id] = null; | |
// callback | |
while ( (fn = ary[++i]) ) { | |
fn(uu); | |
} | |
} | |
} | |
// --- ECMAScript-262 5th --- | |
//{{{!mb | |
// Array.prototype.indexOf | |
function arrayindexof(search, // @param Mix: search element | |
fromIndex) { // @param Number(= 0): from index | |
// @return Number: found index or -1 | |
var iz = this.length, i = fromIndex || 0; | |
i = (i < 0) ? i + iz : i; | |
for (; i < iz; ++i) { | |
if (i in this && this[i] === search) { | |
return i; | |
} | |
} | |
return -1; | |
} | |
// Array.prototype.lastIndexOf | |
function arraylastindexof(search, // @param Mix: search element | |
fromIndex) { // @param Number(= this.length): from index | |
// @return Number: found index or -1 | |
var iz = this.length, i = fromIndex; | |
i = (i < 0) ? i + iz + 1 : iz; | |
while (--i >= 0) { | |
if (i in this && this[i] === search) { | |
return i; | |
} | |
} | |
return -1; | |
} | |
// Array.prototype.every | |
function arrayevery(evaluator, // @param Function: evaluator | |
that) { // @param this(= void): evaluator this | |
// @return Boolean: | |
for (var i = 0, iz = this.length; i < iz; ++i) { | |
if (i in this && !evaluator.call(that, this[i], i, this)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
// Array.prototype.some | |
function arraysome(evaluator, // @param Function: evaluator | |
that) { // @param this(= void): evaluator this | |
// @return Boolean: | |
for (var i = 0, iz = this.length; i < iz; ++i) { | |
if (i in this && evaluator.call(that, this[i], i, this)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
// Array.prototype.forEach | |
function arrayforeach(evaluator, // @param Function: evaluator | |
that) { // @param this(= void): evaluator this | |
var i = 0, iz = this.length; | |
if (that) { | |
for (; i < iz; ++i) { | |
i in this && evaluator.call(that, this[i], i, this); | |
} | |
} else { | |
for (; i < iz; ++i) { | |
i in this && evaluator(this[i], i, this); | |
} | |
} | |
} // [OPTIMIZED] | |
// Array.prototype.map | |
function arraymap(evaluator, // @param Function: evaluator | |
that) { // @param this(= void): evaluator this | |
// @return Array: [element, ... ] | |
for (var iz = this.length, rv = Array(iz), i = 0; i < iz; ++i) { | |
i in this && (rv[i] = evaluator.call(that, this[i], i, this)); | |
} | |
return rv; | |
} | |
// Array.prototype.filter | |
function arrayfilter(evaluator, // @param Function: evaluator | |
that) { // @param this(= void): evaluator this | |
// @return Array: [element, ... ] | |
for (var rv = [], ri = -1, v, i = 0, iz = this.length; i < iz; ++i) { | |
i in this && evaluator.call(that, v = this[i], i, this) | |
&& (rv[++ri] = v); | |
} | |
return rv; | |
} | |
//}}}!mb | |
// Array.prototype.reduce | |
function arrayreduce(evaluator, // @param Function: evaluator | |
initialValue) { // @param Mix(= void): initial value | |
// @return Mix: | |
var z, f = 0, rv = initialValue === z ? z : (++f, initialValue), | |
i = 0, iz = this.length; | |
for (; i < iz; ++i) { | |
i in this && (rv = f ? evaluator(rv, this[i], i, this) : (++f, this[i])); | |
} | |
if (!f) { | |
throw new Error(arrayreduce._MSG); | |
} | |
return rv; | |
} | |
arrayreduce._MSG = "reduce of empty array with no initial value"; | |
// Array.prototype.reduceRight | |
function arrayreduceright(evaluator, // @param Function: evaluator | |
initialValue) { // @param Mix(= void): initial value | |
// @return Mix: | |
var z, f = 0, rv = initialValue === z ? z : (++f, initialValue), | |
i = this.length; | |
while (--i >= 0) { | |
i in this && (rv = f ? evaluator(rv, this[i], i, this) : (++f, this[i])); | |
} | |
if (!f) { | |
throw new Error(arrayreduce._MSG); | |
} | |
return rv; | |
} | |
// Date.prototype.toISOString - to ISO8601 string | |
function datetoisostring() { // @return String: | |
return uudate(this).ISO(); | |
} | |
// Number.prototype.toJSON, Boolean.prototype.toJSON | |
function numbertojson() { // @return String: "123", "true", "false" | |
return this.toString(); | |
} | |
// String.prototype.trim | |
function stringtrim() { // @return String: "has space" | |
return this.replace(uutrim._TRIM, ""); | |
} | |
// String.prototype.toJSON | |
function stringtojson() { // @return String: "string" | |
return _str2json(this); | |
} | |
// --- HTMLElement.prototype --- | |
//{{{!mb | |
// HTMLElement.prototype.innerText getter | |
function innertextgetter() { | |
return this.textContent; | |
} | |
// HTMLElement.prototype.innerText setter | |
function innertextsetter(text) { | |
while (this.hasChildNodes()) { | |
this.removeChild(this.lastChild); | |
} | |
this.appendChild(doc.createTextNode(text)); | |
} | |
// HTMLElement.prototype.outerHTML getter | |
function outerhtmlgetter() { | |
var rv, that = this, p = that.parentNode, | |
r = doc.createRange(), div = doc.createElement("div"); | |
p || doc.body.appendChild(that); // orphan | |
r.selectNode(that); | |
div.appendChild(r.cloneContents()); | |
rv = div.innerHTML; | |
p || that.parentNode.removeChild(that); | |
return rv; | |
} | |
// HTMLElement.prototype.outerHTML setter | |
function outerhtmlsetter(html) { | |
var r = doc.createRange(); | |
r.setStartBefore(this); | |
this.parentNode.replaceChild(r.createContextualFragment(html), this); | |
} | |
//}}}!mb | |
// --- initialize --- | |
// inner - build DOM Lv2 event handler - uu.click(), ... | |
uuevent._LIST.forEach(function(eventType) { | |
uu[eventType] = function bindEvent(node, fn) { // uu.click(node, fn) -> node | |
return uuevent(node, eventType, fn); // attach | |
}; | |
uu["un" + eventType] = function unbindEvent(node) { // uu.unclick(node) -> node | |
return uuevent(node, eventType, 0, true); // detach | |
}; | |
}); | |
// inner - setup node builder - uu.div(), uu.a(), ... | |
uutag.HTML4.forEach(function(v) { | |
// skip "img", "canvas", "audio" | |
if (v === "img" || v === "canvas") { | |
return; | |
} | |
uu[v] = function html4NodeBuilder() { // @param Mix: var_args | |
return uunodebuild(v, arguments); | |
}; | |
}); | |
uutag.HTML5.forEach(function(v) { | |
uu.ie && doc.createElement(v); // [IE] | |
uu[v] = function html5NodeBuilder() { // @param Mix: var_args | |
return uunodebuild(v, arguments); | |
}; | |
}); | |
// Internet Explorer 6 flicker fix | |
try { | |
uu.ver.ie6 && doc.execCommand("BackgroundImageCache", false, true); | |
} catch(err) {} // ignore error(IETester / stand alone IE too) | |
// --- window.onload handler --- | |
function _WindowwOnLoad() { | |
uuready.gone.win = 1; | |
_DOMContentLoaded(); | |
win.xwin && win.xwin(uu); // window.xwin(uu) callback | |
uulazyfire("canvas"); | |
uulazyfire("audio"); | |
uulazyfire("video"); | |
} | |
uueventattach(win, "load", _WindowwOnLoad); | |
// --- DOMContentLoaded handler --- | |
function _DOMContentLoaded() { | |
if (!uuready.gone.blackout && !uuready.gone.dom++) { | |
uulazyfire("boot"); | |
win.xboot && win.xboot(uu); // window.xboot(uu) callback | |
} | |
} | |
// inner - hook DOMContentLoaded for IE6 IE7 IE8 | |
function _IEDOMContentLoaded() { | |
try { | |
// trick -> http://d.hatena.ne.jp/uupaa/20100410/1270882150 | |
new Image.doScroll(); | |
_DOMContentLoaded(); | |
} catch(err) { | |
setTimeout(_IEDOMContentLoaded, 64); | |
} | |
} | |
uu.ver.ie678 ? _IEDOMContentLoaded() | |
: uueventattach(doc, "DOMContentLoaded", _DOMContentLoaded); | |
// --- finalize --- | |
//{{{!mb | |
// inner - [IE] fix mem leak | |
function _WindowOnUnload() { | |
var nodeid, node, ary, i, v; | |
for (nodeid in uunodeid._db) { | |
try { | |
node = uunodeid._db[nodeid]; | |
ary = node.attributes, i = -1; | |
while ( (v = ary[++i]) ) { | |
!v.name.indexOf("uu") && (node[v.name] = null); | |
} | |
} catch (err) {} | |
} | |
doc.html = null; | |
doc.head = null; | |
win.detachEvent("onload", _WindowwOnLoad); | |
win.detachEvent("onunload", _WindowOnUnload); | |
} | |
uu.ie && win.attachEvent("onunload", _WindowOnUnload); | |
//}}}!mb | |
// inner - | |
// 1. prebuild camelized hash - http://handsout.jp/slide/1894 | |
// 2. prebuild nodeid | |
uuready(function() { | |
var nodeList = doc.html.getElementsByTagName("*"), v, i = -1, | |
styles = uusplittohash((uu.ie ? "float,styleFloat,cssFloat,styleFloat" | |
: "float,cssFloat,styleFloat,cssFloat") + | |
",pos,position,w,width,h,height,x,left,y,top,o,opacity," + | |
"bg,background,bgcolor,backgroundColor,bgimg,backgroundImage," + | |
"bgrpt,backgroundRepeat,bgpos,backgroundPosition"); | |
uumix(_camelhash(uufix._db, uu.webkit ? uustyle(doc.html) | |
: doc.html.style), | |
styles, uuattr._HASH); | |
uunodeid(doc.html); | |
while ( (v = nodeList[++i]) ) { | |
v.nodeType === 1 && uunodeid(v); // 1: ELEMENT_NODE | |
} | |
}, 2); // 2: high(system) order | |
// inner - make camelized hash( { "text-align": "TextAlign", ...}) from getComputedStyle | |
function _camelhash(rv, props) { | |
function _camelize(m, c) { | |
return c.toUpperCase(); | |
} | |
function _decamelize(m, c, C) { | |
return c + "-" + C.toLowerCase(); | |
} | |
var k, v, CAMELIZE = /-([a-z])/g, DECAMELIZE = /([a-z])([A-Z])/g; | |
for (k in props) { | |
if (typeof props[k] === "string") { | |
if (uu.webkit) { | |
v = k = props.item(k); // k = "-webkit-...", "z-index" | |
k.indexOf("-") >= 0 && (v = k.replace(CAMELIZE, _camelize)); | |
(k !== v) && (rv[k] = v); | |
} else { | |
v = ((uu.gecko && !k.indexOf("Moz")) ? "-moz" + k.slice(3) : | |
(uu.ie && !k.indexOf("ms")) ? "-ms" + k.slice(2) : | |
(uu.opera && !k.indexOf("O")) ? "-o" + k.slice(1) : k). | |
replace(DECAMELIZE, _decamelize); | |
(k !== v) && (rv[v] = k); | |
} | |
} | |
} | |
return rv; | |
} | |
// inner - make className matcher from array | |
function _classNameMatcher(ary) { | |
return RegExp("(?:^| )(" + ary.join("|") + ")(?:$|(?= ))", "g"); | |
} | |
// inner - make String <-> Number mapping table | |
function _makeMapping(seed, // @param String: "0123456789" or "0123456789abcdef" | |
s2n, // @param Hash: String to Number | |
n2s) { // @param Hash: Number to String | |
var i = 0, j, k = -1, v, ary = seed.split(""), iz = ary.length; | |
for (; i < iz; ++i) { | |
for (j = 0; j < iz; ++j) { | |
v = ary[i] + ary[j]; | |
s2n[v] = ++k; // { "00": 0, "01": 1, ... "ff": 255 } | |
n2s[k] = v; // { 0: 0, 1: 1, ... 255: "ff" } | |
} | |
} | |
} | |
// inner - detect versions and meta informations | |
function _version(libraryVersion) { // @param Number: Library version | |
// @return VersionHash: | |
// http://d.hatena.ne.jp/uupaa/20090603 | |
function detectRenderingEngineVersion(userAgent) { | |
var ver = ((/(?:rv\:|ari\/|sto\/)(\d+\.\d+(\.\d+)?)/.exec(userAgent) | |
|| [,0])[1]).toString() | |
return parseFloat(ver.replace(/[^\d\.]/g, ""). | |
replace(/^(\d+\.\d+)(\.(\d+))?$/,"$1$3")); | |
} | |
function detectUserAgentVersion(userAgent) { | |
var opera = window.opera || false; | |
return opera ? +(opera.version().replace(/\d$/, "")) | |
: parseFloat((/(?:IE |fox\/|ome\/|ion\/)(\d+\.\d)/. | |
exec(userAgent) || [,0])[1]); | |
} | |
// detect Flash version (version 7 ~ later) | |
function detectFlashVersion(ie) { | |
var rv = 0, obj, ver, m; | |
//{{{!mb | |
try { | |
obj = ie ? new ActiveXObject("ShockwaveFlash.ShockwaveFlash") | |
: navigator.plugins["Shockwave Flash"]; | |
ver = ie ? obj.GetVariable("$version").replace(/,/g, ".") | |
: obj.description; | |
m = /\d+\.\d+/.exec(ver); | |
rv = m ? parseFloat(m[0]) : 0; | |
} catch(err) {} | |
//}}}!mb | |
return rv < 7 ? 0 : rv; | |
} | |
// detect Silverlight version (version 3 ~ later) | |
function detectSilverlightVersion(ie) { | |
var rv = 0, obj, check = 3; | |
//{{{!mb | |
try { | |
if (ie) { | |
obj = new ActiveXObject("AgControl.AgControl"); | |
while (obj.IsVersionSupported(check + ".0")) { // "3.0" -> "4.0" -> ... | |
rv = check++; | |
} | |
} else { | |
obj = navigator.plugins["Silverlight Plug-In"]; | |
rv = parseInt(/\d+\.\d+/.exec(obj.description)[0]); | |
} | |
} catch(err) {} | |
//}}}!mb | |
return rv < 3 ? 0 : rv; | |
} | |
var rv = { library: libraryVersion }, | |
ie = !!doc.uniqueID, userAgent = navigator.userAgent; | |
rv.render = detectRenderingEngineVersion(userAgent); | |
rv.browser = detectUserAgentVersion(userAgent); | |
rv.flash = detectFlashVersion(ie); | |
rv.silverlight = detectSilverlightVersion(ie); | |
rv.ie = ie; | |
rv.ie6 = ie && rv.browser === 6; | |
rv.ie7 = ie && rv.browser === 7; | |
rv.ie8 = ie && (doc.documentMode || 0) === 8; | |
rv.ie9 = ie && (doc.documentMode || 0) === 9; | |
rv.ie67 = rv.ie6 || rv.ie7; | |
rv.ie678 = rv.ie6 || rv.ie7 || rv.ie8; | |
rv.ie89 = rv.ie8 || rv.ie9; | |
rv.opera = !!(window.opera || false); | |
rv.gecko = userAgent.indexOf("Gecko/") > 0; | |
rv.webkit = userAgent.indexOf("WebKit") > 0; | |
rv.chrome = userAgent.indexOf("Chrome") > 0; | |
rv.safari = !rv.chrome && userAgent.indexOf("Safari") > 0; | |
rv.iphone = rv.webkit && /iPad|iPod|iPhone/.test(userAgent); | |
rv.quirks = (doc.compatMode || "") !== "CSS1Compat"; | |
rv.xml = uunode("div").tagName === uunode("DIV").tagName; | |
rv.win = userAgent.indexOf("Win") > 0; | |
rv.mac = userAgent.indexOf("Mac") > 0; | |
rv.unix = /X11|Linux/.test(userAgent); | |
rv.as3 = rv.flash >= 9; // ActionScript 3, FlashPlayer 9+ | |
rv.advanced = (ie && rv.browser >= 9) || // IE 9+ | |
(rv.gecko && rv.render > 1.9) || // Firefox 3.5+(1.91) | |
(rv.webkit && rv.render >= 528) || // Safari 4+, Google Chrome 2+ | |
(rv.opera && rv.browser >= 10.5); // Opera10.50+ | |
rv.major = (ie && rv.browser >= 6) || // IE 6+ | |
(rv.opera && rv.browser >= 9.5) || // Opera 9.5+ | |
(rv.gecko && rv.render >= 1.9) || // Firefox 3+ | |
(rv.webkit && rv.render > 524); // Safari 3.1+, Google Chrome 1+ | |
rv.jit = rv.advanced; | |
return rv; | |
} | |
})(window, document); | |
// === font === | |
//{{{!depend uu | |
//}}}!depend | |
uu.font || (function(win, doc, uu) { | |
var _BASE_STYLE = "position:absolute;border:0 none;margin:0;padding:0;"; | |
uu.font = { | |
parse: fontparse, // uu.font.parse(font, embase) -> Hash | |
detect: fontdetect, // uu.font.detect(node) -> String("Alial") | |
metric: fontmetric, // uu.font.text(font, text) -> { w, h } | |
ready: fontready, // uu.font.ready(fonts) -> Array | |
SCALE: { | |
//{{{!mb | |
ARIAL: 1.55, "ARIAL BLACK": 1.07, "COMIC SANS MS": 1.15, | |
"COURIER NEW": 1.6, GEORGIA: 1.6, "LUCIDA GRANDE": 1, | |
"LUCIDA SANS UNICODE": 1, "TIMES NEW ROMAN": 1.65, | |
"TREBUCHET MS": 1.55, VERDANA: 1.4, | |
"MS UI GOTHIC": 2, "MS PGOTHIC": 2, MEIRYO: 1, | |
//}}}!mb | |
"SANS-SERIF": 1, SERIF: 1, MONOSPACE: 1, FANTASY: 1, CURSIVE: 1 | |
} | |
}; | |
// uu.font.parse - parse CSS::font style | |
//ja CSS スタイルのフォント文字列をパースする | |
function fontparse(font, // @param String: font string, "12pt Arial" | |
embase) { // @param Node: The em base node | |
// @return Hash: | |
// inner - measure em unit | |
function _em(node) { | |
var rv, div = node.appendChild(uu.node()); | |
div.style.cssText = _BASE_STYLE + "width:12em"; | |
rv = div.clientWidth / 12; | |
node.removeChild(div); | |
return rv; | |
} | |
var rv = {}, fontSize, style, | |
cache = embase.uucanvascache || | |
(embase.uucanvascache = { font: {}, em: _em(embase) }); | |
if (!cache.font[font]) { | |
// --- parse font string --- | |
style = uu.node().style; // dummy element | |
try { | |
style.font = font; // parse | |
} catch (err) { | |
throw err; | |
} | |
fontSize = style.fontSize; // get font-size | |
rv.size = fontparse._sizes[fontSize]; | |
if (rv.size) { // "small", "large" ... | |
rv.size *= 16; | |
} else if (fontSize.lastIndexOf("px") > 0) { // "12px" | |
rv.size = parseFloat(fontSize); | |
} else if (fontSize.lastIndexOf("pt") > 0) { // "12.3pt" | |
rv.size = parseFloat(fontSize) * 1.33; | |
} else if (fontSize.lastIndexOf("em") > 0) { // "10.5em" | |
rv.size = parseFloat(fontSize) * cache.em; | |
} else { | |
throw new Error("unknown font unit"); | |
} | |
rv.style = style.fontStyle; // normal, italic, oblique | |
rv.weight = style.fontWeight; // normal, bold, bolder, lighter, 100~900 | |
rv.variant = style.fontVariant; // normal, small-caps | |
rv.rawfamily = style.fontFamily.replace(/[\"\']/g, ""); //" | |
rv.family = "'" + rv.rawfamily.replace(/\s*,\s*/g, "','") + "'"; | |
rv.formal = [rv.style, | |
rv.variant, | |
rv.weight, | |
rv.size.toFixed(2) + "px", | |
rv.family].join(" "); | |
cache.font[font] = rv; // add cache | |
} | |
return cache.font[font]; | |
} | |
fontparse._sizes = { | |
"xx-small": 0.512, | |
"x-small": 0.64, | |
smaller: 0.8, | |
small: 0.8, | |
medium: 1, | |
large: 1.2, | |
larger: 1.2, | |
"x-large": 1.44, | |
"xx-large": 1.728 | |
}; | |
// uu.font.detect - detect the rendering font | |
//ja レンダリングに使用されているフォントを特定する | |
function fontdetect(node) { // @param Node: | |
// @return String: detected font, eg: "serif" | |
var fam = uu.style.quick(node).fontFamily, | |
ary = uu.split.token(fam, ","), v, i = -1, | |
a, b = fontmetric("72pt " + fam); | |
while ( (v = ary[++i]) ) { | |
a = fontmetric("72pt " + v); | |
if (a.w === b.w && a.h === b.h) { | |
return v; // match | |
} | |
} | |
return ""; | |
} | |
// uu.font.metric - measure text rect(width, height) | |
//ja レンダリング時の幅と高さを返す | |
function fontmetric(font, // @param CSSFronString: "12pt Arial" | |
text) { // @param String(= "aABCDEFGHIJKLMm"): | |
// @return Hash: { w, h } | |
var node = fontmetric._node; | |
if (!node) { | |
fontmetric._node = node = uu.node(); | |
node.style.cssText = _BASE_STYLE + | |
"top:-10000px;left:-10000px;text-align:left;visibility:hidden"; | |
doc.body.appendChild(node); | |
} | |
node.style.font = font; | |
node[uu.gecko ? "textContent" | |
: "innerText"] = text || "aABCDEFGHIJKLMm"; | |
return { w: node.offsetWidth, | |
h: node.offsetHeight }; | |
} | |
fontmetric._node = 0; // [lazy] measure node | |
// uu.font.ready - enum usable font | |
//ja レンダリングに利用可能なフォントを列挙する | |
function fontready(fonts) { // @param FontNameArray: ["Arial", "Times New Roman", "UnknownFontName"] | |
// @return Array: ["Arial", "Times New Roman"] | |
var rv = [], i = 0, iz = fonts.length, a, b; | |
for (; i < iz; ++i) { | |
a = fontmetric("72pt dummy"); | |
b = fontmetric("72pt " + fonts[i]); | |
if (a.w !== b.w || a.h !== b.h) { | |
rv.push(fonts[i]); | |
} | |
} | |
return rv; | |
} | |
})(window, document, uu); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://gist.github.com/882213/dc9d6f52cc83733d6342bdc50c6b9f9f83c21612
String = convApp.str_simpl2ortho(String) //舊字の選択肢が一つのみの字を、舊字へ
を追加。
旧ver.
俗字⇒正字変換機 - c4se記:さっちゃんですよ☆ http://d.hatena.ne.jp/Kureduki_Maari/20090519/1242715608
俗字⇒正字変換機 0.2 - c4se記:さっちゃんですよ☆ http://d.hatena.ne.jp/Kureduki_Maari/20090817/1250464485
俗字←→正字、相互変換出来る様にしたよ! #c4se - c4se記:さっちゃんですよ☆ http://d.hatena.ne.jp/Kureduki_Maari/20100212/1265937568
convApp 0.4 フォントを知ってる正字⇔俗字変換機 #javascript - c4se記:さっちゃんですよ☆ http://d.hatena.ne.jp/Kureduki_Maari/20100413/1271113925