This module is used to provide custom events and convert the objects implementing this interface into an event transmitter.
// ================================================ ================/// Event transmitter module ================================ ============================ (function (global, doc) {var dom = global [Doc. URL. replace (/(#. + | \ W)/g, '')]; Dom. define ("emitter", "data", function () {var firetype = "", blank = "" Var ensure = function (array, Neo) {var OBJ = {} For (VAR I = 0, El; El = array [I ++];) {OBJ [El. UUID] = 1} If (! OBJ [Neo. UUID]) {array. push (NEO) };} var events = Dom. events = {special :{}, // used to process individual DOM events BIND: function (type, callback, phase) {// It adds an attribute named uniqueid to the native event sender or any common JS object that can be an event sender to associate a cache body, // store the required data in it, and now we store all the objects named @ events in it, // The @ event table is used to place various event types and the corresponding callback function var target = This, table = Dom. data (target, "@ events") | Dom. data (target, "@ events", {}); If (! Table |! Callback) return; var bag = callback. callback? Callback: {callback: callback, UUID: Dom. UUID ++, type: Type} // ensure that UUID, bag is consistent with the uuid of callback. callback. UUID = bag. UUID; // native DOM events are not allowed to be bound to the same callback function. For details, see the following test // function callback () {alert (1)} // document. addeventlistener ("click", callback, false) // document. addeventlistener ("click", callback, false) type = bag. type; var queue = table [type] = table [type] | []; ensure (queue, bag); If (DOM ["@ emitter"] in Target) {// If the native event sender var special = events. special [Bag. type], setup = events. setup, tag = "@" + type if (special) {type = Special. type | type tag = (bag. live? "@ Live _": "@ special _") + type; Setup = bag. Live? Special. livesetup: Special. Setup} bag. Tag = tag; If (! Table [tag]) {Dom. Log ("setup" + Type + "event...") setup (target, type, events. Handle ,!! Phase); table [tag] = 1 }}, unbind: function (type, bag, phase) {var target = This, table = Dom. data (target, "@ events"); If (! Table) return; If (typeof type = "string") {// If you specify the event type to be removed, type = bag & bag. type | type; var queue = table [type]; If (Queue) {var callback = bag. callback | bag; queue = callback? Table [type]. Filter (function (BAG) {return bag. callback! = Callback;}): []; If (DOM ["@ emitter"] in target) {// if it is a native event sender var special = events. special [type], teardown = events. teardown, tag = "@" + type if (special) {type = Special. type | type tag = (bag. live? "@ Live _": "@ special _") + type; teardown = bag. Live? Special. liveteardown: Special. teardown} var length = queue. Filter (function (BAG) {return bag. Tag = tag}). length; If (! Length) {teardown (target, type, events. Handle ,!! Phase); Dom. log ("teardown" + Type + "event... ") Delete table [tag] }}} else {for (type in table) {If (type. charat (0 )! = "@") Events. unbind (target, type) ;}}, fire: function (type) {var target = This, table = Dom. data (target, "@ events"), argS = Dom. slice (arguments, 1), event if (! Table) return; event = type instanceof jevent? Type: New jevent (type); event.tar get = target; event. fireargs = ARGs; If (DOM ["@ emitter"] in target) {var cur = target, ONTYPE = "on" + type; do {// simulate event bubbling and execute inline Event Events. handle. call (cur, event); If (cur [ONTYPE] & cur [ONTYPE]. call (cur) === false) {event. preventdefault ();} cur = cur. parentnode | cur. ownerdocument | cur === target. ownerdocument & Global;} while (cur &&! Event. ispropagationstopped); If (! Event. isdefapreprevented) {// simulate the default behavior click () Submit () reset () Focus () blur () var old; try {If (ONTYPE & target [type]) {// No need to trigger the internal event old = target [ONTYPE]; If (old) {target [ONTYPE] = NULL;} firetype = type; target [type] () ;}} catch (e) {Dom. log ("dom. events. fire ("+ Type +") Throw errer "+ E);} If (old) {target [ONTYPE] = old;} firetype = blank ;}} else {// Custom Event Events of a common object. handle. call (T Arget, event) ;}}, filter: function (target, parent, expr) {If (Dom. contains (parent, target) {If (typeof expr = "function") {return expr. call (target)} else {return Dom. matchesselector (target, expr); // requires the travel module }}, handle: function (event) {If (firetype = event. type) return undefined; var queue = Dom. data (this, "@ events") [event. type]; If (Queue) {If (! Event. UUID) {event = events. fix (event);} event. currenttarget = This; var emitter = event.tar get, result, // get parameters (only custom parameters are available) ARGs = "fireargs" in event? [Event]. concat (event. fireargs): arguments; // copy the array to prevent the next operation from affecting queue = queue. concat (); // start the unpacking operation for (VAR I = 0, bag; bag = queue [I ++];) {// if it is an event proxy, make sure that the element is in the Enabled state and meets the filter condition if (bag. live & emitter. disabled &&! Events. Filter (emitter, this, bag. Live) {continue;} // gets the callback function result = bag. Callback. Apply (emitter, argS); If (result! = Undefined) {event. result = result; If (result = false) {event. preventdefault (); event. stoppropagation () ;}} if (event. isimmediatepropagationstopped) {break ;}} return event. result;}, fix: function (event) {If (event. UUID) {return event;} var originalevent = event = new jevent (originalevent); For (VAR prop in originalevent) {If (typeof originalevent [prop]! = "Function") {event [prop] = originalevent [prop]} event. wheeldelta = 0; // mousewheel if ("wheeldelta" in originalevent) {var detail = originalevent. wheeldelta; // The scroll direction of the opera 9x series is consistent with that of IE, And if (Global. opera & Global. opera. version ()Example:
Dom. require ("Ready, class, emitter", function () {var A = Dom. factory ({include: Dom. emitter, init: function () {This. defineevents ("click, Mouseover")}); var A = new A;. BIND ("click", function () {alert ([]. slice. call (arguments) // [object event], 1, 2, 3}). fire ("click", 1, 2, 3);. onmouseover (function () {alert ("situ zhengmei")});. fire ("Mouseover") Dom. log ()})
The first window is "1, 2, 3", and the second window is "situ zhengmei". view the structure of instance a under firebug as follows:
The second example only depends on the emitter module.
Dom. require ("emitter", function () {var A = {}; Dom. mix (A, Dom. emitter);. BIND ("data", function () {alert ("11111111")});. BIND ("data", function (e) {alert ([]. slice. call (arguments); // [object event], 3,5 alert (E. type) // data});. fire ("data", 3, 5)});