6 description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events, if necessary.
8 license: MIT-style license.
10 requires: [Element, Event]
12 provides: Element.Event
19 Element.Properties.events = {set: function(events){
20 this.addEvents(events);
23 [Element, Window, Document].invoke('implement', {
25 addEvent: function(type, fn){
26 var events = this.retrieve('events', {});
27 if (!events[type]) events[type] = {keys: [], values: []};
28 if (events[type].keys.contains(fn)) return this;
29 events[type].keys.push(fn);
31 custom = Element.Events[type],
35 if (custom.onAdd) custom.onAdd.call(this, fn, type);
36 if (custom.condition){
37 condition = function(event){
38 if (custom.condition.call(this, event, type)) return fn.call(this, event);
42 if (custom.base) realType = Function.from(custom.base).call(this, type);
44 var defn = function(){
47 var nativeEvent = Element.NativeEvents[realType];
49 if (nativeEvent == 2){
50 defn = function(event){
51 event = new DOMEvent(event, self.getWindow());
52 if (condition.call(self, event) === false) event.stop();
55 this.addListener(realType, defn, arguments[2]);
57 events[type].values.push(defn);
61 removeEvent: function(type, fn){
62 var events = this.retrieve('events');
63 if (!events || !events[type]) return this;
64 var list = events[type];
65 var index = list.keys.indexOf(fn);
66 if (index == -1) return this;
67 var value = list.values[index];
68 delete list.keys[index];
69 delete list.values[index];
70 var custom = Element.Events[type];
72 if (custom.onRemove) custom.onRemove.call(this, fn, type);
73 if (custom.base) type = Function.from(custom.base).call(this, type);
75 return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this;
78 addEvents: function(events){
79 for (var event in events) this.addEvent(event, events[event]);
83 removeEvents: function(events){
85 if (typeOf(events) == 'object'){
86 for (type in events) this.removeEvent(type, events[type]);
89 var attached = this.retrieve('events');
90 if (!attached) return this;
92 for (type in attached) this.removeEvents(type);
93 this.eliminate('events');
94 } else if (attached[events]){
95 attached[events].keys.each(function(fn){
96 this.removeEvent(events, fn);
98 delete attached[events];
103 fireEvent: function(type, args, delay){
104 var events = this.retrieve('events');
105 if (!events || !events[type]) return this;
106 args = Array.convert(args);
108 events[type].keys.each(function(fn){
109 if (delay) fn.delay(delay, this, args);
110 else fn.apply(this, args);
115 cloneEvents: function(from, type){
116 from = document.id(from);
117 var events = from.retrieve('events');
118 if (!events) return this;
120 for (var eventType in events) this.cloneEvents(from, eventType);
121 } else if (events[type]){
122 events[type].keys.each(function(fn){
123 this.addEvent(type, fn);
131 Element.NativeEvents = {
132 click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
133 wheel: 2, mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
134 mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
135 keydown: 2, keypress: 2, keyup: 2, //keyboard
136 orientationchange: 2, // mobile
137 touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
138 gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
139 focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements
140 load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
141 hashchange: 1, popstate: 2, pageshow: 2, pagehide: 2, // history
142 error: 1, abort: 1, scroll: 1, message: 2 //misc
147 base: 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll'
151 var check = function(event){
152 var related = event.relatedTarget;
153 if (related == null) return true;
154 if (!related) return false;
155 return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
158 if ('onmouseenter' in document.documentElement){
159 Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2;
160 Element.MouseenterCheck = check;
162 Element.Events.mouseenter = {
167 Element.Events.mouseleave = {
174 if (!window.addEventListener){
175 Element.NativeEvents.propertychange = 2;
176 Element.Events.change = {
178 var type = this.type;
179 return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change';
181 condition: function(event){
182 return event.type != 'propertychange' || event.event.propertyName == 'checked';
190 Element.Events = new Hash(Element.Events);