2016年12月26日 星期一

(js)Area88_event.js

////////////////////////////////////////////////////////////////////////////////
/**
 *
 */
////////////////////////////////////////////////////////////////////////////////

(function($) {
    var eventData = new Map();
    $.eventGuid = 0;
    /**
     * 取得或設定事件的資料
     */
    $.eventData_ = function(dom, name, _data) {
        var data;

        if ((data = eventData.get(dom)) == null) {
            eventData.set(dom, {});
            data = eventData.get(dom);
        }
        /* ---------------------------------- */
        if (arguments.length == 2) {
            return data[name];
        } else if (arguments.length == 1) {
            return data;
        }
        /* ---------------------------------- */
        data[name] = _data;
    };
})(Area88_);


////////////////////////////////////////////////////////////////////////////////
/**
 * trigger
 */
(function($) {

    $.trigger_ = function(dom, eventType, data) {
        var eventObj = document.createEvent("CustomEvent");
        eventObj.initCustomEvent(eventType, true, true, data);

        dom.dispatchEvent(eventObj);
    };
    /* ====================================================================== */
    $.fn.trigger_ = function(eventType, data) {
        this.each(function() {
            $.trigger_(this, eventType, data);
        });
    };
    /* ====================================================================== */
})(Area88_);
////////////////////////////////////////////////////////////////////////////////
/**
 * 事件綁定的核心
 */
(function($) {
    /**
     *
     * @param {boolean} one:只執行一次
     */
    $._bindEvent_ = function(dom, types, fn, data, selector, one) {
        debugger;

        var eventData, events, _handle, namespace;
        var one = one ? true : false;

        eventData = $.eventData_(dom);
        (events = eventData.events) || (events = eventData.events = {});
        (_handle = eventData.handle) || (_handle = eventData.handle = handle);
        _handle.elem = dom;

        /* ---------------------------------- */
        types = types.split(/\s+/gi);

        types.forEach(function(type) {
            namespace = type.split(/\./gi);
            type = namespace.shift();


            if (!fn.guid) {
                fn.guid = ++$.eventGuid;
            }

            var _data = {
                one: one,
                type: type,
                data: data,
                handler: fn,
                guid: fn.guid,
                selector: (typeof selector == 'string' ? selector : ''),
                namspace: (namespace.length ? namespace.join('.') : '')
            };

            if (!events[type]) {
                // 若沒有登錄過該事件
                events[type] = [];
                dom.addEventListener(type, _handle);
            }
            events[type].push(_data);
        });

    };
    /* ====================================================================== */
    /**
     * 事件
     */
    function handle() {
        debugger;
        $._dispatch_.apply(handle.elem, arguments);
    };

    /* ====================================================================== */
    /**
     * 只會進來單一事件
     */
    $._dispatch_ = function() {
        debugger;

        alert('_dispatch_');

        var dom = this; // 事件綁定的dom
        var e = arguments[0];
        var type = e.type;
        var currentTarget = e.currentTarget;
        var target = e.target;
        var events = $.eventData_(dom, 'events');

        var handler_array = events[type] || [];

        // 巡迴該事件要執行的fn
        for (var i = 0; i < handler_array.length; i++) {
            var data = handler_array[i];

            var one = data.one;
            var namspace = data.namespace || '';
            var selector = data.selector;
            var handler = data.handler;

            if (selector) {
                var selectDom = document.querySelector(selector);
                if (selectDom !== target) {
                    continue;
                }
            }
            /* ---------------------------------- */

            //只執行一次的任務
            if (one) {
                handler_array.splice(i, 1);
                i--;
            }
            var result = handler.apply(dom, arguments);
            (result === false) && (e.preventDefault());
        };

    };
})(Area88_);
////////////////////////////////////////////////////////////////////////////////
/**
 * 移除事件的核心
 */
(function($) {
    $._unbindEvent_ = function(dom, types, fn, selector) {
        var events = $.eventData_(dom, 'events');

        if (!events) {
            return;
        }
        types = types.split(/\s+/gi);


        types.forEach(function(type) {
            // 不同事件的迴圈
            var namespace_array = type.split(/\./gi);
            type = namespace.shift();


            var handler_array = events[type] || [];

            for (var i = 0; i < handler_array.length; i++) {

                var _namspace_array = data.namespace.split(/\./gi);;
                var _selector = data.selector;
                var _guid = data.guid;

                var del = false;

                if (!del && typeof selector == 'string' && _selector.localeCompare(selector) == 0) {
                    // check selector
                    del = true;
                }

                if (!del && namespace_array.length > 0 && havveNamespace(namespace_array, _namspace_array)) {
                    // check namespace
                    del = true;
                }

                if (!del && typeof fn == 'function' && typeof fn.guid != 'undefined' && fn.guid === _guid) {}

                if (del) {
                    handler_array.splice(i, 1);
                    i--;
                }
            }
        });
    };

    function havveNamespace(array_1, array_2) {
        var result = false;
        loop1: for (i = 0; i < array_1.length; i++) {
            for (j = 0; j < array_2.length; j++) {

                if (array_1[i] === array_2[j]) {
                    result = true;
                    break loop1;
                }
            }
        }

        return result;
    };
})(Area88_);



////////////////////////////////////////////////////////////////////////////////
(function() {
    /**
     * 綁定事件
     */
    $.fn.on = $.fn.on || function(types, selector, data, fn, one) {
        debugger;
        var type, origFn;

        if (data == null && fn == null) {
            // ( types, fn )
            fn = selector;
            data = selector = undefined;
        } else if (fn == null) {
            if (typeof selector === "string") {
                // ( types, selector, fn )
                fn = data;
                data = undefined;
            } else {
                // ( types, data, fn )
                fn = data;
                data = selector;
                selector = undefined;
            }
        }

        if (typeof fn != 'function') {
            return this;
        }
        /* ---------------------------------- */
        this.each(function(i, dom) {
            debugger;
            $._bindEvent_(this, types, fn, data, selector, one);
        });
        return this;
    };

})(Area88_);

/* ========================================================================== */

(function($) {
    /**
     * 移除事件
     */
    $.fn.off = $.fn.off || function(types, selector, fn) {
        if (arguments.length == 2 && typeof selector == "function") {
            // ( types [, fn] )
            fn = selector;
            selector = undefined;
        }

        if (typeof types != 'string') {
            return this;
        }
        /* ---------------------------------- */
        this.each(function(i, dom) {
            $._unbindEvent_(dom, types, fn, selector);
        });
        return this;
    };
})(Area88_);
/* ========================================================================== */
(function($) {
    /**
     * 綁定只執行一次的事件
     */
    $.fn.one = $.fn.one || function(types, selector, data, fn) {
        this.on(types, selector, data, fn, 1);
        return this;
    };
})(Area88_);