fruffl icon

tri4m Bootloader

fruffl | 01/31/13 06:52:54 PM UTC | 0 ⭐ | 289 👁️ | Never ⏰ | []
jQuery |

63.5 KB

|

None

|

0 👍

/

0 👎

(function(window, undefined)
{
    var plat4m, bootstrapList, compstrapList,
    document    = window.document,
    location    = window.location,
    navigator   = window.navigator,
        _tri4m  = window.tri4m,
        tri4m   = function(selector, context) { return new tri4m.shell.init(selector, context, plat4m); },
    ECMA_push   = Array.prototype.push,
    ECMA_slice  = Array.prototype.slice,
    ECMA_indexOf    = Array.prototype.indexOf,
    ECMA_toString   = Object.prototype.toString,
    ECMA_hasOwn = Object.prototype.hasOwnProperty,
    ECMA_trim   = String.prototype.trim,
    ECMA_classType  = {},
    DOMContentLoaded = function()
    {
        if(document.addEventListener)
        {
            document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
            tri4m.bootstrap();
        }
        else if(document.readyState === "complete")
        {
            document.detachEvent("onreadystatechange", DOMContentLoaded);
            tri4m.bootstrap();
        }
    };
    
    var REGEX_V_MS_PREFIX   = /^-ms-/;
    var REGEX_D_DASH_ALPHA  = /-([\da-z])/gi;
    var REGEX_C_NOT_WHITE   = /\S/;
    var REGEX_C_SPACE   = /\s+/;
    
    var JQUERY_SRC      = 'http://code.jquery.com/jquery-latest.min.js';
    var JQUERY_INIT_TIME    = 500; // idle for jQuery === undefined
 
tri4m.shell = tri4m.prototype =
{
    constructor: tri4m,
    init: function(selector, context, plat4m)
    {
        if(!selector)
            return this;
            
        if(selector.nodeType)
        {
            this.context = this[0] = selector;
            this.length = 1;
            return this;
        }
        
        if(typeof selector === "string")
        {
            tri4m.log('no jQuery - no selector support! (request: ' + selector + ')', 3);
            return this;
        }
        else if(tri4m.isFunction(selector))
        {
            return plat4m.compstrap(selector);
        }
 
        if(typeof selector.selector !== 'undefined')
        {
            this.selector = selector.selector;
            this.context  = selector.context;
        }
 
        return tri4m.makeArray(selector, this);
    },
    selector: "",
    build: "1.8.3",
    minor: "1.8.2",
    major: "1.8.3",
    length: 0,
    size: function()
    {
        return this.length;
    },
    toArray: function()
    {
        return ECMA_slice.call(this);
    },
    get: function(num)
    {
        return num == null
            ? this.toArray()
            : (num < 0 ? this[this.length + num] : this[num]);
    },
    pushStack: function(elems, name, selector)
    {
        var ret = tri4m.merge(this.constructor(), elems);
        
        ret.prevObject = this;
        ret.context    = this.context;
 
        if(name === "find")
        {
            ret.selector = this.selector + (this.selector ? " " : "") + selector;
        }
        else if(name)
        {
            ret.selector = this.selector + "." + name + "(" + selector + ")";
        }
        
        return ret;
    },
    each: function(callback, args)
    {
        return tri4m.each(this, callback, args);
    },
    bootstrap: function(fn)
    {
        tri4m.bootstrap.promise().done(fn);
        return this;
    },
    compstrap: function(fn)
    {
        tri4m.compstrap.promise().done(fn);
        return this;
    },
    eq: function(i)
    {
        i = +i;
        return i === -1
            ? this.slice(i)
            : this.slice(i, i + 1);
    },
    first: function()
    {
        return this.eq(0);
    },
    last: function()
    {
        return this.eq(-1);
    },
    slice: function()
    {
        return this.pushStack
        (
            ECMA_slice.apply(this, arguments),
            "slice",
            ECMA_slice.call(arguments).join(",")
        );
    },
    map: function(callback)
    {
        return this.pushStack
        (
            tri4m.map
            (
                this,
                function(elem, i)
                {
                    return callback.call(elem, i, elem);
                }
            )
        );
    },
    end: function()
    {
        return this.prevObject || this.constructor(null);
    },
    push: ECMA_push,
    sort: [].sort,
    splice: [].splice
};
 
tri4m.shell.init.prototype = tri4m.shell;
 
 
tri4m.extend = tri4m.shell.extend = function()
{
    var opt, name, des, ref, refIsArray, clone, tar = arguments[0] || {}, i = 1, length = arguments.length, rec = false;
 
    if(typeof tar === "boolean")
    {
        rec = tar;
        tar = arguments[1] || {};
        i = 2;
    }
        
    if(typeof tar !== "object"
    && !tri4m.isFunction(tar))
        tar = {};
        
    if(length === i)
    {
        tar = this;
        --i;
    }
 
    for(; i < length; i++)
    {
        if((opt = arguments[i]) == null)
            continue;
        
        for(name in opt)
        {
            des = tar[name];
            ref = opt[name];
            
            if(tar === ref)
                continue;
 
            if(rec
            && ref
            && (tri4m.isPlainObject(ref) || (refIsArray = tri4m.isArray(ref))))
            {
                if(refIsArray)
                {
                    refIsArray = false;
                    clone = des && tri4m.isArray(des) ? des : [];
 
                }
                else
                {
                    clone = des && tri4m.isPlainObject(des) ? des : {};
                }
 
                tar[name] = tri4m.extend(rec, clone, ref);
                
                continue;
            }
            
            if(ref === undefined)
                continue;
                
            tar[name] = ref;
        }
    }
    
    return tar;
};
 
tri4m.extend(
{
    isBootstrapped: false,
    isCompstrapped: false,
    bootstrapWait: 1,
    compstrapWait: 1,
    holdBoot: function(hold)
    {
        if(hold)
        {
            tri4m.bootstrapWait++;
        }
        else
        {
            tri4m.bootstrap(true);
        }
    },
    bootstrap: function(wait)
    {
        if(wait === true ? --tri4m.bootstrapWait : tri4m.isBootstrapped)
            return;
            
        if(!document.body)
            return setTimeout(tri4m.bootstrap, 1);
 
        tri4m.isBootstrapped = true;
        
        if(wait !== true
        && --tri4m.bootstrapWait > 0)
            return;
        
        bootstrapList.resolveWith(document, [tri4m]);
 
        tri4m.log('-- Bootstrap complete');
    },
    compstrap: function(wait)
    {
        if(wait === true ? --tri4m.compstrapWait : tri4m.isCompstrapped)
            return;
            
        if(!document.body)
            return setTimeout(tri4m.compstrap, 1);
 
        tri4m.isCompstrapped = true;
        
        if(wait !== true
        && --tri4m.compstrapWait > 0)
            return;
        
        compstrapList.resolveWith(document, [tri4m]);
        
        tri4m.log('-- Compstrap complete');
    },
    log : function(sText, sType, _bTimestamp)
    {
        var debugMode = true, useConsole = true,
             c = null, d = ['log', 'info', 'warn', 'error'], sType = sType || 0, n = d[sType];
                        
        if(typeof l == 'undefined')
            l = 0;
    
        if(false === debugMode)
            return this;
        
        
        if(null === c)
            c = (typeof console !== 'undefined' && typeof console.log !== 'undefined');
        
 
        if(typeof(_bTimestamp) !== 'undefined' && _bTimestamp)
            sText = sText + ' | ' + new Date().getTime();
 
        sText = 'tri4m: ' + sText;
        sType = d[sType];
        
        l++;
        
        if(c && useConsole)
        {
            if(typeof console[sType] === 'undefined')
                sType = d[sType];
            
            if(typeof console[sType] !== 'undefined')
            {
                console[sType](sText);
            }
            else
            {
                console.log(sText);
            }
        }
        
        return this;
    },
    isFunction: function(obj)
    {
        return tri4m.type(obj) === "function";
    },
    isArray: Array.isArray || function(obj)
    {
        return tri4m.type(obj) === "array";
    },
    isWindow: function(obj)
    {
        return obj != null && obj == obj.window;
    },
    isNumeric: function(obj)
    {
        return !isNaN(parseFloat(obj)) && isFinite(obj);
    },
    type: function(obj)
    {
        return obj == null ?
            String(obj) :
            ECMA_classType[ECMA_toString.call(obj)] || "object";
    },
    isPlainObject: function(obj)
    {
        if(!obj || tri4m.type(obj) !== "object" || obj.nodeType || tri4m.isWindow(obj))
            return false;
 
        try {
            if(obj.constructor
            && !ECMA_hasOwn.call(obj, "constructor")
            && !ECMA_hasOwn.call(obj.constructor.prototype, "isPrototypeOf"))
                return false;
        }
        catch(e)
        {
            return false;
        }
 
        var key;
        for(key in obj) {}
 
        return key === undefined || ECMA_hasOwn.call(obj, key);
    },
    isEmptyObject: function(obj)
    {
        var name;
        for(name in obj)
            return false;
        
        return true;
    },
    stringToFlag: function(options, type)
    {
        var object = {};
        
        var type = (type
                && type === true
                || type === false
                || type === null
                || type === 0
                || type === 1
                || type === 2)
                    ? type
                    : true;
        
        tri4m.each
        (
            options.split(REGEX_C_SPACE),
            function(i, flag)
            {
                i++;
                if(type === 0)
                {
                    object[flag] = i - 1;
                    return;
                }
                
                if(type === 1)
                {
                    object[flag] = i;
                    return;
                }
                
                if(type === 2)
                {
                    object[flag] = Math.pow(2, i);
                    return;
                }
                
                object[flag] = type;
            }
        );
        
        return object;
    },
    objectToString : function(object, includeFunctions, fullPrintFunctions, tbl)
    {
        var incFunctions = includeFunctions || false, prntFunctions = fullPrintFunctions || false, tbl = tbl || false;
        
        var type = function(p, t, l)
        {
            var l = l || 0, s = tri4m.stringRepeat('    ', l), n = "\n" + s, d = n + '@prop ' + p + ': ', r;
            
            var space   = n;
            var type    = '[property] ';
            var name    = p;
            var value   = t;
            var scalar  = true;
            
            switch(true)
            {
                case(typeof t === "undefined"):
                    value = "undefined";
                    break;
                case(t === null):
                    value = "null";
                    break;
                case(typeof t === "boolean"):
                    value = (t === true) ? "true" : 'false';
                    type = "[boolean]";
                    break;
                case(t === NaN):
                    value = "NaN" ;
                    break;
                case(tri4m.isFunction(t)):
                    internal = t.toString().match(/\[native code\]/g);
                    type = "[function"+ ((internal !== null) ? "[internal: " + t.constructor.name + "]" : "") + "]";
                    value = (true === prntFunctions) ? t.toString() : null;
                    break;
                case(tri4m.isArray(t) && t.length === 0):
                    type = "[array]";
                    value = "[]";
                    break;
                case(tri4m.isArray(t)):
                    var b = parse(t, (l + 1)).join("");
                    type = "[array]";
                    value = n + " [" + b + n + "], ";
                    scalar = false;
                    break;
                case (typeof t === "object" && tri4m.isEmptyObject(t)):
                    type = "[object]";
                    value = "[]";
                    break;
                case (typeof t === "object"):
                    var b = parse(t, (l + 1)).join(s);
                    type = "[object]";
                    value = "[" + b + n +"], ";
                    scalar = false;
                    break;
                case (typeof t === "string"):
                    type = "[string]";
                    value = "'" + t.toString() + "', ";
                    break;
                default:
                    type = "[" + (typeof t) + "]";
                    value = t.toString();
                    break;
            }
            
            return { space : space, type : type, name : name, value : value, scalar : scalar };
        };
        
        var parse = function(o, l)
        {
            var a = [], b = [], l = l || 1, tl = 0, nl = 0;
            
            for(var p in o)
            {
                if(typeof o.hasOwnProperty !== 'function')
                    continue;
                    
                if(!o.hasOwnProperty(p))
                    continue;
                
                var t = o[p];
                
                if(false === incFunctions
                && tri4m.isFunction(t))
                    continue;
                
                a[a.length] = type(p, t, l);
            }
            
            for(var i in a)
            {
                var atl = a[i].type.length, anl = a[i].name.length;
                
                if(atl > tl)
                    tl = atl;
                    
                if(anl > nl)
                    nl = anl;
            }
            
            for(var i in a)
            {
                var t = a[i], n = t.name, p = t.type, v = t.value;
                
                if(true === t.scalar && true === tbl)
                {
                    n = tri4m.stringPadRight(t.name, " ", nl);
                    p = tri4m.stringPadRight(t.type, " ", tl)
                }
                
                v =  (null === v) ? "" : ": " + v;
                
                b[b.length] = t.space + p + " " + n + v;
            }
            
            return b;
        };
        
        var r = parse(object).join("");
        r = (r !== '') ? r + "\n" : 'null';
            
        return "{{{!:" + r + ":!EOF}}}\n";
    },
    rand: function(numericScope)
    {
        if(!numericScope)
            var numericScope = Math.floor(Math.random());
        
        return Math.floor(Math.random() * numericScope);
    },
    sprintf: function(str)
    {
        for(var i = 1, len = arguments.length; i < len; ++i)
            str = str.replace("{" + (i - 1) + "}", arguments[i]);
        
        return str;
    },
    sizeOf : function(subject)
    {
        if(tri4m.isArray(subject))
            return subject.length;
            
        if(typeof subject === 'undefined') return;
        if(typeof subject === null) return;
        
        var c = 0;
        for(var i in subject) c++;
        return c;
    },
    sleep : function(subject, time, callback)
    {
        var i = subject;
        
        i.queue(function()
        {
            setTimeout(function()
            {
                i.dequeue();
                if(callback) callback();
                return subject;
            }, time);
        });
        
        return subject;
    },
    stringFindNumber: function(string)
    {
        string = string.replace(/[^0-9]/gi, '');
        if(!string || isNaN(string)) string = 0;
        return string;
    },
    stringPadLeft: function(string, chr, width)
    {
        var result = string, length = width - result.toString().length, i = length - 1;
            
        if(width > 0 && i >= 0)
            do result = chr + result;
            while(i--);
        
        return result;
    },
    stringPadRight: function(string, chr, width)
    {
        var result = string, length = width - result.toString().length, i = length - 1;
            
        if(width > 0 && i >= 0)
            do result = result + chr;
            while(i--);
        
        return result;
    },
    stringRepeat: function(string, width)
    {
        var result = '';
        for(var i = 0; i < width; i++)
            result += string;
        
        return result;
    },
    stringToWrite : function(str, depth, width, chr)
    {
        var width = width || 8, depth = depth || 0, chr = chr || ' ';
        return tri4m.stringRepeat(chr, depth * width) + str + "\n";
    },
    trimChar: function(string, chr)
    {
        if(string.substr(0, 1) === chr)
            string = string.substr(1, (string.length - 1));
        if(string.substr((string.length - 1), string.length) === chr)
            string = string.substr(0, (string.length - 1));
        return string;
    },
    trimCharsRight: function(string, charlist)
    {
        charlist = !charlist ? ' \\s\u00A0' : (charlist + '').replace(/([\[\]\(\)\.\?\/\*\{\}\+\tri4m\^\:])/g, '\\tri4m1');
        return (string + '').replace(new RegExp('[' + charlist + ']+tri4m', 'g') , '');
    },
    zeroFill: function(number, width, includeDecimal)
    {
        if(typeof includeDecimal == 'undefined')
            includeDecimal = false;
        
        var result = parseFloat(number), negative = false, length = width - result.toString().length, i = length - 1;
        
        if(result < 0)
        {
            result = Math.abs(result);
            negative = true;
            length++;
            i = length - 1;
        }
        
        if(width > 0)
        {
            if(result.toString().indexOf('.') > 0)
            {
                if(!includeDecimal)
                    length += result.toString().split('.')[1].length;
                length++;
                i = length - 1;
            }
            
            if(i >= 0)
                do result = '0' + result;
                while (i--);
        }
        
        return (true === negative)
            ? '-' + result
            : result;
    },
    rgb2hex : function(dec)
    {
        var n = parseInt(dec), c = 'ABCDEF', b = n / 16, r = n % 16; b = b-(r/16); 
        b = ((b >= 0) && (b <= 9)) ? b : c.charAt(b - 10);    
        return ((r >= 0) && (r <= 9)) ? b + '' + r : b + '' + c.charAt(r - 10);
    },
    dec2hex : function(d)
    {
        return Number(d).toString(16).toUpperCase();
    },
    dec2hexCode : function(dec, length)
    {
        if(!length) var length = 8;
        return '0x' + tri4m.stringPadLeft(tri4m.dec2hex(dec), '0', length);
    },
    error: function(msg)
    {
        throw new Error(msg);
    },
    noop: function() {},
    globalEval: function(data) {
        if(data
        && ECMA_rnotwhite.test(data))
            (window.execScript || function(data) { window["eval"].call(window, data); })(data);
    },
    camelCase: function(string) {
        return string.replace(REGEX_V_MS_PREFIX, "ms-").replace(REGEX_D_DASH_ALPHA, fcamelCase);
    },
    nodeName: function(elem, name) {
        return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
    },
    each: function(obj, callback, args)
    {
        var name, i = 0, length = obj.length, isObj = length === undefined || tri4m.isFunction(obj);
 
        if(args)
        {
            if(isObj)
            {
                for(name in obj)
                    if(callback.apply(obj[name], args) === false)
                        break;
            }
            else
            {
                for(; i < length;)
                    if(callback.apply(obj[i++], args) === false)
                        break;
            }
        }
        else
        {
            if(isObj)
            {
                for(name in obj)
                    if(callback.call(obj[name], name, obj[name]) === false)
                        break;
            } 
            else
            {
                for(; i < length;)
                    if(callback.call(obj[i], i, obj[i++]) === false)
                        break;
            }
        }
 
        return obj;
    },
    trim: function(text)
    {
        if(ECMA_trim
        && !ECMA_trim.call("\uFEFF\xA0"))
        {
            return (function(text)
            {
                return text == null
                    ? ""
                    : ECMA_trim.call(text);
            })(text);
        }
        else
        {
            return (function(text)
            {
                return text == null
                ? ""
                : (text + "").replace(rtrim, "");
            })(text);
        }
    },
    makeArray: function(arr, results)
    {
        var type, ret = results || [];
 
        if(arr == null)
            return ret;
            
        type = tri4m.type(arr);
 
        if(arr.length == null
        || type === "string"
        || type === "function"
        || type === "regexp"
        || tri4m.isWindow(arr))
        {
            ECMA_push.call(ret, arr);
        }
        else
        {
            tri4m.merge(ret, arr);
        }
 
        return ret;
    },
    inArray: function(elem, arr, i) {
        var len;
 
        if(arr)
        {
            if(ECMA_indexOf)
                return ECMA_indexOf.call(arr, elem, i);
    
            len = arr.length;
            i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
            
            for(; i < len; i++)
                if(i in arr
                && arr[i] === elem)
                    return i;
        }
 
        return -1;
    },
    merge: function(first, second)
    {
        var l = second.length, i = first.length, j = 0;
 
        if(typeof l === "number")
        {
            for(; j < l; j++)
                first[i++] = second[j];
        }
        else
        {
            while(second[j] !== undefined)
                first[i++] = second[j++];
        }
 
        first.length = i;
 
        return first;
    },
    grep: function(elems, callback, inv)
    {
        var retVal, ret = [], i = 0, length = elems.length;
        
        inv = !!inv;
 
        for(; i < length; i++)
        {
            retVal = !!callback(elems[i], i);
            if(inv !== retVal)
                ret.push(elems[i]);
        }
 
        return ret;
    },
    map: function(elems, callback, arg)
    {
        var value, key, ret = [], i = 0, length = elems.length,
        isArray = elems instanceof tri4m
                || length !== undefined 
                    && typeof length === "number"
                    && ((length > 0 && elems[0] && elems[length -1])
                        || length === 0
                        || tri4m.isArray(elems));
 
        if(isArray)
        {
            for(; i < length; i++)
            {
                value = callback(elems[i], i, arg);
 
                if(value != null)
                    ret[ret.length] = value;
            }
        }
        else
        {
            for(key in elems)
            {
                value = callback(elems[key], key, arg);
                
                if(value != null)
                    ret[ret.length] = value;
            }
        }
 
        return ret.concat.apply([], ret);
    },
    guid: 1,
    proxy: function(fn, context)
    {
        var tmp, args, proxy;
 
        if(typeof context === "string")
        {
            tmp = fn[context];
            context = fn;
            fn = tmp;
        }
 
        if(!tri4m.isFunction(fn))
            return undefined;
 
        args = ECMA_slice.call(arguments, 2);
        proxy = function()
        {
            return fn.apply(context, args.concat(ECMA_slice.call(arguments)));
        };
        
        proxy.guid = fn.guid = fn.guid || tri4m.guid++;
 
        return proxy;
    },
    access: function(elems, fn, key, value, chainable, emptyGet, pass)
    {
        var exec, bulk = key == null, i = 0, length = elems.length;
        
        if(key
        && typeof key === "object")
        {
            for(i in key)
                tri4m.access(elems, fn, i, key[i], 1, emptyGet, value);
            
            chainable = 1;
        }
        else if(value !== undefined)
        {
            exec = pass === undefined && tri4m.isFunction(value);
 
            if(bulk)
            {
                if(exec)
                {
                    exec = fn;
                    
                    fn = function(elem, key, value)
                    {
                        return exec.call(tri4m(elem), value);
                    };
                }
                else
                {
                    fn.call(elems, value);
                    fn = null;
                }
            }
 
            if(fn)
                for(; i < length; i++)
                    fn(elems[i], key, exec ? value.call(elems[i], i, fn(elems[i], key)) : value, pass);
 
            chainable = 1;
        }
 
        return chainable
            ? elems
            : bulk
                ? fn.call(elems)
                : length
                    ? fn(elems[0], key)
                    : emptyGet;
    },
    now: function()
    {
        return (new Date()).getTime();
    },
    loadScript: function(src, callback)
    {
        var head = document.getElementsByTagName('head')[0],
            script = document.createElement('script');
            done = false;
        
        script.setAttribute('src', src);
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('charset', 'utf-8');
        
        script.onload = script.onreadstatechange = function()
        {
            if(!done
            && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete'))
            {
                done = true;
                script.onload = script.onreadystatechange = null;
                if(callback)
                {
                    callback();
                }
            }
        };
        
        head.insertBefore(script, head.firstChild);
    },
    toRegister :
    {
        expr :
        {
            ':' : {}
        }
    }
});
 
        
tri4m.bootstrap.promise = function(obj)
{
    if(!bootstrapList)
    {
        bootstrapList = tri4m.Deferred();
        
        if(document.readyState === "complete")
        {
            setTimeout(tri4m.bootstrap, 1);
        }
        else if(document.addEventListener)
        {
            document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);
            window.addEventListener("load", tri4m.bootstrap, false);
        }
        else
        {
            document.attachEvent("onreadystatechange", DOMContentLoaded);
            window.attachEvent("onload", tri4m.bootstrap);
            var top = false;
 
            try
            {
                top = window.frameElement == null && document.documentElement;
            }
            catch(e)
            {
            }
 
            if(top && top.doScroll)
            {
                (function doScrollCheck()
                {
                    if(!tri4m.isBootstrapped)
                    {
                        try
                        {
                            top.doScroll("left");
                        }
                        catch(e)
                        {
                            return setTimeout(doScrollCheck, 50);
                        }
 
                        tri4m.bootstrap();
                    }
                })();
            }
        }
    }
    
    return bootstrapList.promise(obj);
};
 
tri4m.compstrap.promise = function(obj)
{
    if(!compstrapList)
        compstrapList = tri4m.Deferred();
    
    return compstrapList.promise(obj);
};
 
tri4m.each
(
    "Boolean Number String Function Array Date RegExp Object".split(" "),
    function(i, name)
    {
        ECMA_classType["[object " + name + "]"] = name.toLowerCase();
    }
);
 
plat4m = tri4m(document);
 
 
var optionsCache = {};
var createOptions = function(options)
{
    var object = optionsCache[options] = {};
    tri4m.each
    (
        options.split(REGEX_C_SPACE),
        function(_, flag)
        {
            object[flag] = true;
        }
    );
    
    return object;
};
 
tri4m.Callbacks = function(options)
{
    options = typeof options === "string"
        ? (optionsCache[options] || createOptions(options))
        : tri4m.extend({}, options);
 
    var memory,
        fired,
        firing,
        firingStart,
        firingLength,
        firingIndex,
        list        = [],
        stack       = !options.once && [],
        fire = function(data)
        {
            memory      = options.memory && data;
            fired       = true;
            firingIndex = firingStart || 0;
            firingStart = 0;
            firingLength    = list.length;
            firing      = true;
            
            for(; list && firingIndex < firingLength; firingIndex++)
            {
                if(list[firingIndex].apply(data[0], data[1]) === false
                && options.stopOnFalse)
                {
                    memory = false;
                    break;
                }
            }
            
            firing = false;
            
            if(list)
            {
                if(stack)
                {
                    if(stack.length)
                        fire(stack.shift());
                }
                else if(memory)
                {
                    list = [];
                }
                else
                {
                    self.disable();
                }
            }
        },
        self = {
            add : function()
            {
                if(list)
                {
                    var start = list.length;
                    
                    (function add(args)
                    {
                        tri4m.each(args, function(_, arg)
                        {
                            var type = tri4m.type(arg);
                            
                            if(type === "function")
                            {
                                if(!options.unique
                                || !self.has(arg))
                                    list.push(arg);
                            }
                            else if(arg
                            && arg.length
                            && type !== "string")
                            {
                                add(arg);
                            }
                        });
                    })(arguments);
                    
                    if(firing)
                    {
                        firingLength = list.length;
                    }
                    else if(memory)
                    {
                        firingStart = start;
                        fire(memory);
                    }
                }
                
                return this;
            },
            remove: function()
            {
                if(list)
                {
                    tri4m.each
                    (
                        arguments,
                        
                        function(_, arg)
                        {
                            var index;
                            
                            while((index = tri4m.inArray(arg, list, index)) > -1)
                            {
                                list.splice(index, 1);
                                if(firing)
                                {
                                    if(index <= firingLength)
                                        firingLength--;
                                        
                                    if(index <= firingIndex)
                                        firingIndex--;
                                }
                            }
                        }
                    );
                }
                
                return this;
            },
            has: function(fn)
            {
                return tri4m.inArray(fn, list) > -1;
            },
            empty: function()
            {
                list = [];
                return this;
            },
            disable: function()
            {
                list = stack = memory = undefined;
                return this;
            },
            disabled: function()
            {
                return !list;
            },
            lock: function()
            {
                stack = undefined;
                if(!memory)
                    self.disable();
                
                return this;
            },
            locked: function()
            {
                return !stack;
            },
            fireWith: function(context, args)
            {
                args = args || [];
                args = [context, args.slice ? args.slice() : args];
                
                if(list
                && (!fired || stack))
                {
                    if(firing)
                    {
                        stack.push(args);
                    }
                    else
                    {
                        fire(args);
                    }
                }
                
                return this;
            },
            fire: function()
            {
                self.fireWith(this, arguments);
                return this;
            },
            fired: function()
            {
                return !!fired;
            }
        };
 
    return self;
};
 
tri4m.extend(
{
    Deferred: function(func)
    {
        var     tuples =
            [   /* action, add listener, listener list, final state */
                ["resolve", "done",     tri4m.Callbacks("once memory"), "resolved"],
                ["reject",  "fail",     tri4m.Callbacks("once memory"), "rejected"],
                ["notify",  "progress", tri4m.Callbacks("memory")]
            ],
            state = "pending",
            promise =
            {
                state: function()
                {
                    return state;
                },
                always: function()
                {
                    deferred.done(arguments).fail(arguments);
                    return this;
                },
                then: function(/* fnDone, fnFail, fnProgress */)
                {
                    var fns = arguments;
                    return tri4m.Deferred(function(newDefer)
                    {
                        tri4m.each(tuples, function(i, tuple)
                        {
                            var action = tuple[0],
                                fn = fns[i];
                            
                            deferred[tuple[1]](tri4m.isFunction(fn)
                                ? function()
                                {
                                    var returned = fn.apply(this, arguments);
                                    if(returned && tri4m.isFunction(returned.promise))
                                    {
                                        returned.promise()
                                            .done(newDefer.resolve)
                                            .fail(newDefer.reject)
                                            .progress(newDefer.notify);
                                    }
                                    else
                                    {
                                        newDefer[action + "With"](this === deferred
                                            ? newDefer
                                            : this, [returned]);
                                    }
                                }
                                : newDefer[action]
                            );
                        });
                        
                        fns = null;
                        
                    }).promise();
                },
                promise: function(obj)
                {
                    return obj != null
                        ? tri4m.extend(obj, promise)
                        : promise;
                }
            },
            deferred = {};
 
        promise.pipe = promise.then;
        
        tri4m.each(tuples, function(i, tuple)
        {
            var list = tuple[2], stateString = tuple[3];
            promise[tuple[1]] = list.add;
            
            if(stateString)
            {
                list.add
                (
                    function()
                    {
                        state = stateString;
                    },
                    tuples[i ^ 1][2].disable,
                    tuples[2][2].lock
                );
            }
 
            deferred[tuple[0]] = list.fire;
            deferred[tuple[0] + "With"] = list.fireWith;
        });
 
        promise.promise(deferred);
 
        if(func)
            func.call(deferred, deferred);
 
        return deferred;
    },
    when: function(subordinate /* , ..., subordinateN */)
    {
        var     i       = 0,
            resolveValues   = core_slice.call(arguments),
            length      = resolveValues.length,
            remaining   = length !== 1 || (subordinate && tri4m.isFunction(subordinate.promise)) ? length : 0,
            deferred    = remaining === 1 ? subordinate : tri4m.Deferred(),
            updateFunc = function(i, contexts, values)
            {
                return function(value)
                {
                    contexts[i] = this;
                    values[i]   = arguments.length > 1 ? core_slice.call(arguments) : value;
                    
                    if(values === progressValues)
                    {
                        deferred.notifyWith(contexts, values);
                    }
                    else if(!(--remaining))
                    {
                        deferred.resolveWith(contexts, values);
                    }
                };
            },
            progressValues, progressContexts, resolveContexts;
 
        if(length > 1)
        {
            progressValues      = new Array(length);
            progressContexts    = new Array(length);
            resolveContexts     = new Array(length);
            
            for(; i < length; i++)
            {
                if(resolveValues[i]
                && tri4m.isFunction(resolveValues[i].promise))
                {
                    resolveValues[i].promise()
                        .done(updateFunc(i, resolveContexts, resolveValues))
                        .fail(deferred.reject)
                        .progress(updateFunc(i, progressContexts, progressValues));
                }
                else
                {
                    --remaining;
                }
            }
        }
        
        if(!remaining)
            deferred.resolveWith(resolveContexts, resolveValues);
 
        return deferred.promise();
    }
});
 
tri4m.extend
(
    {
        lib :
        {
            exception :
            {
                Throwable : function(name)
                {
                    var name = name;
                    
                    var constructor = function(message)
                    {
                        //Error.apply(this, arguments);
                        if(this == window) return new arguments.callee(message, level);
                        
                        this.message    = message || '';
                        this.name   = name + '.Exception';
                    };
                    
                    constructor.name = name || 'tri4m.lib.exception.Throwable';
                    constructor.prototype.toString = Error.prototype.toString;
                    
                    return constructor;
                }
            },
            loader :
            {
                /**
                 * @param string src
                 * @param object lfo        the expected object
                 * @param function onload
                 * @param function callback
                 */
                Javascript : function(options)
                {
                    this.name = 'tri4m.lib.loader.Javascript';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    var tried   = false;
                    var avail   = false;
                    
                    var __settings = tri4m.extend(
                    {
                        src     : null,
                        lfo     : null,
                        success     : null
                    }, options);
                    
                    this.load = function()
                    {
                        if(true === tried)
                            return this;
                            
                        tried = true;
                            
                        if(null === __settings.src)
                            throw new this.Exception('src is null.');
                        
                        /* NullReferenceError....
                        if(typeof __settings.lfo !== 'undefined' && __settings.lfo !== null)
                        {
                            tri4m.log('lfo is avail: ' + tri4m.objectToString(__settings.lfo));
                            
                            avail = true;
                            __settings.callback(this);
                            return this;
                        }
                        
                        */
                        
                        tri4m.log('Load script ' + __settings.src);
                        
                        try
                        {
                            var head = document.getElementsByTagName('head')[0],
                                script = document.createElement('script');
                        
                            script.setAttribute('src', __settings.src);
                            script.setAttribute('type', 'text/javascript');
                            script.setAttribute('charset', 'utf-8');
                            
                            script.onload = script.onreadstatechange = function()
                            {
                                if(!this.readyState
                                || this.readyState == 'loaded'
                                || this.readyState == 'complete')
                                {
                                    script.onload = script.onreadystatechange = null;
                                    
                                    if(tri4m.isFunction(__settings.success))
                                        __settings.success(__settings);
                                        
                                }
                            };
                        
                            head.insertBefore(script, head.firstChild);
                            
                        }
                        catch(e)
                        {
                            throw new this.Exception('Unable to append javasript ' + __settings.src)
                        }
                        
                        
                        return this;
                    }
                },
                /**
                 * @param string src
                 * @param object lfo        the expected object
                 * @param function onload
                 * @param function callback
                 */
                Stylesheet : function(options)
                {
                    this.name = 'tri4m.lib.loader.Stylesheet';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    var tried   = false;
                    var avail   = false;
                    
                    var __settings = tri4m.extend(
                    {
                        src     : null,
                        lfo     : null,
                        success     : null
                    }, options);
                    
                    this.load = function()
                    {
                        if(true === tried)
                            return this;
                            
                        tried = true;
                            
                        if(null === __settings.src)
                            throw new this.Exception('src is null.');
                        
                        /* NullReferenceError....
                        if(typeof __settings.lfo !== 'undefined' && __settings.lfo !== null)
                        {
                            tri4m.log('lfo is avail: ' + tri4m.objectToString(__settings.lfo));
                            
                            avail = true;
                            __settings.callback(this);
                            return this;
                        }
                        
                        */
                        
                        tri4m.log('Load script ' + __settings.src);
                        
                        try
                        {
                            var head = document.getElementsByTagName('head')[0],
                                script = document.createElement('link');
                        
                            script.setAttribute('src', __settings.src);
                            script.setAttribute('type', 'text/css');
                            script.setAttribute('media', 'all');
                            
                            script.onload = script.onreadstatechange = function()
                            {
                                if(!this.readyState
                                || this.readyState == 'loaded'
                                || this.readyState == 'complete')
                                {
                                    script.onload = script.onreadystatechange = null;
                                    
                                    if(tri4m.isFunction(__settings.success))
                                        __settings.success(__settings);
                                        
                                }
                            };
                        
                            head.insertBefore(script, head.firstChild);
                            
                        }
                        catch(e)
                        {
                            throw new this.Exception('Unable to append stylesheet ' + __settings.src)
                        }
                        
                        
                        return this;
                    }
                },
                /**
                 * Queue-Loader based on Automation-Player
                 *
                 *
                 * var Loader = new tri4m.lib.loader.Queue('Javascript');
                 *
                 * var myComplete = function() { Loader.next(); alert('whohoo'); }
                 *
                 * Loader.push(new tri4m.lib.loader.Javascript({src : 'swfobject.js', success : Loader.next}))
                 * Loader.push(new tri4m.lib.loader.Javascript({src : 'whoohooo.js', success : myComplete }));
                 * Loader.push(new tri4m.lib.loader.Javascript({src : 'another.js', success : Loader.next }));
                 * Loader.start();
                 *
                 *
                 * jQuery is ready before we init our plugins:
                 * plat4m.bootstrap(function()
                 * {
                 *  var JS = tri4m.lib.loader.Javascript, JSLoader = tri4m.lib.loader.Queue,
                 *      Compstrap = new JSLoader,
                 *      Bootstrap = new JSLoader({ success: Compstrap.start });
                 *  
                 *  Bootstrap.push(new JS({ src : 'http://localfrost/wp-content/plugins/tri4m/jquery.js', success : Bootstrap.next }));
                 *  Compstrap.push(new JS({ src : 'http://localfrost/wp-content/plugins/tri4m/tri4mQtLoader/js/tri4m.QtLoader.js' }));
                 *  
                 *  setTimeout
                 *  (
                 *      function()
                 *      {
                 *          typeof jQuery === 'undefined'
                 *              ? Bootstrap.start()
                 *              : Compstrap.start();
                 *      } , 200
                 *  );
                 * });
                 *
                 * @note calling Loader.next() in File-callback is required
                 * @see ri4m.lib.automation.Player
                 */
                Queue : function(options) 
                {
                    var __methods = new tri4m.lib.method.Hook,
                        __player = new tri4m.lib.automation.Player(options);
                    
                    /**
                     * @param tri4m.lib.loader.File File
                     */
                    this.push = function(File)
                    {
                        __methods.push(File.load);
                        return this;
                    }
                    
                    /**
                     * start
                     */
                    this.start = function()
                    {   
                        __player.setup(__methods).play();
                        return this;
                    }
                    
                    /**
                     * next
                     */
                    this.next = function()
                    {
                        __player.next();
                        return this;
                    }
                }
            },
            property :
            {
                /**
                 * value for value-queue
                 *
                 * overwrite is allowed or not
                 *
                 * @param value mixed
                 * @param protect bool true: can not overwrite existing value
                 */
                Value : function(value, protect)
                {
                    this.name = 'tri4m.lib.property.Value';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    var __value = value || null;
                    var __protect = (protect === true) ? true : false;
                    
                    /**
                     * get value
                     * @return mixed
                     */
                    this.get = function()
                    {
                        return __value;
                    };
                    
                    /**
                     * set value
                     *
                     * this has no effect, if __protect is true
                     * @return tri4m.lib.property.Value
                     */
                    this.set = function(value)
                    {
                        if(__protect === true)
                            throw new this.Exception(value + ' is protected', 3);
                        
                        __value = value;
                        return this;
                    };
                    
                    /**
                     * get variable as object
                     *
                     * @return object
                     */
                    this.toObject = function()
                    {
                        return {
                            value   : __value,
                            protect : __protect
                        };
                    };
                },
                /**
                 * value registry
                 *
                 * store vars with values
                 *
                 * // new value-queue
                 * var foo = new tri4m.lib.property.Registry();
                 *
                 * // var "baz"
                 * foo.register('baz', 'baz: bar'); log.t100(foo.get('baz')); // baz: bar
                 * foo.set('baz', 'baz: bar -> foo'); log.t100(foo.get('baz')); // baz: foo
                 *
                 * // protected var "foo"
                 * foo.register('foo', 'foo: lol', true); log.t100(foo.get('foo')); // foo: lol
                 * foo.set('foo', 'foo: lol -> rofl'); log.t100(foo.get('foo')); // foo: lol
                 */
                Registry : function()
                {
                    this.name = 'tri4m.lib.property.Registry';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    var __data = {};
                    
                    /**
                     * register value-instance
                     *
                     * @param name string instance-name
                     * @param value mixed
                     * @param protect bool true: can not overwrite existing value
                     * @see tri4m.lib.property.Value()
                     * @return tri4m.lib.property.Registry
                     */
                    this.register = function(name, value, protect)
                    {
                        if(this.isset(name) === true)
                            throw new this.Exception('Unable to register existing property ' +  name, 3);
                        
                        __data[name] = new tri4m.lib.property.Value(value, protect);
 
                        return this;
                    };
                    
                    /**
                     * unregister value-instance
                     *
                     * @param name string instance-name
                     * @return tri4m.lib.property.Registry
                     */
                    this.unregister = function(name)
                    {
                        if(this.isset(name) === false)
                            return this;
                        
                        delete _data[name]
 
                        return this;
                    };
 
                    /**
                     * isset instance
                     *
                     * @param name string instance-name
                     * @return bool
                     */
                    this.isset = function(name)
                    {
                        return (!__data[name]) ? false : true;
                    };
 
                    /**
                     * get value of instance
                     *
                     * @param name string instance-name
                     * @see tri4m.lib.property.Value.get()
                     * @return tri4m.lib.property.Value || null
                     */
                    this.get = function(name)
                    {
                        return ((this.isset(name) === true) ? __data[name].get() : null);
                    };
 
                    /**
                     * set value of instance
                     *
                     * you must register your variable at first!
                     * you can not use this registry as garbage dump!
                     *
                     * @param name string instance-name
                     * @param value mixed
                     * @see tri4m.lib.property.Value.set()
                     * @return tri4m.lib.property.Registry
                     */
                    this.set = function(name, value)
                    {
                        if(false === this.isset(name))
                            throw new this.Exception('Unable to update value for ' +  name + ': not found', 3);
                        
                        try{ __data[name].set(value); }
                        catch(e){ throw new this.Exception('Unable update value for ' +  name, 3); }
                        
                        return this;
                    };
 
                    /**
                     * get queue as object
                     *
                     * @return tri4m.lib.property.Registry  as propertyName:propertyValue object
                     */
                    this.toObject = function()
                    {
                        var q = {};
                        for(i in __data)
                            q[i] = __data[i].toObject();
                        return q;
                    };
 
                    /**
                     * get queue as value object
                     *
                     * @return tri4m.lib.property.Registry.__data as propertyValue object
                     */
                    this.toValueObject = function()
                    {
                        var q = {};
                        for(i in __data)
                            q[i] = __data[i].toObject().value;
                        return q;
                    };
 
                    /**
                     * get queue as property object
                     *
                     * @return tri4m.lib.property.Registry.__data as propertyName object
                     */
                    this.toPropertyObject = function()
                    {
                        var q = {};
                        var k = 0;
                        for(i in __data)
                        {
                            q[k] = i;
                            k++;
                        }
                        return q;
                    };
                }
            },
            method :
            {
                /**
                 * method FIFO
                 *
                 * @param runonce bool true: terminate queue on exec
                 *
                 * // some stuff
                 * var test11 = function(){log.t100('test1.1')};
                 * var test12 = function(){log.t100('test1.2')};
                 *
                 * // default queue
                 * var bar = new tri4m.lib.method.Hook;
                 * bar.push(test11).push(test12)
                 *  .execute()  // test1.1 test1.2
                 *  .execute(); // test1.1 test1.2
                 *
                 * // run-once queue
                 * var baz = new tri4m.lib.method.Hook(true);
                 * baz.push(test11).push(test12)
                 *  .execute()  // test1.1 test1.2
                 *  .execute(); // nothing
                 */
                Hook : function(runonce)
                {
                    this.name = 'tri4m.lib.method.Hook';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    var __hook = [];
                    var __runonce = (runonce !== true) ? false : true;
 
                    /**
                     * add function to queue
                     *
                     * @param fn function
                     * @return tri4m.lib.method.Hook
                     */
                    this.push = function(fn)
                    {
                        __hook.push(fn);
                        return this;
                    };
 
                    /**
                     * execute queue
                     *
                     * @return tri4m.lib.method.Hook
                     */
                    this.execute = function()
                    {
                        if(__hook.length === 0)
                            return this;
 
                        if(__runonce === false)
                            for(i in __hook) __hook[i]();
                        else
                            while(__hook.length > 0) (__hook.shift())();
 
                        return this;
                    };
 
                    /**
                     * terminate queue
                     *
                     * @return tri4m.lib.method.Hook
                     */
                    this.reset = function()
                    {
                        __hook = [];
                        return this;
                    };
 
                    /**
                     * get queue as array
                     *
                     * @return tri4m.lib.method.Hook.__hook... imho as copy
                     */
                    this.toArray = function()
                    {
                        var a = __hook;
                        return a;
                    };
                },
                /**
                 * method hook registry
                 *
                 * // some stuff
                 * var test11 = function(){log.t100('test1.1')};
                 * var test12 = function(){log.t100('test1.2')};
                 * var test21 = function(){log.t100('test2.1')};
                 * var test22 = function(){log.t100('test2.2')};
                 *
                 * // create registry queue
                 * var foo = new tri4m.lib.method.Registry();
                 *
                 * // default queue
                 * foo.register('test1').push('test1', test11).push('test1', test12)
                 *  .execute('test1')   // test1.1 test1.2
                 *  .execute('test1');  // test1.1 test1.2
                 *
                 * // run-once queue
                 * foo.register('test2', true).push('test2', test11).push('test2', test12)
                 *  .execute('test2')   // test2.1 test2.2
                 *  .execute('test2');  // nothing
                 *
                 *
                 * // shorthand:
                 * // default queue
                 * foo.get('test3').push(test21).push(test22)
                 *  .execute()  // test2.1 test2.2
                 *  .execute(); // test2.1 test2.2
                 *
                 * // run-once queue
                 * foo.get('test4', true).push(test21).push(test22)
                 *  .execute()  // test2.1 test2.2
                 *  .execute(); // nothing
                 */
                Registry : function()
                {
                    this.name = 'tri4m.lib.method.Registry';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    var __hook = new tri4m.lib.property.Registry();
 
                    /**
                     * register queue instance
                     *
                     * @param name string instance-name
                     * @param runonce bool
                     * @see tri4m.lib.method.Hook()
                     * @see tri4m.lib.property.Registry.register()
                     * @return tri4m.lib.method.Registry
                     */
                    this.register = function(name, runonce)
                    {
                        __hook.register(name, new tri4m.lib.method.Hook(runonce), true);
                        return this;
                    };
 
                    /**
                     * isset instance
                     *
                     * @param name string instance-name
                     * @see tri4m.lib.property.Registry.isset()
                     * @return bool tri4m.lib.property.Registry.isset()
                     */
                    this.isset = function(name)
                    {
                        return __hook.isset(name);
                    };
 
                    /**
                     * get/create queue instance
                     *
                     * @param name string instance-name
                     * @param runonce bool
                     * @see tri4m.lib.method.Hook
                     * @return tri4m.lib.method.Hook
                     */
                    this.get = function(name, runonce)
                    {
                        //log.t100(__hook.get(name).className());
                        if(this.isset(name) === false)
                            this.register(name, runonce);
                        return __hook.get(name);
                    };
 
                    /**
                     * execute queue of instance
                     *
                     * @param name string instance-name
                     * @see tri4m.lib.method.Hook.execute()
                     * @return tri4m.lib.method.Registry
                     */
                    this.execute = function(name)
                    {
                        if(this.isset(name) === true)
                            this.get(name).execute();
                        return this;
                    };
 
                    /**
                     * terminate queue
                     *
                     * @see tri4m.lib.method.Hook.reset()
                     * @return tri4m.lib.method.Registry
                     */
                    this.reset = function(name)
                    {
                        if(this.isset(name) === true)
                            this.get(name).reset();
                        return this;
                    };
 
                    /**
                     * add function to queue of instance
                     *
                     * @param name string instance-name
                     * @param fn function
                     * @see tri4m.lib.method.Hook.push()
                     * @return tri4m.lib.method.Registry
                     */
                    this.push = function(name, fn)
                    {
                        if(this.isset(name) === true)
                            this.get(name).push(fn);
                        return this;
                    };
 
                    /**
                     * get queue as object
                     *
                     * @return tri4m.lib.property.Registry.__hook as copy
                     */
                    this.toObject = function()
                    {
                        return __hook.toObject();
                    };
 
                    /**
                     * get queue as object
                     *
                     * @return tri4m.lib.property.Registry.__hook as copy
                     */
                    this.getHook = function()
                    {
                        var q = __hook;
                        return q;
                    };
                }
            },
            automation :
            {
                /**
                 * animation playlist player
                 *
                 * split methods from tri4m.lib.method.Hook
                 * to partials
                 *
                 * @example tri4m.lib.loader.Queue
                 *
                 *
                 * step 1:
                 *  create your methods:
                 *
                 * ...
                 * Env :
                 * {
                 *  Playlists : null,
                 *  Animation :
                 *  {
                 *      test10 : function(){
                 *          log.t100('test10');
                 *          tri4m('ul.list li').css({height: 5});
                 *          tri4m.Env.Playlists.next('intro');
                 *      },
                 *      test11 : function(){
                 *          log.t100('test11');
                 *          tri4m('ul.list li').animate({height: 140}, 2200, function()
                 *          {
                 *              log.t100('test11 anim callback');
                 *              tri4m.Env.Playlists.next('intro');
                 *          });
                 *      },
                 *      test12 : function(){
                 *          log.t100('test12');
                 *          tri4m('ul.list li').css({width: 10});
                 *          tri4m.Env.Playlists.next('intro');
                 *      },
                 *      test13 : function(){
                 *          log.t100('test13');
                 *          tri4m('ul.list li').animate({width: 140}, 2200);
                 *          tri4m.Env.Playlists.next('intro');
                 *      }
                 *  }
                 * },
                 * ...
                 *
                 *
                 * step 2:
                 *  init the animation registry and register
                 *  the methods into sections, e.g. "intro" or "button-hover"
                 *
                 * ...
                 * test : function()
                 * {
                 *  tri4m.Env.Playlists =
                 *      new tri4m.lib.automation.Registry();
                 *
                 *  tri4m.Env.Playlists.register('intro')
                 *      .push(tri4m.Env.Animation.test10)
                 *      .push(tri4m.Env.Animation.test11)
                 *      .push(tri4m.Env.Animation.test12)
                 *      .push(tri4m.Env.Animation.test13)
                 *  ;
                 *  tri4m.Env.Playlists.play('intro');
                 * },
                 * ...
                 *
                 *
                 * @todo    lock, pause, start, stop not really implemented
                 */
                Player : function(options)
                {
                    this.name = 'tri4m.lib.automation.Player';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    
                    var __settings = tri4m.extend(
                    {
                        onPlayStart : tri4m.noop,
                        onPlayNext  : tri4m.noop,
                        onPlayPause : tri4m.noop,
                        onPlayStop  : tri4m.noop,
                        success : tri4m.noop
                    }, options);
                    
                    /**
                     * method registry queue
                     */
                    var __registry = null;
 
                    /**
                     * __isPlaying bool status quo
                     */
                    var __isPlaying = false;
 
                    /**
                     * translated registry as func-callback-object
                     */
                    var __playlist = [];
 
                    /**
                     * working-copy of __playlist
                     */
                    var __playqueue = [];
 
                    /**
                     * counter
                     */
                    var __playedTimes = 0;
 
                    /**
                     * install method queue
                     *
                     * @param registry tri4m.lib.method.Hook
                     * @return tri4m.lib.automation.Player
                     */
                    this.setup = function(registry)
                    {
                        if(__registry !== null)
                            return this;
 
                        __registry = registry;
 
                        var methods = __registry.toArray();
 
                        for(var i = 0; i < methods.length; i++)
                        {
                            var fn = methods[i];
 
                            if(typeof fn !== 'function')
                                continue;
 
                            var cb = function(){};
                            
                            if((next = methods[i+1]))
                            {
                                if(typeof next !== 'function')
                                    continue;
 
                                cb = next;
                            }
 
                            var item = {
                                method: fn,
                                callback :
                                {
                                    method : cb
                                }
                            };
                            
                            __playlist.push(item);
                        }
                        
                        return this;
                    };
 
                    /**
                     * init playing
                     *
                     * @return tri4m.lib.automation.Player
                     */
                    this.play = function()
                    {
                        if(true === this.isPlaying())
                            return false;
 
                        if(__playqueue.length === 0)
                        {
                            __playedTimes++;
                            __settings.onPlayStart();
                        }
                            
                        
                        __isPlaying = true;
                        __playqueue = __playlist;
                        
 
                        this.next();
                        return this;
                    };
 
                    /**
                     * play next method
                     *
                     * test11 : function(){
                     *  log.t100('test11');
                     *  tri4m('ul.list li').animate({height: 140}, 2200, function()
                     *  {
                     *      log.t100('test11 anim callback');
                     *      tri4m.Env.Playlists.next('intro');
                     *  });
                     * },
                     *
                     * @return tri4m.lib.automation.Player
                     */
                    this.next = function()
                    {
                        if(null === __playqueue)
                            return this;
 
                        var next = null;
 
                        if(__playqueue.length > 0)
                            next = __playqueue.shift();
 
                        if(!next)
                        {
                            this.stop();
                            __settings.success();
                            return this;
                        }
 
                        __settings.onPlayNext();
                        next.method();
 
                        return this;
                    };
 
                    /**
                     * pause
                     *
                     * @return tri4m.lib.automation.Player
                     */
                    this.pause = function()
                    {
                        __isPlaying = false;
                        __settings.onPlayPause();
                        return this;
                    };
 
                    /**
                     * stop/abort playing and delete working copy
                     *
                     * @return tri4m.lib.automation.Player
                     */
                    this.stop = function()
                    {
                        __playqueue = [];
                        __isPlaying = false;
                        __settings.onPlayStop();
                        return this;
                    };
 
                    /**
                     * is playing status
                     *
                     * @return bool status quo
                     */
                    this.isPlaying = function()
                    {
                        return __isPlaying;
                    };
                },
                /**
                 * playlist class
                 *
                 * holds a methodhook (playlist) and the player
                 *
                 */
                Playlist : function()
                {
                    this.name = 'tri4m.lib.automation.Playlist';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    /**
                     * method queue/playlist
                     */
                    var __playlist  = new tri4m.lib.method.Hook();
 
                    /**
                     * player
                     */
                    var __player    = new tri4m.lib.automation.Player();
 
                    /**
                     * push method to __playlist
                     *
                     * @param function
                     * @return tri4m.lib.automation.Playlist
                     */
                    this.push = function(fn)
                    {
                        __playlist.push(fn);
                        return this;
                    };
 
                    /**
                     * initialize player and start playing
                     *
                     * @return tri4m.lib.automation.Playlist
                     */
                    this.play = function()
                    {
                        __player.setup(__playlist).play();
                        return this;
                    };
 
                    /**
                     * play next frame
                     *
                     * this is the callback-caller
                     *
                     * test11 : function(){
                     *  log.t100('test11');
                     *  tri4m('ul.list li').animate({height: 140}, 2200, function()
                     *  {
                     *      log.t100('test11 anim callback');
                     *      tri4m.Env.Playlists.next('intro');
                     *  });
                     * },
                     *
                     *
                     * @return tri4m.lib.automation.Playlist
                     */
                    this.next = function()
                    {
                        __player.next();
                        return this;
                    };
                },
                /**
                 * playlist/player registry
                 *
                 * store animation-queues by event-name
                 *
                 */
                Registry : function()
                {
                    this.name = 'tri4m.lib.automation.Registry';
                    this.Exception = new tri4m.lib.exception.Throwable(this.name);
                    
                    var __queue = new tri4m.lib.property.Registry();
 
                    /**
                     * craete a new playlist-instance
                     *
                     * @param string instance name
                     * @return tri4m.lib.automation.Playlist
                     */
                    this.register = function(name)
                    {
                        __queue.register(name, new tri4m.lib.automation.Playlist(), true);
                        return __queue.get(name);
                    };
 
                    /**
                     * get playlist-instance
                     *
                     * @param string instance name
                     * @return tri4m.lib.automation.Playlist
                     */
                    this.get = function(name)
                    {
                        return __queue.get(name);
                    };
                    
                    /**
                     * play a playlist-instance
                     *
                     * @param string instance name
                     * @return tri4m.lib.automation.Registry
                     */
                    this.play = function(name)
                    {
                        __queue.get(name).play();
                        return this;
                    };
                    
                    /**
                     * play next callback
                     *
                     * @param string instance name
                     * @return tri4m.lib.automation.Registry
                     */
                    this.next = function(name)
                    {
                        __queue.get(name).next();
                        return this;
                    };
                }
            }
        }
    }
);
 
tri4m.extend
(
    {
        append :
        {
            /**
             * head:
             *
             * (function(tri4m, undefined)
             * {
             *  tri4m(function()
             *  {
             *      tri4m.append([
             *          'plugin.js',
             *          'another.js'
             *      ],
             *      {
             *          success : function()
             *          {
             *              tri4m.log('-- init my plugin');
             *          }
             *      });
             *  });
             * })(tri4m);
             */
            Javascript : function(src, options, hold)
            {
                var __settings = tri4m.extend
                (
                    {
                        success : tri4m.noop
                    },
                    options
                );
                
                if(typeof stack === 'undefined')
                     stack = new tri4m.lib.loader.Queue({ success : __settings.success });
                
                if(typeof src !== 'string')
                {
                    var i = 0, l = src.length;
                    
                    for(var name in src)
                    {
                        i++;
                        tri4m.append.Javascript(src[name], {}, i !== l)
                    }
                        
                    return tri4m.com;
                }
                
                if(typeof cache === 'undefined')
                    cache = [];
                
                for(var i in cache)
                    if(src === cache[i])
                        return tri4m.com;
                
                cache.push(src);    
                
                tri4m.log('append script ' + src);
                
                     
                var cur = stack;
                
                stack.push(new tri4m.lib.loader.Javascript(
                {
                    //src : src + '?' + Math.random(0, 100000000),
                    src : src,
                    success : cur.next
                    
                }));
                
                if(!hold || hold !== true)
                    stack.start();
                    
                return tri4m;
            },
            Stylesheet : function(src, options, hold)
            {
                var __settings = tri4m.extend
                (
                    {
                        success : tri4m.noop
                    },
                    options
                );
                
                if(typeof stack === 'undefined')
                     stack = new tri4m.lib.loader.Queue({ success : __settings.success });
                
                if(typeof src !== 'string')
                {
                    var i = 0, l = src.length;
                    
                    for(var name in src)
                    {
                        i++;
                        tri4m.append.Stylesheet(src[name], {}, i !== l)
                    }
                        
                    return tri4m.com;
                }
                
                if(typeof cache === 'undefined')
                    cache = [];
                
                for(var i in cache)
                    if(src === cache[i])
                        return tri4m.com;
                
                cache.push(src);    
                
                tri4m.log('append script ' + src);
                
                     
                var cur = stack;
                
                stack.push(new tri4m.lib.loader.Stylesheet(
                {
                    //src : src + '?' + Math.random(0, 100000000),
                    src : src,
                    success : cur.next
                }));
                
                if(!hold || hold !== true)
                    stack.start();
                    
                return tri4m;
            }
        }
    }
);
 
tri4m.com = function(name, base, prototype)
{
    var     fullName,
        existingConstructor,
        constructor,
        basePrototype,
        namespace = name.split(".")[0];
 
    name        = name.split(".")[1];
    fullName    = 'tri4m-' + namespace + "-" + name;
    
 
    if(!prototype)
    {
        prototype   = base;
        base        = tri4m.__Com;
    }
    
    tri4m.toRegister.expr[':'][fullName] = function(elem)
    {
        return !!jQuery.data(elem, fullName);
    };
 
    tri4m[namespace]    = tri4m[namespace] || {};
    existingConstructor = tri4m[namespace][name];
    
    constructor = tri4m[namespace][name] = function(options, element)
    {
        if(!this._create__Com)
            return new constructor(options, element);
 
        if(arguments.length)
            this._create__Com(options, element);
    };
    
    tri4m.extend(constructor, existingConstructor,
    {
        version: prototype.version,
        _proto: tri4m.extend({}, prototype),
        _childConstructors: []
    });
 
    basePrototype       = new base();
    basePrototype.options   = tri4m.com.extend({}, basePrototype.options);
    
    tri4m.each(prototype, function(prop, value)
    {
        if(tri4m.isFunction(value)) {
            prototype[prop] = (function()
            {
                var     _super = function()
                    {
                        return base.prototype[prop].apply(this, arguments);
                    },
                    _superApply = function(args)
                    {
                        return base.prototype[prop].apply(this, args);
                    };
                    
                return function()
                {
                    var __super     = this._super,
                        __superApply    = this._superApply,
                        returnValue;
 
                    this._super     = _super;
                    this._superApply    = _superApply;
                    returnValue         = value.apply(this, arguments);
                    this._super     = __super;
                    this._superApply    = __superApply;
 
                    return returnValue;
                };
            })();
        }
    });
    
    constructor.prototype = tri4m.com.extend
    (
        basePrototype,
        {
            comEventPrefix: name
        },
        prototype,
        {
            constructor:    constructor,
            namespace:  namespace,
            comName:    name,
            comBaseClass:   fullName,
            comFullName:    fullName
        }
    );
 
    if(existingConstructor)
    {
        tri4m.each(existingConstructor._childConstructors, function(i, child)
        {
            var childPrototype = child.prototype;
            tri4m.com(childPrototype.namespace + "." + childPrototype.comName, constructor, child._proto);
        });
        
        delete existingConstructor._childConstructors;
    }
    else
    {
        base._childConstructors.push(constructor);
    }
 
    tri4m.com.bridge(name, constructor);
};
 
tri4m.com.extend = function(target)
{
    var     input       = ECMA_slice.call(arguments, 1),
        inputIndex  = 0,
        inputLength = input.length,
        key,
        value;
        
    for(  ; inputIndex < inputLength; inputIndex++)
    {
        for(key in input[inputIndex])
        {
            value = input[inputIndex][key];
            
            if(input[inputIndex].hasOwnProperty(key) && value !== undefined)
            {
                target[key] = tri4m.isPlainObject(value)
                    ? tri4m.com.extend({}, target[key], value)
                    : value;
            }
        }
    }
    
    return target;
};
 
tri4m.com.bridge = function(name, object)
{
    var fullName = object.prototype.comFullName;
    tri4m.shell[name] = function(options)
    {
        var isMethodCall    = typeof options === "string",
            args        = ECMA_slice.call(arguments, 1),
            returnValue = this;
 
        options = !isMethodCall && args.length
            ? tri4m.com.extend.apply(null, [options].concat(args))
            : options;
 
        if(isMethodCall)
        {
            this.each(function()
            {
                var methodValue, instance = jQuery.data(this, fullName);
                
                if(!instance)
                    return tri4m.log("cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'", 3);
                
                if(!tri4m.isFunction(instance[options]) || options.charAt(0) === "_")
                    return tri4m.log("no such method '" + options + "' for " + name + " com instance", 3);
                
                
                methodValue = instance[options].apply(instance, args);
                
                
                if(methodValue !== instance
                && methodValue !== undefined)
                {
                    returnValue = methodValue && methodValue.jquery
                        ? returnValue.pushStack(methodValue.get())
                        : methodValue;
                        
                    return false;
                }
            });
        }
        else
        {
            this.each(function()
            {
                var instance = tri4m.data(this, fullName);
                
                if(instance)
                {
                    instance.option(options || {})._init();
                }
                else
                {
                    new object(options, this);
                }
            });
        }
 
        return returnValue;
    };
};
 
var uuid            = 0;
tri4m.__Com         = function(options, element) {};
tri4m.__Com._childConstructors  = [];
 
tri4m.__Com.prototype =
{
    comName: "component",
    defaultElement: "<div>",
    options:
    {
        disabled: false,
 
        // callbacks
        create: null
    },
    _create__Com: function(options, element)
    {
        element         = jQuery(element || this.defaultElement || this)[0];
        this.element        = jQuery(element);
        this.uuid       = uuid++;
        this.eventNamespace = "." + this.comName + this.uuid;
        this.options        = tri4m.com.extend
                    (
                        {},
                        this.options,
                        this._getCreateOptions(),
                        options
                    );
        
        if(element !== this)
        {
            jQuery.data(element, this.comName, this);
            jQuery.data(element, this.comFullName, this);
        }
        
        this.element.addClass(this.comFullName);
 
        this._create();
        this._init();
    },
    _getCreateOptions:  tri4m.noop,
    _getCreateEventData:    tri4m.noop,
    _init:          tri4m.noop,
    _log: function(message, level)
    {
        if(typeof this.options.debug === 'undefined')
            return;
            
        if(this.options.debug !== true)
            return;
            
        tri4m.log(this.comName + ': ' + message, level);
    },
    com: function()
    {
        return this.element;
    },
    keyCode: {
        ALT: 18,
        BACKSPACE: 8,
        CAPS_LOCK: 20,
        COMMA: 188,
        COMMAND: 91,
        COMMAND_LEFT: 91, // COMMAND
        COMMAND_RIGHT: 93,
        CONTROL: 17,
        DELETE: 46,
        DOWN: 40,
        END: 35,
        ENTER: 13,
        ESCAPE: 27,
        HOME: 36,
        INSERT: 45,
        LEFT: 37,
        MENU: 93, // COMMAND_RIGHT
        NUMPAD_ADD: 107,
        NUMPAD_DECIMAL: 110,
        NUMPAD_DIVIDE: 111,
        NUMPAD_ENTER: 108,
        NUMPAD_MULTIPLY: 106,
        NUMPAD_SUBTRACT: 109,
        PAGE_DOWN: 34,
        PAGE_UP: 33,
        PERIOD: 190,
        RIGHT: 39,
        SHIFT: 16,
        SPACE: 32,
        TAB: 9,
        UP: 38,
        WINDOWS: 91 // COMMAND
    },
    option: function(key, value)
    {
        var options = key, parts, curOption, i;
 
        if(arguments.length === 0)
            return tri4m.com.extend({}, this.options);
 
        if(typeof key === "string")
        {
            // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
            options = {};
            parts   = key.split(".");
            key = parts.shift();
            
            if(parts.length)
            {
                curOption = options[key] = tri4m.com.extend({}, this.options[key]);
                
                for(i = 0; i < parts.length - 1; i++)
                {
                    curOption[parts[i]] = curOption[parts[i]] || {};
                    curOption       = curOption[parts[i]];
                }
                
                key = parts.pop();
                
                if(value === undefined)
                    return curOption[key] === undefined
                        ? null
                        : curOption[key];
                
                curOption[key] = value;
            }
            else
            {
                if(value === undefined)
                    return this.options[key] === undefined ? null : this.options[key];
                
                options[key] = value;
            }
        }
 
        this._setOptions(options);
 
        return this;
    },
    _setOptions: function(options)
    {
        var key;
 
        for (key in options)
            this._setOption(key, options[key]);
 
        return this;
    },
    _setOption: function(key, value)
    {
        this.options[key] = value;
 
        if(key === "disabled")
        {
            this.com()
                .toggleClass(this.comFullName + "-disabled ui-state-disabled", !!value)
                .attr("aria-disabled", value);
        }
 
        return this;
    }
};
 
tri4m.com("__postInit.__Com",
{
    _create__Com: function()
    {
        tri4m.__Com.prototype._create__Com.apply(this, arguments);
        this._init();
    },
});
 
plat4m.bootstrap(function()
{
    var     JS      = tri4m.lib.loader.Javascript,
        JSLoader    = tri4m.lib.loader.Queue,
        Bootstrap   = new JSLoader({ success : tri4m.compstrap  });
    
    Bootstrap.push(new JS({ src : JQUERY_SRC, success : Bootstrap.next }));
    
    setTimeout
    (
        function()
        {
            typeof jQuery === 'undefined'
                ? Bootstrap.start()
                : tri4m.compstrap();
        },
        JQUERY_INIT_TIME
    );
});
 
window.tri4m = tri4m;
})(window);

Comments