11 var Local = Local || {};
13 var fire = 'fireEvent', create = function(){
14 return new Element('div');
17 describe('Events API: Element', function(){
19 beforeEach(function(){
21 Local.fn = function(){
22 return Local.called++;
26 it('should add an Event to the Class', function(){
27 var object = create();
29 object.addEvent('event', Local.fn)[fire]('event');
31 expect(Local.called).toEqual(1);
34 it('should add multiple Events to the Class', function(){
38 })[fire]('event1')[fire]('event2');
40 expect(Local.called).toEqual(2);
43 it('should remove a specific method for an event', function(){
44 var object = create();
45 var x = 0, fn = function(){ x++; };
47 object.addEvent('event', Local.fn).addEvent('event', fn).removeEvent('event', Local.fn)[fire]('event');
50 expect(Local.called).toEqual(0);
53 it('should remove an event and its methods', function(){
54 var object = create();
55 var x = 0, fn = function(){ x++; };
57 object.addEvent('event', Local.fn).addEvent('event', fn).removeEvents('event')[fire]('event');
60 expect(Local.called).toEqual(0);
63 it('should remove all events', function(){
64 var object = create();
65 var x = 0, fn = function(){ x++; };
67 object.addEvent('event1', Local.fn).addEvent('event2', fn).removeEvents();
68 object[fire]('event1')[fire]('event2');
71 object.removeEvents()[fire]('event1')[fire]('event2');
74 expect(Local.called).toEqual(0);
77 it('should remove events with an object', function(){
78 var object = create();
84 object.addEvent('event1', function(){ Local.fn(); }).addEvents(events)[fire]('event1');
85 expect(Local.called).toEqual(2);
87 object.removeEvents(events);
88 object[fire]('event1');
89 expect(Local.called).toEqual(3);
91 object[fire]('event2');
92 expect(Local.called).toEqual(3);
95 it('should remove an event immediately', function(){
96 var object = create();
100 var three = function(){
104 object.addEvent('event', function(){
106 this.removeEvent('event', three);
107 }).addEvent('event', function(){
109 }).addEvent('event', three);
111 object[fire]('event');
112 expect(methods).toEqual([1, 2]);
114 object[fire]('event');
115 expect(methods).toEqual([1, 2, 1, 2]);
118 it('should be able to remove itself', function(){
119 var object = create();
123 var one = function(){
124 object.removeEvent('event', one);
127 var two = function(){
128 object.removeEvent('event', two);
131 var three = function(){
135 object.addEvent('event', one).addEvent('event', two).addEvent('event', three);
137 object[fire]('event');
138 expect(methods).toEqual([1, 2, 3]);
140 object[fire]('event');
141 expect(methods).toEqual([1, 2, 3, 3]);
146 var fragment = document.createDocumentFragment();
148 // Restore native fireEvent in IE for Syn
149 var createElement = function(tag, props){
150 var el = new Element(tag);
151 if (el._fireEvent) el.fireEvent = el._fireEvent;
152 return el.set(props);
155 describe('Element.Event', function(){
157 it('Should trigger the click event', function(){
159 var callback = jasmine.createSpy('Element.Event click');
161 var el = createElement('a', {
171 }).inject(document.body);
173 Syn.trigger('click', null, el);
175 expect(callback).toHaveBeenCalled();
179 it('Should trigger the click event and prevent the default behavior', function(){
181 var callback = jasmine.createSpy('Element.Event click with prevent');
183 var el = createElement('a', {
191 click: function(event){
192 event.preventDefault();
196 }).inject(document.body);
198 Syn.trigger('click', null, el);
200 expect(callback).toHaveBeenCalled();
205 if (window.postMessage && !navigator.userAgent.match(/phantomjs/i)) it('Should trigger message event', function(){
207 var theMessage, spy = jasmine.createSpy('message');
208 window.addEvent('message', function(e){
209 theMessage = e.event.data;
212 window.postMessage('I am a message from outer space...', '*');
215 expect(spy).toHaveBeenCalled();
216 expect(theMessage).toEqual('I am a message from outer space...');
220 it('Should watch for a key-down event', function(){
222 var callback = jasmine.createSpy('keydown');
224 var div = createElement('div').addEvent('keydown', function(event){
226 }).inject(document.body);
230 expect(callback).toHaveBeenCalledWith('a');
234 it('should clone events of an element', function(){
238 var element = new Element('div').addEvent('click', function(){ calls++; });
239 element.fireEvent('click');
241 expect(calls).toBe(1);
243 var clone = new Element('div').cloneEvents(element, 'click');
244 clone.fireEvent('click');
246 expect(calls).toBe(2);
248 element.addEvent('custom', function(){ calls += 2; }).fireEvent('custom');
250 expect(calls).toBe(4);
252 clone.cloneEvents(element);
253 clone.fireEvent('click');
255 expect(calls).toBe(5);
257 clone.fireEvent('custom');
259 expect(calls).toBe(7);
264 describe('Element.Event', function(){
265 // This is private API. Do not use.
267 it('should pass the name of the custom event to the callbacks', function(){
269 var callback = jasmine.createSpy('Element.Event custom');
271 var fn = function(anything, type){
272 expect(type).toEqual('customEvent');
275 Element.Events.customEvent = {
279 condition: function(event, type){
289 var div = createElement('div').addEvent('customEvent', callback).inject(document.body);
291 Syn.trigger('click', null, div);
293 expect(callback).toHaveBeenCalled();
294 div.removeEvent('customEvent', callback).destroy();
295 expect(callbacks).toEqual(3);
300 describe('Element.Event.change', function(){
302 it('should not fire "change" for any property', function(){
303 var callback = jasmine.createSpy('Element.Event.change');
305 var radio = new Element('input', {
307 'class': 'someClass',
309 }).addEvent('change', callback).inject(document.body);
311 radio.removeClass('someClass');
312 expect(callback).not.toHaveBeenCalled();
314 var checkbox = new Element('input', {
316 'class': 'someClass',
318 }).addEvent('change', callback).inject(document.body);
320 checkbox.removeClass('someClass');
321 expect(callback).not.toHaveBeenCalled();
323 var text = new Element('input', {
325 'class': 'otherClass',
326 'value': 'text value'
327 }).addEvent('change', callback).inject(document.body);
329 text.removeClass('otherClass');
330 expect(callback).not.toHaveBeenCalled();
332 [radio, checkbox, text].invoke('destroy');
337 describe('Element.Event keyup with f<key>', function(){
339 it('should pass event.key == f2 when pressing f2 on keyup and keydown', function(){
341 var keydown = jasmine.createSpy('keydown');
342 var keyup = jasmine.createSpy('keyup');
344 var div = createElement('div')
345 .addEvent('keydown', function(event){
348 .addEvent('keyup', function(event){
351 .inject(document.body);
353 Syn.trigger('keydown', 'f2', div);
354 Syn.trigger('keyup', 'f2', div);
356 expect(keydown).toHaveBeenCalledWith('f2');
357 expect(keyup).toHaveBeenCalledWith('f2');
365 describe('Keypress key code', function(){
368 // return early for IE8- because Syn.js does not fire events
369 if (!document.addEventListener) return;
372 var input, key, shift, done;
374 function keyHandler(e){
376 shift = !!e.event.shiftKey;
379 function typeWriter(action){
380 setTimeout(function () {
381 Syn.type(action, 'keyTester');
383 if (done) return true;
386 beforeEach(function(){
387 input = new Element('input', {
390 }).addEvent('keypress', keyHandler).inject(document.body);
393 afterEach(function(){
394 input.removeEvent('keypress', keyHandler).destroy();
395 input = key = shift = done = null;
398 it('should return "enter" in event.key', function(){
399 typeWriter('[enter]');
402 expect(key).toBe('enter');
403 expect(shift).not.toBeTruthy();
407 it('should return "1" in event.key', function(){
411 expect(key).toBe('1');
412 expect(shift).not.toBeTruthy();
416 it('should return false when pressing SHIFT + 1', function(){
417 typeWriter('[shift]![shift-up]');
420 expect(key).toBe(false);
421 expect(shift).toBeTruthy();
427 describe('Element.removeEvent', function(){
429 it('should remove the onunload method', function(){
431 var handler = function(){ text = 'nope'; };
432 window.addEvent('unload', handler);
433 window.removeEvent('unload', handler);
434 window.fireEvent('unload');
435 expect(text).toBe(undefined);
441 describe('Mouse wheel', function(){
443 function attachProperties(e, direction){
444 e.detail = 1 * direction;
445 e.wheelDelta = 1 * direction;
446 e.deltaY = -1 * direction;
449 function dispatchFakeWheel(type, wheelDirection){
454 event = document.createEvent("MouseEvents");
455 event.initMouseEvent(type, true, true, window, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, null);
456 attachProperties(event, wheelDirection);
457 window.dispatchEvent(event);
461 // Chrome, PhantomJS, Safari
462 event = document.createEvent("WheelEvent");
463 event.initMouseEvent(type, 0, 100, window, 0, 0, 0, 0, null, null, null, null);
464 attachProperties(event, wheelDirection);
465 window.dispatchEvent(event);
470 event = document.createEvent("HTMLEvents");
471 event.initEvent(type, true, false);
472 attachProperties(event, wheelDirection);
473 window.dispatchEvent(event);
478 var event = document.createEvent("MouseEvents");
479 event.initEvent(type, true, true);
480 attachProperties(event, wheelDirection);
481 window.dispatchEvent(event);
486 var event = document.createEventObject();
487 document.documentElement.fireEvent(type, event);
491 var triggered = false;
493 var testWheel = !!window.addEventListener;
494 var callback = function(e){
495 if (e.wheel) wheel = e.wheel > 0 ? 'wheel moved up' : 'wheel moved down';
496 triggered = 'triggered';
499 beforeEach(function(){
500 wheel = triggered = false;
501 window.addEvent('mousewheel', callback);
502 document.documentElement.addEvent('mousewheel', callback);
505 afterEach(function(){
506 window.removeEvent('mousewheel', callback);
507 document.documentElement.removeEvent('mousewheel', callback);
510 it('should trigger/listen to mousewheel event', function(){
511 // http://jsfiddle.net/W6QrS/3
513 ['mousewheel', 'wheel' ,'DOMMouseScroll' ].each(dispatchFakeWheel);
514 expect(triggered).toBeTruthy();
517 it('should listen to mouse wheel direction', function(){
518 // http://jsfiddle.net/58yCr/
520 if (!testWheel) return;
522 // fire event with wheel going up
523 ['mousewheel', 'wheel' ,'DOMMouseScroll' ].each(function(type){
524 dispatchFakeWheel(type, 120);
526 expect(wheel).toEqual('wheel moved up');
529 // fire event with wheel going down
530 ['mousewheel', 'wheel' ,'DOMMouseScroll' ].each(function(type){
531 dispatchFakeWheel(type, -120);
533 expect(wheel).toEqual('wheel moved down');