/* ======================================================================== * @license The MIT License * * http://www.opensource.org/licenses/mit-license.php * * @author Yoshiaki Sugimoto * @copyright Neo,Inc * @version ,v 0.7.1 * * ======================================================================== */ /* ======================================================================== * Animation easing functions * * http://www.robertpenner.com/easing/ * * TERMS OF USE - EASING EQUATIONS * * Open source under the BSD License. * Copyright © 2001 Robert Penner All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ========================================================================= */ (typeof FL_CONFIG === 'object') ? (function(initTime, doc, win, LOC, UA) { // 重複ロード禁止 if (win.getInstance) { return; } // =================== このスコープで使う変数定義 ========================== / // SYSTEM : システム内部で保持するデータやフラグ var SYSTEM = { INITIAL_TIME : initTime, DOM_CREATE_TIME : 0, WINDOW_LOADED_TIME : 0, SSL_CONNECT : (LOC.protocol === 'https:'), GLOBAL_EVAL : win.eval, CONTROLLER : null, CONTROLLER_NAME : '', EXEC_METHOD : null, METHOD_ARGUMENTS : {}, WINDOW_LOADED : false, START_CONTROLLER : null, BENCH_MARKS : {}, DOM_LOADED : false, CURRENT_ZINDEX : 1, XHR_RESPONSES : { READY_STATE : { 1 : 'LOADING', 2 : 'LOADED', 3 : 'INTERACTIVE', 4 : 'COMPLETED'}, STATUS : {403 : 'PERMISSION ERROR', 404 : 'NOT FOUND', 500 : 'SERVER ERROR', 503 : 'INTERNAL SERVER ERROR', 200 : 'OK', 999 : 'UNDEFINED'} }, /* * POSITION_FIX for IE6 * position:static -- 1 * position:relative -- 2 * position:absolute -- 3 * position:fixed -- 4 */ POSITION_STATIC : 1, POSITION_RELATIVE : 2, POSITION_ABSOLUTE : 3, POSITION_FIXED : 4, POSITION : {'static' : 1, 'relative' : 2, 'absolute' : 3, 'fixed' : 4} }, // STACK : 拡張xElementやxNodeList、イベントハンドラーを保持 STACK = { LOADED_CORE_CLASSES : {}, ELEMENTS : {}, EVENT_HANDLERS : [], LOADED_FUNCS : [], DOM_LOADED_FUNCS : [], INSTANCED_API : {}, CONFIG : {}, GLOBAL_LAYER : null, CAMELED_PROP : {}, DECAMELED_PROP : {}, API_STACK : [], CSS_STACK : [], API_READY : {}, MODULE_READY : {}, API_READY_FUNC : {}, MODULE_READY_FUNC : {}, BENCH_MARKS : {}, AJAX_EVENTS : [], AJAX_QUEUE : [], DEFFERD : {} }, // 内部取り込み用CONFIGオブジェクト CORE_CONFIG = {}, // ループ用変数 I, // 拡張エレメントインデックスID EXID = 0, // 検索回避ID ignoreID = 0, // 状態管理ID DEFFERD_ID = 0, // ========================= グローバルメソッド等のalias ============== / head = doc.head || doc.getElementsByTagName('head')[0], body, html = doc.documentElement || doc.getElementsByTagName('html')[0], pi = win.parseInt, pf = win.parseFloat, mr = Math.round, abs = Math.abs, sin = Math.sin, cos = Math.cos, mp = Math.pow, enc = win.encodeURIComponent, dec = win.decodeURIComponent, delay = win.setTimeout, unDelay = win.clearTimeout, interval = win.setInterval, unInterval = win.clearInterval, defWinWidth = win.innerWidth || 0, defWinHeight = win.innerHeight || 0, SSLURI, SITEURI, indexReg = /index\.php\/?/, MODULES = {}, COMPUTED_STYLE = (doc.defaultView && doc.defaultView.getComputedStyle) ? doc.defaultView.getComputedStyle : null, // ========================= クラスオブジェクト用内部変数 ================= / DOM, ua, ut, enables, Animation, Timer, connect, disConnect, Controller, Model, Base, IEFIX, // IE拡張用擬似グローバルオブジェクト CUSTOM_EVENT, DEFFERD_CONTROLLER, // ========================= 内部パラメータ =================================== / // Color Regexes COLOR_REGEX = { rgb : /^rgb\(([0-9]{1,3}),([0-9]{1,3}),([0-9]{1,3})\)$/, rgba : /^rgba\(([0-9]{1,3}),([0-9]{1,3}),([0-9]{1,3}),([0-9\.]+)\)$/, hex : /^#([0-9a-zA-Z]{3,6})$/, hsl : /^hsl\(([0-9]+),([0-9]+)%,([0-9]+)%\)$/, hsla : /^hsla\(([0-9]+),([0-9]+)%,([0-9]+)%,([0-9\.]+)\)$/ }, // IE6,7用属性変換マップ IE_MAP = { 'class' : 'className', 'for' : 'htmlFor', 'colspan' : 'colSpan', 'rowspan' : 'rowSpan', 'acesskey' : 'accessKey', 'tabindex' : 'tabIndex', 'frameborder' : 'frameBorder' }, ClassMap, // インライン要素マッピング用文字列 INLINE_ELEMENTS = 'span,em,strong,dfn,cide,abbr,acronym,q,sub,sup,br,a,img,input,select,textarea,label', BLOCK_ELEMENTS = 'div,h1,h2,h3,h4,h5,h6,address,blockquote,p,pre,ul,li,ol,dl,table,hr,form,fieldset', CSS_BG_REG = /^url\s?\(/, CoreTimer, // 内部タイマーインターバル INTERVAL_FPS, // 数値CSSマッピング NUMERIC_CSS = 'opacity,zIndex', EXT = '.js', // data-*独自属性プレフィックス HTML_DATA_PREFIX = 'data-fl-', // Keymapperモジュール用キーマップ KEY_MAP = { DOWN_UP : { BASIC : { NUM_0 : 48, NUM_1 : 49, NUM_2 : 50, NUM_3 : 51, NUM_4 : 52, NUM_5 : 53, NUM_6 : 54, NUM_7 : 55, NUM_8 : 56, NUM_9 : 57, a : 65, b : 66, c : 67, d : 68, e : 69, f : 70, g : 71, h : 72, i : 73, j : 74, k : 75, l : 76, m : 77, n : 78, o : 79, p : 80, q : 81, r : 82, s : 83, t : 84, u : 85, v : 86, w : 87, x : 88, y : 89, z : 90, HYPEN : 189, CARET : 222, YEN : 220, AT : 192, BRACKET_L : 219, SEMICOLON : 187, COLON : 186, BRACKET_R : 221, COMMA : 188, PERIOD : 190, SLASH : 191, BACK_SLASH : 226, ESC : 27, F1 : 112, F2 : 113, F3 : 114, F4 : 115, F5 : 116, F6 : 117, F7 : 118, F8 : 119, F9 : 120, F10 : 121, F11 : 122, F12 : 123, SCROLL_ROCK : 145, INSERT : 45, DELETE : 46, END : 35, PAGE_UP : 33, PAGE_DOWN : 34, LEFT : 37, UP : 38, RIGHT : 39, DOWN : 40, TAB : 9, CAPS_LOCK : 240, ALT : 18, SPACE : 32, WINDOWS_L : 91, WINDOWS_R : 92, ENTER : 13, BACK_SPACE : 8 }, SHIFT : { EX_MARK : 49, DOUBLE_QUOTE : 50, NUMBER_SIGN : 51, DOLLER : 52, PERCENT : 53, AMPERSAND : 54, SINGLE_QUOTE : 55, PARENTHESIS_L : 56, PARENTHESIS : 57, A : 65, B : 66, C : 67, D : 68, E : 69, F : 70, G : 71, H : 72, I : 73, J : 74, K : 75, L : 76, M : 77, N : 78, O : 79, P : 80, Q : 81, R : 82, S : 83, T : 84, U : 85, V : 86, W : 87, X : 88, Y : 89, Z : 90, EQUAL : 189, TILDE : 222, PIPE : 220, BACK_QUOTE : 192, CURLY_BRACKET_L : 219, PLUS : 187, ASTERISK : 186, CURLY_BRACKET_R : 221, LESS_THAN : 188, GREATER_THAN : 190, QUESTION : 191, UNDER_SCORE : 226 }, TEN_KEY : { NUM_0 : 96, NUM_1 : 97, NUM_2 : 98, NUM_3 : 99, NUM_4 : 100, NUM_5 : 101, NUM_6 : 102, NUM_7 : 103, NUM_8 : 104, NUM_9 : 105, DOT : 110, NUMLOCK : 144, SLASH : 111, ASTERISK : 106, HYPHEN : 109, PLUS : 107, ENTER : 13 } }, PRESS : { BASIC : { NUM_0 : 48, NUM_1 : 49, NUM_2 : 50, NUM_3 : 51, NUM_4 : 52, NUM_5 : 53, NUM_6 : 54, NUM_7 : 55, NUM_8 : 56, NUM_9 : 57, a : 97, b : 98, c : 99, d : 100, e : 101, f : 102, g : 103, h : 104, i : 105, j : 106, k : 107, l : 108, m : 109, n : 110, o : 111, p : 112, q : 113, r : 114, s : 115, t : 116, u : 117, v : 118, w : 119, x : 120, y : 121, z : 122, HYPEN : 45, CARET : 94, YEN : 92, AT : 64, BRACKET_L : 91, SEMICOLON : 59, COLON : 58, BRACKET_R : 93, COMMA : 44, PERIOD : 46, SLASH : 47, BACK_SLASH : 92, ESC : 27, F1 : 112, F2 : 113, F3 : 114, F4 : 115, F5 : 116, F6 : 117, F7 : 118, F8 : 119, F9 : 120, F10 : 121, F11 : 122, F12 : 123, SCROLL_ROCK : 145, INSERT : 45, DELETE : 46, END : 35, PAGE_UP : 33, PAGE_DOWN : 34, LEFT : 37, UP : 38, RIGHT : 39, DOWN : 40, TAB : 9, CAPS_LOCK : 240, ALT : 18, SPACE : 32, WINDOWS_L : 91, WINDOWS_R : 92, ENTER : 13, BACK_SPACE : 8 }, SHIFT : { EX_MARK : 33, DOUBLE_QUOTE : 34, NUMBER_SIGN : 35, DOLLER : 36, PERCENT : 37, AMPERSAND : 38, SINGLE_QUOTE : 39, PARENTHESIS_L : 40, PARENTHESIS : 41, A : 65, B : 66, C : 67, D : 68, E : 69, F : 70, G : 71, H : 72, I : 73, J : 74, K : 75, L : 76, M : 77, N : 78, O : 79, P : 80, Q : 81, R : 82, S : 83, T : 84, U : 85, V : 86, W : 87, X : 88, Y : 89, Z : 90, EQUAL : 61, TILDE : 126, PIPE : 124, BACK_QUOTE : 86, CURLY_BRACKET_L : 123, PLUS : 43, ASTERISK : 42, CURLY_BRACKET_R : 125, LESS_THAN : 60, GREATER_THAN : 62, QUESTION : 63, UNDER_SCORE : 95 }, TEN_KEY : { NUM_0 : 48, NUM_1 : 49, NUM_2 : 50, NUM_3 : 51, NUM_4 : 52, NUM_5 : 53, NUM_6 : 54, NUM_7 : 55, NUM_8 : 56, NUM_9 : 57, DOT : 46, NUMLOCK : 144, SLASH : 47, ASTERISK : 42, HYPHEN : 45, PLUS : 43, ENTER : 13 } } }; // ========================= スタートアップ ============================= / // 設定情報取り込み for ( I in FL_CONFIG ) { if ( ! I.isPrototypeOf(FL_CONFIG) ) { CORE_CONFIG[I] = FL_CONFIG[I]; } } // @notice CIから設定をビルドする場合、オブジェクトデータも文字列になるので、ここで変換(現在はcookieDomainのみ) if ( CORE_CONFIG.cookieDomain === 'document.domain' ) { CORE_CONFIG.cookieDomain = doc.domain; } // 設定情報を内部に移したあとは、グローバルオブジェクトを削除する try { delete FL_CONFIG; } catch (e) { FL_CONFIG = undefined; } // siteUrlの値が空の場合は自身のパスからビルドする if ( !CORE_CONFIG.siteUrl ) { (function() { var sc = head.getElementsByTagName('script'), i = -1, reg = /flint.*\.js$/, ap = CORE_CONFIG.scriptPath; while(sc[++i]) { if (reg.test(sc[i].src)) { CORE_CONFIG.siteUrl = sc[i].src.substring(0, sc[i].src.lastIndexOf(ap + 'flint')); break; } } })(); } // sslの場合も同様に if ( !CORE_CONFIG.ssl_siteUrl ) { (function() { var sc = head.getElementsByTagName('script'), i = -1, reg = /flint.*\.js$/, ap = CORE_CONFIG.scriptPath; while(sc[++i]) { if (reg.test(sc[i].src)) { CORE_CONFIG.ssl_siteUrl = sc[i].src.substring(0, sc[i].src.lastIndexOf(ap + 'flint')); break; } } })(); } // フック取り込み if (win.Hook && typeof Hook === 'object') { CORE_CONFIG.__hooks = Hook; try { delete win.Hook; } catch (e) { win.Hook = undefined; } } // デバッグモードチェック if ( CORE_CONFIG.debugMode === true ) { // 他のライブラリとの名前空間コンフリクトチェック if ( !(function() { var cf = [], g, N, gn = CORE_CONFIG.globalNames; for (N in gn) { if ( win[gn[N]] ) { cf[cf.length] = g; } } return (cf.length > 0) ? confirm('Namespace [' + cf.join(',') + ']' + 'is confrict!\nThis script keep running?') : true; })() ) { return; } } // window.eval禁止チェック if ( CORE_CONFIG.disableEval === true ) { win.eval = function() { throw Error('Eval function has deleted by system.'); }; } // プロトコルチェックと使用するURIの設定 SITEURI = CORE_CONFIG.siteUrl.replace(indexReg, ''); SSLURI = (CORE_CONFIG.ssl_siteUrl) ? CORE_CONFIG.ssl_siteUrl.replace(indexReg, '') : SITEURI; // 設定オブジェクトに追加 CORE_CONFIG.BASE_URL = (SYSTEM.SSL_CONNECT) ? SSLURI : SITEURI; CORE_CONFIG.SITE_URL = CORE_CONFIG[(SYSTEM.SSL_CONNECT) ? 'ssl_siteUrl' : 'siteUrl']; CORE_CONFIG.APPPATH = CORE_CONFIG.BASE_URL + CORE_CONFIG.scriptPath; // SITE_URLの末尾に/がなければ付加する if ( !/.+\/$/.test(CORE_CONFIG.SITE_URL) ) { CORE_CONFIG.SITE_URL += '/'; } // ====================- コアクラスマッピング ================== / ClassMap = { UserAgent : UserAgent, Loader : Loader, Utility : Utility, Router : Router, Config : Config, Event : Event, AjaxInit : AjaxInit, FL_Image : FL_Image, BenchMark : BenchMark, CreateClass : CreateClass, Extends : Extends, Enables : Enables, Language : Language, Hook : Hook, URI : URI, Json : Json, Input : Input, CustomEvent : CustomEvent }; ua = loadClass('UserAgent'); enables = loadClass('Enables'); // ======================= Compatible ECMA Script Section ========================== // // Array#forEach // @see https://developer.mozilla.org/ja/JavaScript/Reference/Global_Objects/Array/forEach ! Array.prototype.forEach && (Array.prototype.forEach = function(fn, pointer) { if ( typeof fn !== 'function' ) { throw new TypeError('First argument must be function on Array#forEach.'); } var i = 0, len = this.length, ctx = pointer || null; for ( ; i < len; ++i ) { if ( i in this ) { fn.call(ctx, this[i], i, this); } } }); // Array#map // @see https://developer.mozilla.org/ja/JavaScript/Reference/Global_Objects/Array/map ! Array.prototype.map && ( Array.prototype.map = function(fn, pointer) { if ( typeof fn !== 'function' ) { throw new TypeError('First argument must be function on Array#map.'); } var i = 0, len = this.length, ctx = pointer || null, ret = new Array(len); for ( ; i < len; ++i ) { if ( i in this ) { ret[i] = fn.call(ctx, this[i], i, this); } } }); // ======================= /Compatible ECMA Script Section End ========================== // // スタートアップ function ignite() { var UT, CFG, RTR, URI, HOOK, UA, BM, LANG, LOADER, INPUT, Class, Method, // method alias ael = 'addEventListener', ate = 'attachEvent', dte = 'detachEvent', rel = 'removeEventListener', dn, ss, G = CORE_CONFIG.globalNames; _registCustomEvent(); // IE8--用にVMLセットアップ // エミュレート以外にもVML置換が必要な場合があるので、 // 名前空間は作成しておく if (enables.needFixBrowserIE) { doc.createElement('canvas'); if (doc.namespaces) { dn = doc.namespaces; if (!dn.v) { // namespace dn.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML'); } if (!dn.v_o) { // namespace dn.add('v_o', 'urn:schemas-microsoft-com:office:office', '#default#VML'); } if (!doc.styleSheets.fl_canvas) { ss = doc.createStyleSheet(); ss.owningElement.id = 'fl_canvas'; ss.cssText = ['canvas{display:inline-block;overflow:hidden;', 'text-align:left;width:300px;height:150px;}', 'v\\:*{behavior:url(#default#VML)}', 'v_o\\:*{behavior:url(#default#VML)}' ].join(''); } } } ut = loadClass('Utility'); BM = loadClass('BenchMark'); // BM.mark('TotalExecutionTimeStart'); // BM.mark('LoadingTimeBaseClassesStart'); HOOK = loadClass('Hook'); HOOK._callHook('preSystem'); CFG = loadClass('Config'); URI = loadClass('URI'); RTR = loadClass('Router'); // Output Class is No Use. LANG = loadClass('Language'); INPUT = loadClass('Input'); LOADER = loadClass('Loader'); // =============== Base Startup Section ===================== Controller = Base = new _Controller(); Model = new _Model(); // 設定に基づいてグローバルスコープにaliasを貼る win.ClassExtend = function(ex, base) { new Extends(ex, base); }; win.getInstance = function() { return SYSTEM.CONTROLLER || Controller; }; alias('FLClass', loadClass('CreateClass')); alias(G.DOM, DOM); alias(G.Animation, Animation); alias(G.Module, Module); if (G.Helper !== '') { win[G.Helper] = {}; } // autoload start! Controller.load._fl_autoLoader(); if (CORE_CONFIG.routingMode === 'segment' || CORE_CONFIG.routingMode === 'config') { Controller.__load(CFG.appPath() + 'controllers/' + RTR.fetchDirectory() + RTR.fetchClass() + EXT); } else { win[G.Controller] = Controller; } // EXT._callHook('postSystem'); if (win[ael]) { win[ael]('load', Base.event.__execLoad, false); win[ael]('unload', ut.cleanEvElm, false); } else if (win[ate]) { // IEはページのunload時に登録ハンドラを全削除(memory leak対策) win[ate]('onunload', ut.cleanEvElm); win[ate]('onload', Base.event.__execLoad); } else { // インラインイベントハンドラも削除 win.onunload = ut.cleanEvElm; } // DOM ready監視 if (enables.canDOMReady) { doc[ael]('DOMContentLoaded', Base.event.__execDOM, false); } else if (ua.IE) { function rsc() { if (doc.readyState === 'complete') { Base.event.__execDOM(win.event); doc.detachEvent('onreadystatechange', rsc); } } doc[ate]('onreadystatechange', rsc); } else if (doc.readyState) { (function() { (doc.readyState == 'loaded' || doc.readyState == 'complete') ? Base.event.__execDOM() : delay(arguments.callee, 0); })(); } // TODO : スタートアップ続き書く } // ============================= 汎用メソッド =========================== / /** * union * オブジェクトの合成 * @param Object base : 合成元オブジェクト * @param Object ride : 合成させるオブジェクト * @param Boolean isPublicOnly : publicプロパティ/メソッドのみに限定するかどうか * @return Object : 合成されたオブジェクト */ function union(base, ride, isPublicOnly) { var i, isP = isPublicOnly || false; for (i in ride) { if ( !isP || !/^_/.test(i)) { base[i] = ride[i]; } } return base; } /** * alias * 対象オブジェクトにメソッド/プロパティの参照aliasを貼る * @param String name : 参照名 * @param String prop : 参照させるプロパティ/メソッド * @param Object attach : 参照させるオブジェクト(指定しなければwindow) * @return void */ function alias(name, prop, attach) { (attach || win)[name] = prop; } /** * apiLoad * APIをロード * @param String type : script or css * @param String path : ロードするAPIのパス * @param String att : cssのmedia属性 */ function apiLoad(type, path, att) { var ats = (type === 'css'), t = doc.createElement((ats) ? 'link' : 'script'); t.type = (ats) ? 'text/css' : 'text/javascript'; t[(ats) ? 'href' : 'src'] = path; if (ats) { if (att) { t.media = att; } t.rel = 'stylesheet'; } else { t.charset = 'UTF-8'; } head.appendChild(t); } /** * returnFalse * falseを返す関数 */ function returnFalse() { return false; } /** * loadClass * コアクラスのロード * @param String ClassName : ロードするクラス名 * @return Object : クラスインスタンス */ function loadClass(ClassName) { var LCC = STACK.LOADED_CORE_CLASSES, cl; if (!ClassMap[ClassName]) { throw Error(ClassName + ' class is not defined'); return; } if (!LCC[ClassName]) { LCC[ClassName] = new ClassMap[ClassName](); } return LCC[ClassName]; } /** * ready : API使用準備完了やDOM構築完了の待ち合わせ * @param mixed String or Function type : 文字列:API待機、Function:DOMReady * @param Function listener : API利用可能時に実行するコールバック */ function ready(type, listener) { var ar = STACK.API_READY, arf = STACK.API_READY_FUNC, fn; if (typeof type === 'string') { if (ar[type] === true || (typeof Controller[type] === 'object' || (SYSTEM.CONTROLLER && typeof SYSTEM.CONTROLLER[type] === 'object'))) { listener.call(SYSTEM.CONTROLLER || Controller); } else { function c() { listener.call(SYSTEM.CONTROLLER || Controller); } if (arf[type]) { arf[type].push(c); } else { arf[type] = [c]; } } } else if (typeof type === 'function') { Base.event.set(doc, 'DOMReady', type); } } /** * DefferdInit : FL_Defferd実行のクロージャ */ function DefferdInit() { return new FL_Defferd(arguments); } /** * __registCustomEvent : 独自イベントを登録する * jQueryっぽくmouseenterとかmouseleaveとか登録してみる * @param none */ function _registCustomEvent() { CUSTOM_EVENT = loadClass('CustomEvent'); CUSTOM_EVENT.regist('mouseenter', 'mouseover', function(current, ev) { var e = ev.relatedTarget || ev.fromElement || null, html = doc.documentElement, flag = true; if ( !e ) { return false; } while(e && e !== html) { if ( e === current ) { flag = false; break; } e = e.parentNode; } return flag; }); CUSTOM_EVENT.regist('mouseleave', 'mouseout', function(current, ev) { var e = ev.relatedTarget || ev.toElement || null, html = doc.documentElement, flag = true; if ( !e ) { return false; } while(e && e !== html) { if ( e === current ) { flag = false; break; } e = e.parentNode; } return flag; }); } // ========================= Flint Classes ==================== / // Enables - サポート状況を保持するクラス function Enables() { this.xhr = !!win.XMLHttpRequest; this.fixIE = (ua.IE && ua.IEV < 9) ? true : false; this.positionFixed = this.png = (!ua.IE6) ? true : false; this.minmaxWH = (!ua.IE6) ? true : false; this.hasAttBug = (ua.IE6 || ua.IE7) ? true : false; this.canASCall = (!ua.IE || ua.IEV > 8) ? true : false; // Array.prototype.slice.callが使用可能かどうか this.canQSA = (doc.querySelectorAll) ? true : false; // document.querySelectorAllが使えるかどうか // IE8とIE9のquerySelectorAllはnth-childとlast-child、!を含むトークンは例外を投げるので判定 this.isQSAChild = (this.canQSA && ua.IEV >= 8) ? true : false; // IE8とIE9以外のブラウザでquerySelectorAllを使う場合、:containsを含むトークンは例外を投げるので判定 this.isQSAContains = (this.canQSA && !ua.IE) ? true : false; // IE拡張が必要なバージョン判定 this.needFixBrowserIE = (ua.IE && ua.IEV < 9) ? true : false; // DOMContentLoadedが使えるブラウザ // Firefox, Opera, GoogleChrome, Safari version 3.1以上はaddEventListenerに登録できる // added at 2010/09/30 - IE9はaddEventListenerサポート+ContentLoadedが可能になった this.canDOMReady = (ua.IE9 || ua.IE10 || ua.Firefox || ua.Opera || ua.GoogleChrome || (ua.Safari && ua.SafariV > 3.1)) ? true : false; } Enables.prototype = {}; // <-- Enables ============================================================================= // UserAgentクラス -- ユーザーエージェント判定 function UserAgent() { var u = UA, sfV, __flashVer, map, i = -1, BS = [], c = doc.documentElement.className, DM = doc.documentMode, lteV = 10; this.agent = UA; // aliasメソッド function parse(match, n, m) { return pf(match[n] + '.' + ((!m) ? 0 : match[m])); } function has (str) { return (u.indexOf(str) !== -1); } function set(prefix) { BS[++i] = prefix; return true; } // is()メソッド用ショートカットマッピング map = { 'I' : 'IE', 'I6' : 'IE6', 'I7' : 'IE7', 'I8' : 'IE8', 'I8S' : 'IE8S', 'F' : 'Firefox', 'S' : 'Safari', 'C' : 'GoogleCrome', 'O' : 'Opera', 'L' : 'Lunascape', 'SL' :'Sleipnir', 'W' : 'Wii', 'GB' : 'GameBoy', 'DS' : 'NintentdoDS', 'PSP' : 'PSP', 'PS2' : 'PlayStation2', 'PS3' : 'PlayStation3', 'i' : 'iPod', 'ip' : 'iPhone', 'ip3' : 'iPhone3G' }; this.Opera = !!win.opera && set('o'); this.IE = has('msie') && !this.Opera && set('ie'); this.IEV = (this.IE) ? parse(u.match(/(.*?)msie ([0-9])\.([0-9])/), 2, 3) : null; this.IE6 = (this.IEV >= 6 && this.IEV < 7) && set('ie6'); this.IE7 = (this.IEV >= 7 && this.IEV < 8) && set('ie7'); this.IE8 = (this.IEV >= 8 && this.IEV < 9) && set('ie8'); this.IE9 = (this.IEV >= 9 && this.IEV < 10) && set('ie9'); this.IE10 = (this.IEV >= 10 && this.IEV < 11) && set('ie10'); this.IE8S = (this.IE8 && typeof DM != 'undefined' && DM === 8); this.IE9S = (this.IE9 && typeof DM != 'undefined' && DM === 9); this.IE10S = (this.IE10 && typeof DM != 'undefined' && DM === 10); this.Firefox = this.gecko = has('gecko') && has('fox') && set('ff'); this.webkit = has('webkit'); this.Safari = has('safari') && has('applewebkit') > 0 && !has('chrome', u) && set('s'); this.GoogleChrome = has('chrome', u) && set('gc'); this.Lunascape = has('lunascape'); this.Sleipnir = has('sleipnir'); this.Windows = has('windows'); this.Mac = has('mac'); this.Linux = has('linux'); if ( this.IE ) { while ( ! this['IE' + lteV] ) { set('ie-lte-' + lteV--); } set('ie-lte-' + lteV--); } // レンダリングモード this.Standard = (doc.compatMode === 'CSS1Compat'); // ブラウザバージョン this.FirefoxV = (this.Firefox) ? pf(u.replace(/(.*?)firefox\/([0-9])\.([0-9])(.*?)/, '$2.$3')) : null; this.OperaV = (this.Opera) ? parse(u.match(/(.*?)opera[\/|\s]([0-9])\.([0-9])(.*?)/), 2, 3) : null; this.GoogleChromeV = (this.GoogleChrome) ? pf(u.replace(/(.*?)chrome\/([0-9])\.([0-9])(.*?)/, '$2.$3')) :null; sfV = (this.Safari) ? u.replace(/(.*?)applewebkit\/([0-9]*?)\.(.*?)/, '$2').substring(0, 2) : null; this.SafariV = (sfV !== null) ? (pi(sfV, 10) > 52) ? u.replace(/(.*?)version\/([0-9])\.([0-9]).*/, '$2.$3') : (sfV == '41') ? '2.0' : (sfV == '31') ? '1.3' : (sfV == '12') ? '1.2' : (sfV == '10') ? '1.1' : (sfV == '85') ? '1.0' : '0' : null; // モバイルユーザーエージェント判定 if (CORE_CONFIG.useMobileAgent) { // ゲーム機のuserAgenet this.Wii = has('nintendo wii'); this.GameBoy = has('gameboy'); this.NintentdoDS = has('nitro'); this.PSP = has('psp'); this.PlayStation2 = has('ps2') && has('bb navigator'); this.PlayStation3 = has('playstation 3'); // PDAのuserAgent this.iPod = has('ipod'); this.iPnone = has('iphone'); this.iPhone3G = this.iPhone && has('applewebkit/525'); this.Android = has('android'); } /** * is * ブラウザ判定ショートカット * @param String reg : ショートカットID,|で複数指定できる * @return Boolean */ this.is = function(reg) { var uas = reg.split('|'), uaslen = uas.length, i = 0; for (;i < uaslen; i++) { if (uas[i] in map && this[map[uas[i]]] === true) { return true; } } return false; }; __flashVer = (function() { var v = [0, 0, 0], vn, m, n = navigator, pl, AX, mmt = 'application/x-shockwave-flash', AC7 = 'ShockwaveFlash.ShockwaveFlash.7', AC6 = 'ShockwaveFlash.ShockwaveFlash.6'; // other IE if (n.plugins && n.mimeTypes[mmt]) { pl = n.mimeTypes[mmt].enabledPlugin; if (pl && pl.description) { m = pl.description.match(/([0-9]+)\.([0-9])\s?[a-zA-Z]([0-9]+)$/); v = [m[1], m[2], m[3]]; } } else { // Windows IE try { // version 7+ try AX = new ActiveXObject(AC7); vn = AX.GetVariable("$version"); } catch (e) { try { // version 6 try AX = new ActiveXObject(AC6); vn = 'WIN 6,0,21,0'; AX.AllowScriptAccess = 'always'; vn = AX.GetVariable("$version"); } catch (e) { vn = null; } } if (vn) { v = vn.replace(/^WIN /, '').split(','); v.splice(3, 1); } } return v; })(); this.toString = function() { return '[ Class UserAgent ]'; }; this.flashVer = __flashVer.join('.'); this.flashVerArray = __flashVer; // set Agent prefix doc.documentElement.className = ( c === '') ? BS.join(' ') : c + BS.join(' '); } UserAgent.prototype = {}; // <-- /UserAgent ============================================================================= // CreateClass -- 汎用的なクラス作成 function CreateClass() {} CreateClass.prototype = { // genericなクラス雛形生成 create : function(ext) { var fn = function() {}; return this.__extend(fn, ext || undefined); }, // singletonクラス雛形生成 singleton : function(ext) { var ins, fn = function() { if (ins) { return ins; } else { ins = this; } }; return this.__extend(fn, ext || undefined); }, __extend : function(fn, ext) { switch (typeof ext) { case 'function': fn.constructor = ext; fn.prototype = new ext(); break; case 'object': fn.constructor = ext.constructor; fn.ptototype = ext; break; default: break; } return fn; } }; // <-- /CreateClass ============================================================================= // Configクラス -- 設定情報を取得/設定するクラス function Config() { this.C = CORE_CONFIG; } Config.prototype = { /** * siteurl * サイトURIを取得 * @param String suffix : 後ろに付加するURI * @return String */ siteUrl : function(suffix) { return this.C.SITE_URL + (suffix ? suffix.replace('/^[\/]', '') : ''); }, /** * baseUrl * ドキュメントルートまでの絶対パスを取得 * @return String */ baseUrl : function() { return this.C.BASE_URL; }, /** * appPath * このファイルまでのパスを取得 * @return String */ appPath : function() { return this.C.APPPATH; }, /** * item * 設定情報を取得 * @param String name : 設定名 * @reutrn mixed */ item : function(name) { return (name in this.C) ? this.C[name] : false; }, /** * isDebug * デバッグモードで動作しているかを取得 * @reutrn Boolean */ isDebug : function() { return this.C.debugMode; }, /** * setItem * 設定情報を追加。既に情報がある場合は上書きする * @param String name : 設定名 * @param mixed data : 設定データ * @reutrn void */ setItem : function(name, data) { this.C[name] = data; }, /** * getGlobal * 名前空間オブジェクトを返却する */ getGlobal : function(name) { var G = this.C.globalNames; if (!name) { return { Controller : (CORE_CONFIG.routingMode === 'segment') ? '' : G.Controller, DOM : G.DOM, Animation : G.Animation, Helper : (G.helper === '') ? win : G.Helper, Module : (G.Module === '') ? win : G.Module }; } else { if (G.hasOwnProperty(name)) { return (name === 'Helper') ? (G[name] != '') ? win[G[name]] : win : win[G[name]]; } } }, toString : function() { return '[ Class Config ]'; } }; // <-- Config ============================================================================= // JSONクラス -- window.JSONをサポートしないブラウザ向けJSONサポートクラス function Json() { this.esc = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; this.meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; this.gap = null; this.ind = null; this.rep = null; } Json.prototype = { parse : function(str) { return SYSTEM.GLOBAL_EVAL('(' + str + ')'); }, stringify : function(value, rep, sp) { var i = 0; this.gap = ''; this.ind = ''; if (ut.isNumber(sp)) { for (; i < sp; i++) { this.ind += ' '; } } else if (ut.isString(sp)) { this.ind = sp; } this.rep = rep; if (rep && !ut.isFunction(rep) && (!ut.isObject(rep) || !ut.isNumber(rep.length))) { throw new TypeError('Json.stringify'); } return this.__strstr('', {'' : value}); }, __q : function(str) { var esc = this.esc, m = this.meta; esc.lastIndex = 0; return esc.test(str) ? '"' + str.replace(esc, function(s){ return (ut.isString(m[s])) ? m[s] : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + str + '"'; }, __strstr : function(key, obj) { var i, k, v, len, m = this.gap, pat = [], val = obj[key], rep = json.rep, isF = window.isFinite; if (ut.isFunction(rep)) { val = rep.call(obj, key, val); } if (ut.isString(val)) { return this.__q(val); } else if (ut.isNumber(val)) { return isF(val) ? String(val) : 'nul'; } else if (ut.isBool(val) || ut.isNull(val)){ return String(val); } else if (ut.isArray(val)) { if (!val) { return 'null'; } this.gap += this.ind; len = val.length; for (i = 0; i < len; i++) { pat[i] = this.__strstr(i, val) || 'null'; } v = (pat.length === 0) ? '[]' : this.gap ? '[\n' + this.gap + pat.join(',\n' + this.gap) + '\n' + m + ']' : '[' + pat.join(',') + ']'; this.gap = m; return v; } else { // object if (!val) { return 'null'; } this.gap += this.ind; if (rep && ut.isObject(rep)) { len = rep.length; for (i = 0; i < len; i++) { k = rep[i]; if (ut.isString(k)) { v = this.__strstr(k, val); if (v) { pat.push(json.__q(k) + (json.gap ? ': ' : ':') + v); } } } } else { for (k in val) { if (Object.hasOwnProperty.call(val, k)) { v = this.__strstr(k, val); if (v) { pat.push(json.__q(k) + (json.gap ? ': ' : ':') + v); } } } } v = (pat.lnegth === 0) ? '{}' : this.gap ? '{\n' + this.gap + pat.join(',\n' + this.gap) + '\n' + m + '}' : '{' + pat.join(',') + '}'; this.gap = m; return v; } }, toString : function() { return '[ Class Json ]'; } }; // <-- Json ============================================================================= // BenchMarkクラス -- 実行時間計測系クラス function BenchMark() { this.STB = STACK.BENCH_MARKS; this.SYB = SYSTEM.BENCH_MARKS; } BenchMark.prototype = { mark : function(name) { var n = name || 'default'; this.STB[n] = +new Date(); this.SYB[n] = 'running...'; }, end : function(name, isDisplay) { var n = name || 'default', s = this.STB[n], e = +new Date(), r = e -s; this.SYB[n] = r + ' ms'; return isDisplay ? r : alert('BenchMarks "' + n + '" runs ' + r + ' ms'); }, toString : function() { return '[ Class BenchMark ]'; } }; // <-- BenchMark ============================================================================= // URIクラス -- アクセスURIに関するクラス function URI() { this.hash; this.search; this.uri; this.__construct(); } URI.prototype = { __construct : function() { var URL = LOC.href, hp = URL.indexOf('#'), sp = URL.indexOf('?'), acu, splitUri, segmentLen, ii = 0, uriO = {}, uriA = ['']; // parse request URI this.hash = ( hp !== -1 ) ? URL.slice(hp) : '#'; this.search = ( sp !== -1 ) ? URL.slice(sp + 1) : ''; this.uri = URL.replace(this.hash, '').replace('?' + this.search, ''); this._uriString = this.uri.replace(CORE_CONFIG.SITE_URL); // parse to Object-Array acu = this._uriString.replace(/index\.php\/?/, ''); splitUri = acu.split('/'); segmentLen = splitUri.length; for (; ii < segmentLen; ii++) { uriO[ii + 1] = uriA[uriA.length] = splitUri[ii]; } this.uriObj = uriO; this.uriArray = uriA; }, // ハッシュ値取得 getHash : function(withHash) { return (withHash) ? this.hash : this.hash.slice(1); }, // セグメントデータを配列で取得 segmentArray : function() { var u = this.uriArray, len = u.length, i = 0, ret = ['']; while (u[++i]) { ret[ret.length] = u[i]; } return ret; }, // セグメントを指定して取得 segment : function(num, def) { return this.uriArray[num] || def; }, // 最後のセグメントを取得 lastSegment : function(def) { return this.uriArray[this.uriArray.length - 1] || def || undefined; }, // スラッシュ付きセグメントの取得 slashSegment : function(num, slash) { var u = this.uriArray, sh = slash || '', prefix = (sh === 'leading' || sh === 'both') ? '/' : '', suffix = (sh === 'both') ? '/' : ''; return u[num] ? prefix + u[num] + suffix : false; }, // URIを文字列で取得 uriString : function() { return this._uriString; }, assocToUri : function(arr) { return '/' + arr.join('/'); }, toString : function() { return '[ Class URI ]'; } }; // <-- URI ============================================================================= // Inputクラス -- 入力値を保持するクラス // JavaScriptの特性上、POSTは取れないので単純にqueryStringを解析、get()メソッドのみ実装 function Input() { this._GET = {}; this.__construct(); } Input.prototype = { /** * コンストラクタ */ __construct : function() { var s = (LOC.search !== '') ? LOC.search.slice(1) : '', sp = s.split('&'), spp, i = -1; while(sp[++i]) { spp = sp[i].split('='); this._GET[dec(spp[0])] = dec(spp[1]); } this._GET = this.__cleanInputData(this._GET); }, /** * 入力値の検証 * @note パラメータはXSS検証しないので注意 */ __cleanInputData : function(str) { if ( ut.isObject(str)) { var i, ret = {}, keyRegex = /^[a-zA-Z0-9:_\/\-]+$/; for ( i in str ) { if ( str.hasOwnProperty(i) ) { if ( keyRegex.test(i) ) { ret[i] = this.__cleanInputData(str[i]); } } } return ret; } return str.replace(/[\r\n|\r]/g, '\n'); }, /** * GETパラメータ取得 */ get : function(key) { return (key && this._GET.hasOwnProperty(key) ) ? this._GET[key] : false; } }; // <-- Input ============================================================================= // Hookクラス -- スタートアップ中に任意のタイミングでコールバックを実行するクラス function Hook() { this.__hooks = CORE_CONFIG._hooks || {}; } Hook.prototype = { _callHook : function(type) { var h = this.__hooks; if (h[type] && ut.isFunction(h[type])) { h[type](); } } }; // <-- Hook ============================================================================= // Utilityクラス -- クロスブラウザユーティリティクラス function Utility() {} Utility.prototype = { /** * 要素のviewport座標系位置を取得 */ getAbsPosition : function(e) { var t, l, p, sc, gCS, nowStyle; if (e.style.position === 'fixed') { // case position : fixed t = e.style.top; l = e.style.left; // top if (t == 'auto' || t == '') { t = e.offsetTop; } else if (t.indexOf('%') > -1) { t = mr(screen.availHeight * pi(t) / 100); } else { t = pi(t); } // left if (l == 'auto' || l == '') { l = e.offsetLeft; } else if (l.indexOf('%') > -1) { l = mr(screen.availHeight * pi(l) / 100); } else { l = pi(l); } return {x : l, y : t}; } if (e.getBoundingClientRect) { // IE6+ p = e.getBoundingClientRect(); sc = this.getScrollPosition(); return { x : mr(p.left + sc.x), y : mr(p.top + sc.y)}; } // getBoundingClientRectが未サポートの場合、手動で絶対位置を計算 p = { x : 0, y : 0 }; var getStyle = function(elm, cameledProp, prop) { if (elm.currentStyle) { switch (elm.currentStyle[camledProp]) { case 'thin' : return 2; case 'medium' : return 4; case 'thick' : return 6; default : return elm.currentStyle[cameledProp]; } } else if (COMPUTED_STYLE) { nowStyle = COMPUTED_STYLE(elm, ''); return nowStyle.getPropertyValue(prop); } return 0; }; while (e) { p.x += e.offsetLeft; p.y += e.offsetTop; e = e.offsetParent; if (e && ua.IE) { p.x += (pi(getStyle(e, 'borderLeftWidth', 'border-left-width'), 10) || 0); p.y += (pi(getStyle(e, 'borderTopWdth', 'border-top-width'), 10) || 0); } } if (ua.Firefox) { p.x += 2 * (pi(getStyle(body, 'borderLeftWidth', 'border-left-width'), 10) || 0); p.y += 2 * (pi(getStyle(body, 'borderTopWidth', 'border-top-width'), 10) || 0); } return p; }, // getScrollPosition - 現在のスクロール量を取得 getScrollPosition : function() { var b = doc.body, h = doc.documentElement; return { x : b.scrollLeft || h.scrollLeft || 0, y : b.scrollTop || h.scrollTop || 0 }; }, // getPageSize - コンテンツの最大幅を取得 getPageSize : function() { var b = doc.body, h = doc.documentElement, max = Math.max; return { width : max(b.innerWidth || 0, b.clientWidth || 0, b.scrollWidth || 0, h.clinetWidth || 0, h.scrollWidth || 0), height : max(b.innerHeight || 0, b.clientHeight || 0, b.scrollHeight || 0, h.clinetHeight || 0, h.scrollHeight || 0) }; }, // getContentSize - ウインドウ表示領域を取得 getContentSize : function() { var b = doc.body, h = doc.documentElement; return { width : ( defWinWidth > 0 ) ? defWinWidth : ( !!win.innerWidth ) ? win.innerWidth : ( ua.Standard ) ? h.clientWidth : b.clientWidth, height : ( defWinHeight > 0 ) ? defWinHeight : ( !!win.innerHeight ) ? win.innerHeight : ( ua.Standard ) ? h.clientHeight : b.clientHeight }; }, // getCenterPosition - ウインドウ表示領域中心点を取得 getCenterPosition : function(current) { var size = this.getContentSize(), sc = this.getScrollPosition(); return { x : size.width / 2 + (current ? sc.x : 0), y : size.height / 2 + (current ? sc.y : 0) }; }, // getPixel - 各単位をpxに変換 getPixel : function(unit) { var d = doc.createElement('div'), ret = {}, val = pf(unit); if (isNaN(val)) { return 0; } d.style.visibility = 'hidden'; d.style.position = 'absolute'; d.style.top = '0px'; d.style.left = '0px'; doc.body.appendChild(d); d.style.width = '10pt'; ret.pt = d.offsetWidth / 10; d.style.width = '10em'; ret.em = d.offsetWidth / 10; doc.body.removeChild(d); d = null; return (unit.indexOf('em') !== -1) ? ret.em * val : (unit.indexOf('pt') !== -1) ? ret.pt * val : val; }, // getTextSize - テキストを表示させた時の幅を取得する getTextSize : function(txt, additional) { var d = doc.createElement('span'), res = {}; d.style.fontSize = additional || 'inherit'; d.style.width = 'auto'; d.style.visibility = 'hidden'; d.appendChild(doc.createTextNode(txt)); doc.body.appendChild(d); res.width = d.offsetWidth; res.height = d.ofsetHeight; doc.body.removeChild(d); d = null; return res; }, // inRect - 要素1が要素2の中に入っているかどうかをチェック inRect : function(elm1, elm2) { var fd = DOM(elm1).absDimension(), td = DOM(elm2).absDimension(); return (fd.top > td.top && fd.left > td.left && fd.bottom < td.bottom && fd.right < td.right); }, // inRectPiece - 要素1が要素2の一部分に入っているかどうかをチェック inRectPiece : function(elm1, elm2) { var fd = DOM(elm1).absDimension(), td = DOM(elm2).absDimension(); return !(fd.bottom < td.top || fd.top > td.bottom || fd.right < td.left || fd.left > td.right); }, // inRectHalfVertical - 要素1が要素2の一部分に入っている場合、上半分か下半分かをチェック inRectHalfVertical : function(elm1, elm2) { if (this.inRectPiece(elm1, elm2) === false) { return false; } var fd = DOM(elm1).absDimension(), td = DOM(elm2).absDimension(); if ((fd.bottom >= td.top && fd.bottom <= td.bottom - (td.height / 2)) && ((fd.left >= td.left && fd.left <= td.right) || (fd.right >= td.left && fd.right <= td.right))) { return 'T'; } else if ((fd.top >= td.top + (td.height / 2) && fd.top <= td.bottom) && ((fd.left >= td.left && fd.left <= td.right) || (fd.right >= td.left && fd.right <= td.right))) { return 'B'; } return false; }, // inRectParallel - 要素1が要素2の一部分に入っている場合、左半分か右半分かをチェック inRectHalfParallel : function(elm1, elm2) { if (this.inRectPiece(elm1, elm2) === false) { return false; } var fd = DOM(elm1).absDimension(), td = DOM(elm2).absDimension(); if ((fd.left >= td.left + (td.width / 2) && fd.left <= td.right) && ((fd.top >= td.top && fd.top <= td.bottom) || (fd.bottom >= td.top && fd.bottom <= td.bottom))) { return 'L'; } else if ((fd.right >= td.left && fd.right <= td.left + (td.width / 2)) && ((fd.top >= td.top && fd.top <= td.bottom) || (fd.bottom >= td.top && fd.bottom <= td.bottom))) { return 'R'; } return false; }, // mouseInRect - マウス座標が要素の中に入ったかどうかをチェック mouseInRect : function(mouse, elm) { var ed = DOM(elm).absDimension(); return (mouse.x >= ed.left && mouse.x <= ed.right && mouse.y >= ed.top && mouse.y <= ed.bottom); }, // mouseInRectHalfVertical - マウス座標が要素の一部分に入っている場合、上半分か下半分かをチェック mouseInRectHalfVertical : function(mouse, elm) { if (!this.mouseInRect(mouse, elm)) { return false; } var td = DOM(elm).absDimension(); if ((mouse.y >= td.top && mouse.y < td.top + (td.height / 2)) && (mouse.x >= td.left && mouse.x <= td.right)) { return 'T'; } else if ((mouse.y >= td.top + (td.height / 2) && mouse.y <= td.bottom) && (mouse.x >= td.left && mouse.x <= td.right)) { return 'B'; } return false; }, // mouseInRectHalfParallel- マウス座標が要素の一部分に入っている場合、左半分か右半分かをチェック mouseInRectHalfParallel : function(mouse, elm) { if (!this.mouseInRect(mouse, elm)) { return false; } var td = DOM(elm).absDimension(); if ((mouse.x >= td.left && mouse.x < td.left + (td.width / 2)) && (mouse.y >= td.top && mouse.y <= td.bottom)) { return 'L'; } else if ((mouse.x >= td.left + (td.width / 2) && mouse.x <= td.right) && (mouse.y >= td.top && mouse.y <= td.bottom)) { return 'R'; } return false; }, // __is - nullでなくundefinedでないか判定 __is : function(o) { return (o === null || typeof o == 'undefined'); }, // isString - Stringオブジェクトであるかを判定 isString : function(o) { return (this.__is(o) === false && typeof o == 'string'); }, // isNumber - Numberオブジェクトであるかを判定 isNumber : function(o) { return (this.__is(o) === false && typeof o == 'number'); }, // isFunction - Functionオブジェクトであるかを判定 isFunction : function(o) { return (this.__is(o) === false && typeof o == 'function'); }, // isArray - Arrayオブジェクトであるかを判定 isArray : Array.isArray || function(o) { return (this.__is(o) === false && typeof o == 'object' && Object.prototype.toString.call(o) === '[object Array]'); }, // isObject - Objectオブジェクトであるかを判定 isObject : function(o) { return (this.__is(o) === false && typeof o == 'object' && Object.prototype.toString.call(o) === '[object Object]'); }, // isBool - 真偽値オブジェクトであるかを判定 isBool : function(o) { return (this.__is(o) === false && typeof o == 'boolean'); }, // isset - 変数が未定義かどうか判定 isset : function(v) { return (typeof v == 'undefined'); }, // isNull - nullがどうか判定 isNull : function(v) { return (v === null); }, // isXElement - xElementのインスタンスかどうかを判定 isXElement : function(e) { return !!(e instanceof xElement); }, // isxNodeList - xNodelistのインスタンスかどうかを判定 isXNodeList : function(e) { return !!(e instanceof xNodeList); }, // rgbToHex - rgbをhexに変換 rgbToHex : function(rgb) { var t = this.trim(rgb), m, i = 1, h, ret = ['#']; if (/^rgb/.test(t) === false) { return rgb; } m = rgb.match(COLOR_REGEX.rgb); if (pi(m[1], 10) > 255 || pi(m[2], 10) > 255 || pi(m[3], 10) > 255) { throw Error('can\'t convert RGB to Hex on ' + rgb); } for (i; i < 4; i++) { h = pi(m[i], 10).toString(16); ret[ret.length] = (h.length === 1) ? '0' + h : h; } return ret.join(''); }, // hexToRgb - Hexをrgbに変換 hexToRgb : function(hex) { var t = this.trim(hex), m, ret = hex; if (/^#[0-9a-fA-F]{6}$/.test(t)) { m = t.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/); ret = 'rgb(' + pi(m[1], 16).toString() + ',' + pi(m[2], 16).toString() + ',' + pi(m[3], 16).toString() + ')'; } else if (/^#[0-9a-fA-F]{3}/.test(t)) { m = t.match(/^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/); ret = 'rgb(' + pi(m[1] + m[1], 16).toString() + ',' + pi(m[2] +m[2], 16).toString() + ',' + pi(m[3] + m[3], 16).toString() + ')'; } else { throw Error('invalid hex foramt on ' + hex); } return ret; }, // grep - 文字列が特定の文字列を持つかどうかを判定- String.indexOfとRegExp.testのショートカット grep : function(str, has) { if (!ut.isString(str) || !has) { throw TypeError('invalid arguments of Utility.grep function parameter by ' + str); } if (typeof has === 'string') { // String return (str.indexOf(has) !== -1); } else if (has.constructor === RegExp) { // RegExp return has.test(str); } return false; }, // serializeForm -
要素内の入力要素を通信パラメータ用のJSONにまとめる serializeForm : function(elm) { if (!elm.nodeType || elm.tagName.toLowerCase() !== 'form') { throw new Error('utility.serializeForm works element only.'); return; } var res = {}, input, inputlen, iptName, iptArr = {}, select, selectlen, textarea, textarealen, chStack = {}, ch = false, e, chName, i, j, s, sl, k, m, ipt, c; // input elements input = elm.getElementsByTagName('input'); inputlen = input.length; for (i = 0; i < inputlen; i++) { e = input[i]; switch (e.type) { case 'text': case 'password': case 'submit': case 'hidden': if (ut.grep(e.name, '[]')) { iptName = e.name.replace('[]', ''); if (iptName in iptArr) { iptArr[iptName].push(e.value); } else { iptArr[iptName] = [e.value]; } } else { res[e.name] = e.value; } break; case 'radio': if (e.checked === true) { res[e.name] = e.value; } break; case 'checkbox': if (e.checked === true) { ch = true; chName = ut.grep(e.name, '[]') ? e.name.replace('[]', '') : e.name; if (chName in chStack) { chStack[chName].push(e.value); } else { chStack[chName] = [e.value]; } } break; default : break; } } // add checkbox if (ch) { for (c in chStack) { if ( ! c.isPrototypeOf(chStack) ) { res[c] = (chStack[c].length === 1 ) ? chStack[c][0] : chStack[c]; } } } // posted value has array? for (ipt in iptArr) { if (! ipt.isPrototypeOf(iptArr)) { res[ipt] = iptArr[ipt]; } } // select elements select = elm.getElementsByTagName('select'); selectlen = select.length; for (j = 0; j < selectlen; j++) { s = select[j].options; sl = s.length; for (k = 0; k < sl; k++) { if (s[k].selected === true) { if (select[j].multiple) { if (res[select[j].name]) { res[select[j].name].push(s[k].value); } else { res[select[j].name] = s[k].value; } } else { res[select[j].name] = s[k].value; break; } } } } // textarea elements textarea = elm.getElementsByTagName('textarea'); textarealen = textarea.length; for (m = 0; m < textarealen; m++) { res[textarea[m].name] = textarea[m].value; } return res; }, // trim - 前後の空白文字をカット trim : String.trim || function(str) { return str.replace(/^\s|\s$/g, ''); }, // ucfirst - 先頭の文字だけを大文字にする ucfirst : function(str) { return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); }, // br2nl - brタグを改行コードに変換 br2nl : function(str) { return str.replace(//g, '\n'); }, // nl2br - 改行コードを
タグに変換 nl2br : function(str) { return str.replace(/\r\n/g, '
').replace(/\r|\n/g, '
'); }, // javascript Stringを削除 clean : function(str, ignoreScript) { var quoteMode = ignoreScript || true, i; if (typeof str == 'object') { for (i in str) { if (!i.isPrototypeOf(str)) { str[i] = this.clean(str[i], quoteMode); } } return str; } if (quoteMode) { str = str.replace(/javascript:/ig, '[removedprotocol]'); } return str.replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/\'/g, '''); }, // 配列の中に一致する要素があるかどうかを判定 // 第三引数がtrueなら型の一致もチェック inArray : Array.inArray || function(v, arr, strict) { var len = arr.length, i = 0, s = strict || false; for (; i < len; i++) { if (arr[i] == v) { if (s) { if (arr[i] === v) { return true; } } else { return true; } } } return false; }, // forEach : Array#forEach実装 forEach : function(ary, fn) { // native API exists? if ( ary.forEach ) { return ary.forEach(fn); } var i = -1; while ( ary[++i] ) { fn.call(ary[i], i); } }, //getDefaultWH - 要素のデフォルトサイズを取得する getDefaultWH : function(e) { var elm = DOM(e), dis = elm.readStyle('display'), w = elm.readStyle('width'), h = elm.readStyle('height'), abs; elm.addStyle({ width : 'auto', height : 'auto', display : 'block' }); abs = { width : e.offsetWidth, height : e.offsetHeight }; elm.addStyle({ width : w, height : h, display : dis }); return abs; }, // toURIParams - オブジェクトをURIパラメータ形式に変換 toURIParams : function(data) { if (!this.isObject(data)) { throw TypeError('argument must be an Object.'); return; } var ret = [], i; for (i in data) { if ( !i.isPrototypeOf(data)) { ret[enc(i)] = enc(data[i]); } } return ret.join('&='); }, // getExecuteName - ロードした関数の連結名をロードURIから取得 getExecuteNames : function(func) { var ts, n = this.getRealName(func), sc = doc.getElementsByTagName('script'), len = sc.length, i = len - 1, sp; if (!n || n === '') { throw Error('extend class name is undefined.'); return; } for (; i >= 0; i--) { if (sc[i].src && sc[i].src.indexOf(n) !== -1) { ts = sc[i].src; break; } } if (!ts || ut.grep(ts, '?')) { return {name : n, bindName : n}; } sp = ts.split('&'); return { name : n, bindName : (sp[1] && ut.grep(sp[1], 'bind')) ? sp[1].split('=')[1] : n }; }, // getRealName - 関数から定義名のみを取り出す getRealName : function(func){ return func.name || (function(){ var name = func.toString(); return name.slice(9, name.indexOf('(')); })(); }, // cleanEvElm - ページのunload時に全イベント解除と拡張エレメントを削除する cleanEvElm : function() { Base.event.deleteAllEvent(); STACK.ELEMENTS = []; STACK.GLOBAL_LAYER = null; STACK.DEFFERD = {}; }, // camel - ハイフンの次の文字をキャメルケースにする camel : function(str) { var spl, p, i = 0; if (str in STACK.CAMELED_PROP) { return STACK.CAMELED_PROP[str]; } if (!ut.grep(str, '-')) { return str; } spl = str.split('-'); p = [spl[0]]; while (spl[++i]) { p[i] = spl[i].charAt(0).toUpperCase() + spl[i].slice(1).toLowerCase(); } STACK.CAMELED_PROP[str] = p.join(''); return STACK.CAMELED_PROP[str]; }, // deCamel - キャメライズされた文字をハイフン+小文字に戻す deCamel : function(str) { var ret; if (str in STACK.DECAMELED_PROP) { return STACK.DECAMELED_PROP[str]; } ret = str.replace(/([A-Z]{1})/g, '-$1').toLowerCase(); STACK.DECAMELED_PROP[str] = ret; return ret; }, // exists - 関数が定義されているかをチェックする exists : function(fn) { var h = CORE_CONFIG.globalNames.Helper, obj = (h != '') ? win[h] : win; return !!obj[fn]; }, // makeFilter - IE用のfilter文字列を生成する makeFilter : function(type, value, ext) { switch (type) { case 'op' : return 'alpha(opacity=' + (value.indexOf('.') !== -1) ? value * 100 : value + ')'; case 'png' : return 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + value + ', sizingMethod=' + ((ext) ? ext : 'scale') + ')'; default : return ''; } }, toString : function(){ return '[ Class Utility ]'; } }; // <-- Utility ============================================================================= // Firefox on Event::offsetX, Event::offsetY if (ua.Firefox) { win.Event.prototype.__defineGetter__('offsetX', function() { return this.layerX; }); win.Event.prototype.__defineGetter__('offsetY', function() { return this.layerY; }); win.Event.prototype.__defineGetter__('wheelData', function() { return this.detail; }); } // Eventクラス -- クロスブラウザなイベントモデルクラス(DOM Level2イベントモデル準拠) function Event() { this.DRreg = /domready/i; this.ae = STACK.AJAX_EVENTS; this.df = STACK.DOM_LOADED_FUNCS; this.lf = STACK.LOADED_FUNCS; this._customEvents = []; this._AjaxEventNames = {'AjaxEnd' : 1, 'AjaxComplete' : 1, 'AjaxError' : 1}; this.EXPR_LIVE_LIST = []; this.LIVE_LIST = []; this.LIVE_EVENTS = 'mousemove|mouseout|mouseover|mousedown|mouseup|mousewheel|DOMMouseScroll|click|keydown|keypress|keyup'; } Event.prototype = { /** * set - イベントセット * @param Element elm : イベント設定要素 * @param String type : イベントタイプ * @param Function listener : イベントリスナ * @param Object bindObj : callコンテキストオブジェクト * @param Boolean isOnce : 一度だけ実行するかどうかのフラグ * @param Booelan isCapture : キャプチャフェーズでハンドリングするかどうか */ set : function(elm, type, listener, bindObj, isOnce, isCapture) { var bind = bindObj || false, target = (elm instanceof xElement) ? elm.get() : elm, closure, once = isOnce || false, capture = isCapture || false, df = this.df, lf = this.lf; // Ajaxカスタムイベントの場合はスタックに追加 if (this._AjaxEventNames[type]) { this.ae[this.ae.length] = [target, type, listener, bind, once]; return; } else if ( type in CUSTOM_EVENT._customs ) { CUSTOM_EVENT.add(target, type, listener, bind, once); return; } if (type === 'mousewheel' && (!('onmousewheel' in body) && ua.Opera)) { type = 'DOMMouseScroll'; } // イベントクロージャ生成 closure = this.__createClosure(target, type, listener, bind, once, capture); // document.readyの場合は既にロード済みなら実行、まだならキューに追加 if (this.DRreg.test(type)) { df[df.length] = [closure, bind]; } else if (type === 'load' && target === win) { lf[lf.length] = [closure, bind]; } else { this.__set(target, type, closure, listener, capture); } }, // once - 一度だけ実行するイベントを設定する // setメソッドに第5引数を渡すためのシンタックスシュガー once : function(target, type, listener, bindObj) { this.set(target, type, listener, bindObj, true); }, /** * custom - カスタムイベント生成 * @param Element target : イベント設定要素 * @param String type : カスタムイベント名 * @param Function listener : イベントリスナ * @param bindObj : call1コンテキストオブジェクト */ custom : function(target, type, listener, bindObj) { var bind = bindObj || false, elm = (target instanceof xElement) ? target.get() : target, closure = this.__createWrap(target, listener, bind, type, false), ael = 'addEventListener', ce = this._customEvents; if (target[ael]) { target[ael](type, closure, false); } ce[ce.length] = [target, type, listener, closure, bind]; return; }, /** * removeCustom - カスタムイベント削除 * @param Element target : カスタムイベントを設定した要素 * @param String type : カスタムイベント名 * @param Function listener : イベントハンドラ */ removeCustom : function(target, type, listener) { var c = this._customEvents, len = c.length, i = 0, elm = (target instanceof xElement) ? target.get() : target, del = 'removeEventListener', dt = 'detachEvent'; for (; i < len; i++) { if (c[i][0] === elm && c[i][1] === type && (!listener || c[i][2] === listener)) { if (elm[del]) { elm[del](type, c[i][3], false); } else if (elm[dt]) { elm[dt]('on' + type, c[i][3]); } c.splice(i, 1); } } }, /** * fire - イベント発火 * @param Element target : イベント発生コンテキスト要素 * @param String type : イベントタイプ * @param mixed data : イベントに渡すパラメータ * @param String dataType : イベントデータタイプ */ fire : function(target, type, data, dataType) { var e, elm = (target instanceof xElement) ? target.get() : target, dp = 'dispatchEvent', fe = 'fireEvent'; if (doc.createEventObject) { e = doc.createEventObject(); e.type = type; } else if (doc.createEvent){ e = doc.createEvent('Events'); e.initEvent(type, true, true); } else { throw new Error('don\'t supports custom Event on your Browser'); return; } e.dataType = dataType; e.data = data; if ( type in CUSTOM_EVENT._customs ) { CUSTOM_EVENT.dispatch(target, e); return; } if (elm[dp]) { elm[dp](e); } else if (elm[fe]) { // IEは未定義のイベントタイプは例外を投げるようなので、自力で特定し、ディスパッチ var c = EV.CUSTOM_EVENTS, len = c.length, i = 0; for (i; i < len; i++) { if (c[i][1] === type) { c[i][2].call(c[i][3], new Base.event.__margeDOM2Event(c[i][0], e, data, dataType)); } } } }, /** * live 動的イベントハンドリング * @param Element elm : イベント監視起点ノード * @param String type : イベントタイプ * @param Function listener : イベントハンドラ * @param Object bindObj : callコンテキストオブジェクト */ live : function(elm, type, listener, bindObj) { var expr = DOM.__fallbackQuery(elm); this.exprLive(expr, type, listener, bindObj || undefined, elm); }, /** * exprLive - CSSセレクタ指定型の動的イベントハンドリング * @param String expr : CSSセレクタフォーマット * @param String type : イベントタイプ * @param Function listener : イベントハンドラ * @param Object bindObj : callコンテキストオブジェクト * @param Element baseNode : イベント監視起点ノード */ exprLive : function(expr, type, listener, bindObj, baseNode) { if (type.indexOf(this.LIVE_LIST) === -1) { return; } var bind = bindObj || false, closure = this.__createLiveClosure(listener, bind, type, expr), ELL = this.EXPR_LIVE_LIST; this.__set(baseNode || doc, type, closure, listener); ELL[ELL.length] = [type, listener, expr, closure, baseNode || doc]; }, /** * delive - 動的イベントハンドリング解除 * @param Element elm : イベント監視起点要素 * @param String type : イベントタイプ * @pram Function listener : イベントハンドラ */ deLive : function(elm, type, listener) { var expr = DOM.__fallbackQuery(elm); this.exprdeLive(expr, type, listener, bindObj || undefined, elm); }, /** * exprdeLive - CSSセレクタ指定動的イベントハンドリング解除 * @param String expr : CSSセレクタフォーマット * @param String type : イベントタイプ * @param Function listener : イベントハンドラ */ exprdeLive : function(expr, type, listener, baseNode) { var live = this.EXPR_LIVE_LIST, len = live.length, i= 0, base = baseNode || doc; for (; i< len; i++) { if (live[i] && live[i][0] === type && live[i][2] === expr && live[i][4] === base && (!listener || live[i][1] === listener)) { this.__remove([live[i][4], live[i][0], live[i][3]], i, live); } } }, /** * remove - イベント監視解除 * @param Element target : イベントを設定した要素 * @param String type : イベントタイプ * @param Function listener : イベントハンドラ */ remove : function(target, type, listener) { var fns = STACK.EVENT_HANDLERS, fnslen = fns.length, i = fnslen - 1, ind = -1; if (ut.isArray(type)) { while(type[++ind]) { if (type[i]) { this.remove(target, type[i], listener || undefined); } } return; } if (this._AjaxEventNames[type]) { this.__removeAjaxEvents(target, type, listener); return; } else if ( type in CUSTOM_EVENT._customs ) { CUSTOM_EVENT.remove(target, type, listener); return; } for (; i >= 0; i--) { if (fns[i][0] === target && fns[i][1] === type && (!listener || fns[i][3] === listener)) { this.__remove(fns[i], i, fns); } } }, /** * _remove - イベント削除実行 * @param Array arr イベントスタック * @param Number num : イベント管理連番 * @param Array marr : イベントスタックマスターデータ */ __remove : function(arr, num, marr) { var re = 'removeEventListener', de = 'detachEvent'; if (arr[0][re]) { arr[0][re](arr[1], arr[2], arr[4]); } else if (arr[0][de]) { arr[0][de]('on' + arr[1], arr[2]); } else { arr[0]['on' + arr[1]] = null; } marr.splice(num, 1); }, /** * __isAlready - イベントがセットされているかどうかチェック * @param Element target : イベント設定要素 * @param String type : イベントタイプ * @param Function listener : イベントハンドラ */ __isAlready : function(target, type, listener) { var fns = STACK.EVENT_HANDLERS, fnslen = fns.length, i = fnslen - 1; for (; i >= 0; i--) { if (fns[i][0] === target && fns[i][1] === type && fns[i][3] === listener) { return true; } } return false; }, /** * __createClosure - イベントハンドラクロージャ生成 * @param Element target : イベント発生要素 * @param Function lis : イベントハンドラ * @param mixed bind : callコンテキストオブジェクト * @param String type : イベントタイプ * @param Boolean isOnce : 実行後に削除するか */ __createClosure : function(target, type, lis, bind, isOnce, capture) { var that = this; return function(ev) { var event = new Base.event.__margeDOM2Event(target, ev || win.event); if (isOnce === true) { Base.event.remove(target, type, lis); } if (capture && enables.fixIE) { win.event.useCapture = true; } if ( lis.call(bind || target, event) === false ) { event.preventDefault(); } }; }, /** * __createLiveClosure - liveExpr用ラッパー関数生成 * @param Function listener イベントハンドラ * @param mixed bindObj : callコンテキストオブジェクト * @param String type : イベントタイプ * @param String expr : CSSセレクタ */ __createLiveClosure : function(listener, bindObj, type, expr){ var that = this; return function(ev) { var e = ev || win.event, elm = e.target || e.srcElement, list = DOM.getElementsBySelector(expr), len = list.length, i = 0, evt = new that.__margeDOM2Event(elm, e); if (elm.nodeType === 3) { elm = elm.parentNode; } for (; i < len; i++) { if (list[i] === elm) { if ( listener.call(bindObj || elm, evt) === false ) { evt.preventDefault(); } return; } } }; }, /** * __set - イベントリスナ設定 * @param Element target : イベントを設定する要素 * @param String type : イベントタイプ * @param Function wrap : クロージャハンドラ * @param Function fn : イベントハンドラ * @param Boolean capture : キャプチャフェーズかどうか */ __set : function(target, type, wrap, fn, capture) { var ael = 'addEventListener', at = 'attachEvent', EH = STACK.EVENT_HANDLERS; if (target[ael]) { target[ael](type, wrap, capture); } else if (target[at]) { target[at]('on' + type, wrap); } else { target['on' + type] = wrap; } EH[EH.length] = [target, type, wrap, fn, capture]; }, /** * deleteAllEvent - すべてのイベントリスナ開放 * 主にメモリリーク対策 */ deleteAllEvent : function() { var fns = STACK.EVENT_HANDLERS, len = fns.length, i = 0, t, e, f, del = 'removeEventListener', dt = 'detachEvent'; for (; i < len; i++) { t = fns[i][0]; e = fns[i][1]; f = fns[i][2]; if (!t || !e || !f) { continue; } if (t[del]) { t[del](e, f, fns[4]); } else if (t[dt]) { t[dt]('on' + e, f); } else { t['on' + e] = null; } } STACK.EVENT_HANDLERS = []; }, /** * __execDOM - DOMツリー構築完了時のハンドラーを実行(1回のみ) */ __execDOM : function() { SYSTEM.DOM_LOADED = true; SYSTEM.DOM_CREATE_TIME = (new Date()).getTime() - SYSTEM.INITIAL_TIME; STACK.BODY = STACK.HTML = body = doc.body; var api = STACK.API_STACK, apilen = api.length, s, css = STACK.CSS_STACK, csslen = css.length, a = 0, tmp, f = STACK.DOM_LOADED_FUNCS, len2 = f.length; // STACKからAPIのロード if (apilen > 0) { for (a = 0; a < apilen; a++) { apiLoad('script', api[a][0]); } } // STACkからCSSのロード for (a = 0; a < csslen; a++) { apiLoad('css', css[a][0], css[a][1] || null); } // STACKからDOMハンドラー実行 for (a = 0; a < len2; a++) { f[a][0](); } // 全てのシステムの準備が完了したらコントローラの初期メソッド実行 if (ut.isFunction(SYSTEM.START_CONTROLLER)) { SYSTEM.START_CONTROLLER(); }; }, /** * __execLoad - window.onload時のハンドラーを実行(1回のみ) */ __execLoad : function(e) { SYSTEM.WINDOW_LOADED = true; SYSTEM.WINDOW_LOADED_TIME = (new Date()).getTime() - SYSTEM.INITIAL_TIME; // STACKからonloadハンドラー実行 var f = STACK.LOADED_FUNCS, len = f.length, i = 0; for (; i < len; i++) { f[i][0](); } }, /** * __margeDOM2Event - DOM Level2 Eventモデルをエミュレート * @note 既知の問題 * webkit Safariの旧バージョン(ver 2.x?)はevent.targetにテキストノードを示す場合がある * IE9以前はそもそも独自イベントモデルなのでマージする */ // @access private __margeDOM2Event : function(elm, eObj, data, dataType) { // IE9とSafari以外はDOMイベントモデルでビルド if ((!ua.IE && !ua.Safari) || ua.IE9) { return eObj; } var sc = ut.getScrollPosition(), b = eObj.button; // イベントプロパティをマージ this.__nativeEV = eObj; this.type = eObj.type; this.data = eObj.data || data || null; this.dataType = eObj.dataType || dataType || null; this.target = eObj.target || eObj.srcElement; if ( this.target && this.target.nodeType && this.target.nodeType === 3 ) { this.target = this.target.parentNode; } // this.target = (eObj.target) ? (eObj.target.nodeType === 3) ? eObj.target.parentNode // : eObj.target // : eObj.srcElement; this.currentTarget = elm; this.relatedTarget = eObj.relatedTarget || (eObj.type === 'mouseover') ? eObj.fromElement : eObj.toElement || undefined; this.keyCode = eObj.keyCode; this.shiftKey = eObj.shiftKey; this.ctrlKey = eObj.ctrlKey; this.propertyName = eObj.propertyName || undefined; this.pageX = eObj.pageX || (eObj.clientX + sc.x); this.pageY = eObj.pageY || (eObj.clientY + sc.y); this.clientX = eObj.clientX; this.clientY = eObj.clientY; this.detail = eObj.wheelData || eObj.detail; if (ua.IE) { this.button = (b == 4) ? 1 : (b == 1) ? 0 : b; this.which = (b == 4) ? 2 : (b == 2) ? 3 : b; this.stopPropagation = function() { this.__nativeEV.cancelBubble = true; }; this.preventDefault = function() { this.__nativeEV.returnValue = false; }; } else { this.button = eObj.button; this.which = eObj.which; // this.stopPropagation = eObj.stopPropagation; // this.preventDefault = eObj.preventDefault; this.stopPropagation = function() {eObj.stopPropagation(); }; this.preventDefault = function() {eObj.preventDefault(); }; } }, toString : function() { return '[ Class Event ]'; } }; // <-- Event ============================================================================= // CustomEvent -- カスタムイベントを定義する function CustomEvent() { this._customs = {}; this._customsStack = {}; } // prototypes CustomEvent.prototype = { // regist : カスタムイベント登録 regist : function(type, bindType, judgeFunc) { if ( !type || !bindType ) { throw Error('parameters not enough at CustomEvent.regist.'); return; } this._customs[type] = {type : bindType, fn : judgeFunc}; }, // destroy : カスタムイベント破棄 destroy : function(type) { if ( type in this._customs ) { delete this._customs[type]; } }, // add : カスタムイベントバインド add : function(target, type, listener, bindObj, isOnce) { if ( ! this._customs[type] ) { return; } var CE = this._customs[type], CES = this._customsStack, ael = 'addEventListener', ate = 'attachEvent', closure = this.__createCustomClosure(target, type, listener, CE.fn, bindObj, isOnce), stack = {target : target, type : type, closure : closure, listener : listener, isOnce : isOnce || false}; if ( target[ael] ) { target[ael](CE.type, closure, false); } else if ( target[ate] ) { target[ate]('on' + CE.type, closure); } else { target['on' + CE.type] = closure; } if ( CES[type] ) { CES[type][CES[type].length] = stack; } else { CES[type] = [stack]; } }, // remove : カスタムイベントの監視終了 remove : function(target, type, listener) { if ( ! this._customs[type] || ( ! this._customsStack[type] || this._customsStack[type].length === 0 )) { return; } var CES = this._customsStack[type], CE = this._customs[type], i = CES.length, rel = 'removeEventListener', dte = 'detachEvent', S; while ( CES[--i] ) { S = CES[i]; if ( S.target === target && ( !listener || (listener && S.listener === listener)) ) { if ( target[rel] ) { target[rel](CE.type, S.closure, false); } else if ( target[dte] ) { target[dte]('on' + CE.type, S.closure); } else { target['on' + CE.type] = null; } CES.splice(i, 1); } } }, // dispatch : カスタムイベント発火 dispatch : function(target, evt) { if ( ! this._customs[type] || ( ! this._customsStack[type] || this._customsStack[type].length === 0 )) { return; } var CES = this._customsStack[type], CE = this._customs[type], i = CES.length, S; while ( CES[--i] ) { S = CES[i]; if ( S.target === target ) { S.closure(evt); } } }, // __createCustomClosure : カスタムイベント用クロージャ発行 __createCustomClosure : function(target, type, listener, fn, bindObj, isOnce) { var that = this; return function(ev) { var evt = ev || win.event; if ( fn(target, evt) === true ) { listener.call(bindObj, new Base.event.__margeDOM2Event(target, evt)); if ( isOnce ) { that.remove(target, type, listener); } } } }, toString : function() { return '[class CustomEvent]'; } }; // <-- CustomEvent ======================================================================= // Loaderクラス -- APIロードやCSSのロードを担当する function Loader() { this.ap = {}; this.apcs = {}; this.instanced = STACK.INSTANCED_API; this.appPath = CORE_CONFIG.APPPATH; // SWF用設定 this.swfDefaultOptions = { scale : 'noScale', salign : 'lt', menu : false, wmode : 'transparent' }; } Loader.prototype = { config : function(name) { if (ut.isString(name) && !(name in this.ap)) { this.__loadAPI(this.appPath + 'config/' + name + 'js'); } }, helper : function(name) { var i = 0, len, hp = CORE_CONFIG.globalNames.Helper, loadName; if (ut.isArray(name)) { for (len = name.length; i < len; i++) { this.helper(name[i]); } return; } else if (typeof name === 'string'){ loadName = name.replace('_helper', '') + '_helper'; if (loadName in this.ap) { return; } // グローバル空間にヘルパーオブジェクトがなければ作成 if (hp != '' && !win[hp]) { win[hp] = {}; } // ヘルパー関数チェックメソッドをグローバルに追加 if ( !win.functionExists) { win.functionExists = ut.exists; } this.__loadAPI(this.appPath + 'helpers/' + loadName + '.js', loadName, 'h'); } }, library : function(name) { this.__lbLoad(name, 'libraries/', 'l'); }, model : function(name) { this.__lbLoad(name, 'models/', 'mo'); }, __lbLoad : function(name, dir, type) { var i, len; if (ut.isArray(name)) { for (i = 0, len = name.length; i < len; i++) { this.__lbLoad(name[i], dir, type); } return; } else if (typeof name === 'string') { if (name in this.ap) { // インスタンス済みの場合は即座にattach if (this.instanced[name]) { Controller[name] = this.instanced[name]; return; } } else { this.__loadAPI(this.appPath + dir + name + '.js', name, type); } STACK.API_READY[name] = false; } }, module : function(name) { var i , len, m; if (ut.isArray(name)) { for (i = 0, len = name.length; i < len; i++) { this.module(name[i]); } return; } else if (typeof name === 'string') { m = CORE_CONFIG.globalNames.Module; if (!win[m]) { win[m] = Module; } if (name in this.ap) { return; } if (MODULES.hasOwnProperty(name)) { if (!Module[name]) { Module[name] = MODULES[name]; } this.ap[name] = true; } else { this.__loadAPI(this.appPath + 'modules/' + name + '.js', name, 'm'); } } STACK.MODULE_READY[name] = false; }, css : function(css, media) { if (css in this.apcs) { return; } this.__loadCSS(this.appPath + 'fl_css/' + css + '.css', css, media || false); }, ajax : function() { if ( ! Controller.ajax ) { Controller.ajax = new AjaxInit(); } }, view : function(path, appendObj, async) { if (!Controller.ajax) { this.ajax(); } Controller.ajax.get(path, {async : !!!async, success : function(resp) { DOM(appendObj).append(resp.responseText); }}); }, plugin : function(name) { var i = -1, len; if (ut.isArray(name)) { while(name[++i]) { this.plugin(name[i]); } } else if (typeof name === 'string') { if (!(name in this.ap)) { this.__loadAPI(this.appPath + 'plugins/' + name + '.js', name, 'p'); } } }, __loadAPI : function(path, name, type, bind) { var SAS = STACK.API_STACK; this.ap[name] = name; // DOMが構築完了していればにappend if (SYSTEM.DOM_LOADED) { apiLoad('script', path); } else if (/mo|h|p/.test(type)) { // 構築前の場合は、モデル/ヘルパー以外はスタックに追加 doc.write('