-
Notifications
You must be signed in to change notification settings - Fork 640
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Event.fire to support all events, not only custom ones #266
Comments
Juriy Zaytsev I've been using Event.simulate (http://github.com/kangax/protolicious/blob/889a60d6d22cd59e93664ae04866e245c89b35aa/event.simulate.js) for some time now and it's been working fine so far. I know few other people are using it in their applications as well. |
Juriy Zaytsev A couple of comments about Event.fire: isKeyEvent = Enumerable.include.bind($w('keydown keyup keypress')); This looks cool, but should probably be replaced with regex :) It's much faster that way. if (options.relatedTarget && !event.relatedTarget){ if (evenName == 'mouseout'){ event.toElement = options.relatedTarget; evenName looks like a typo, doesn't it? What is the purpose of this assignment? Shouldn't there be a check for existence of toElement before trying to assign to it? Is there a guarantee that toElement can be assigned to (it's a host object we are talking about, after all)? I would rather avoid event augmentation. } catch(e) {
try {
// if initKeyEvent() is not , to create generic event - // will fail in Safari 2.x
return createEvent('Events', eventName, bubble, options);
} catch(e){ Why so many try/catch? try/catch are slow and should be avoided when possible. Instead, why not detect any deficiencies at load time and use boolean checks? var IS_KEY_EVENTS_CREATION_SUPPORTED = (function(){
if (!document.createEvent) return false;
try {
var e = document.createEvent('KeyEvents');
return (typeof e != 'undefined');
} catch(e) {
return false;
}
})(); This snippet gives me true in FF 3.0.10 and false in nightly WebKit. |
Radoslav Stankov 10x for the helpful comments, if (document.createEvent){
function createMouseEvent(){}
function createKeyEvent(){}
// ...
} else if (document.createEventObject){
function createMouseEvent(){}
function createKeyEvent(){}
// ...
} I'm not very experienced with cross-browsers behaviors so, please excuse if some parts of this are not perfect. |
Samuel Lebeau @radoslav : due to how JS scoping works, the construct you just used in your comment wouldn't work as expected, and you'd end up with last version of functions whatever host methods available. |
Radoslav Stankov @samuel Lebeau :10x, I know that, but every time forget about it. I generally overcome this with just variable functions :) |
Radoslav Stankov I think I'm near to the final version
|
Juriy Zaytsev Radoslav, don't forget to test Safari 2.x and Opera 8.54+ |
Radoslav Stankov Juriy, I always forgot those. When I expand the test suite I'll definitely test in them too |
Radoslav Stankov I think I'm ready, finally :)
|
Radoslav Stankov Strange but the patch I have attached wasn't accessible. From 07c93e9d392c8198f6411ac218c4618fa2174267 Mon Sep 17 00:00:00 2001
From: RStankov <rstankov@gmail.com>
Date: Sun, 19 Jul 2009 23:26:21 +0300
Subject: [PATCH] Event.fire can now fire dom events too and all event functional tests are added as unit tests via Event.fire
---
src/dom/event.js | 213 ++++++++++++++++---
test/unit/event_test.js | 472 ++++++++++++++++++++++++++++++++++++++++-
test/unit/fixtures/event.html | 38 ++++
3 files changed, 692 insertions(+), 31 deletions(-)
diff --git a/src/dom/event.js b/src/dom/event.js
index bbdb4d1..e68e490 100644
--- a/src/dom/event.js
+++ b/src/dom/event.js
@@ -67,7 +67,8 @@
_isButton = function(event, code) {
switch (code) {
case 0: return event.which == 1 && !event.metaKey;
- case 1: return event.which == 1 && event.metaKey;
+ case 1: return event.which == 2 && !event.metaKey;
+ case 2: return event.which == 3 && !event.metaKey;
default: return false;
}
};
@@ -247,10 +248,14 @@
if (Prototype.Browser.IE) {
function _relatedTarget(event) {
var element;
- switch (event.type) {
- case 'mouseover': element = event.fromElement; break;
- case 'mouseout': element = event.toElement; break;
- default: return null;
+ if (event.relatedTarget){
+ element = event.relatedTarget;
+ } else {
+ switch (event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
}
return Element.extend(element);
}
@@ -494,44 +499,192 @@
}
/**
- * Event.fire(element, eventName[, memo[, bubble = true]]) -> Event
+ * Event.fire(element, customEventName[, memo]) -> Event
* - memo (?): Metadata for the event. Will be accessible through the
* event's `memo` property.
- * - bubble (Boolean): Whether the event will bubble.
- *
- * Fires a custom event of name `eventName` with `element` as its target.
+ * Event.fire(element, eventName[, options]) -> Event
+ * - options (?): Object with options for the event.
+ * For all events options - bubbles, cancelable, view, ctrlKey, altKey, shiftKey, metaKey.
+ * For mouse event options could be also - detail, screenX, screenY, clientX, clientY, button, relatedTarget
+ * For key events - keyCode, charCode
+ *
+ * Fires a event of name `eventName` with `element` as its target.
*
* Custom events must include a colon (`:`) in their names.
**/
- function fire(element, eventName, memo, bubble) {
- element = $(element);
+ var fire = (function(){
+ var mouseEvent = /^(click|dblclick|mouseover|mouseout|mousedown|mouseup|mousemove|mouseenter|mouseleave|contextmenu)$/,
+ keyEvent = /^(keydown|keyup|keypress)$/;
+
+ var defaultOptions = {
+ event: {
+ bubbles: true,
+ cancelable: true,
+ view: document.defaultView,
+ ctrlKey: false,
+ altKey: false,
+ shiftKey: false,
+ metaKey: false
+ },
+ mouse: {
+ detail: 1,
+ screenX: 0,
+ screenY: 0,
+ clientX: 0,
+ clientY: 0,
+ button: 0,
+ relatedTarget: null
+ },
+ key: {
+ keyCode: 0,
+ charCode: 0
+ }
+ };
- if (Object.isUndefined(bubble))
- bubble = true;
+ var createEvent, dispatchEvent;
+ if (document.createEvent){
+ createEvent = (function(){
+ var createEvent = function(name, eventName, options){
+ var event = document.createEvent(name);
- if (element == document && document.createEvent && !element.dispatchEvent)
- element = document.documentElement;
+ event.initEvent(eventName, options.bubbles, options.cancelable);
- var event;
- if (document.createEvent) {
- event = document.createEvent('HTMLEvents');
- event.initEvent('dataavailable', true, true);
- } else {
- event = document.createEventObject();
- event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
+ delete(options.bubbles);
+ delete(options.cancelable);
+
+ return Object.extend(event, options);
+ };
+
+ var createKeyEvent = (function(){
+ try { // only Firefox supports KeyEvents
+ if (typeof document.createEvent('KeyEvents') != 'undefined')
+ return function(eventName, options){
+ var event = document.createEvent('KeyEvents');
+ event.initKeyEvent(eventName, options.bubbles, options.cancelable, options.view,
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
+ options.keyCode, options.charCode);
+ return event;
+ };
+ } catch(e){}
+
+ try { // try to use generic event (will fail in Safari 2.x)
+ if (typeof document.createEvent('Events') != 'undefined')
+ return createEvent.curry('Events');
+ } catch(e){}
+
+ // generic event fails, use UIEvent for Safari 2.x
+ return createEvent.curry('UIEvents');
+ }());
+
+ return function(eventName, options){
+ if (eventName.include(':')){
+ return createEvent('HTMLEvents', 'dataavailable', options);
+ }
+
+ if (mouseEvent.test(eventName)){
+ options = Object.extend(Object.clone(defaultOptions.mouse), options);
+ var event = document.createEvent('MouseEvents');
+
+ if (event.initMouseEvent){
+ event.initMouseEvent(eventName, options.bubbles, options.cancelable, options.view,
+ options.detail, options.screenX, options.screenY, options.clientX, options.clientY,
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
+ options.button, options.relatedTarget);
+
+ return event;
+ }
+
+ // Safari 2.x doesn't implement initMouseEvent(), the closest thing available is UIEvents
+ return createEvent('UIEvents', eventName, options);
+ }
+
+ if (keyEvent.test(eventName)){
+ return createKeyEvent(eventName, Object.extend(Object.clone(defaultOptions.key), options));
+ }
+
+ return createEvent('HTMLEvents', eventName, options);
+ };
+ })();
+
+ dispatchEvent = function(element, event){
+ if (element == document && !element.dispatchEvent) element = document.documentElement;
+
+ element.dispatchEvent(event);
+ };
+ } else /* if (document.createEventObject()) */ {
+ createEvent = function(eventName, options){
+ if (eventName.include(':')){
+ eventName = options.bubbles ? 'dataavailable' : 'filterchange';
+ } else if (mouseEvent.test(eventName)){
+ options = Object.extend(Object.clone(defaultOptions.mouse), options);
+
+ // fix options, IE button property
+ switch(options.button){
+ case 0: options.button = 1; break;
+ case 1: options.button = 4; break;
+ case 2: /* no change */ break;
+ default: options.button = 0;
+ }
+ } else if (keyEvent.test(eventName)){
+ options = Object.extend(Object.clone(defaultOptions.key), options);
+
+ if (options.charCode > 0)
+ options.keyCode = options.charCode;
+
+ delete(options.charCode);
+ }
+
+ options.eventType = 'on' + eventName;
+
+ return Object.extend(document.createEventObject(), options);
+ };
+
+ dispatchEvent = function(element, event){
+ // for some reason event.cancelBubble doesn't work
+ // and document.fireEvent doesn't support several events
+ // in both cases we could just take all events form 'prototype_event_registry'
+ if (!event.bubbles || (element == document && event.eventType in element)){
+ if (Object.isFunction(element[event.eventType])) element[event.eventType]();
+ var registry = Element.retrieve(element, 'prototype_event_registry');
+ if (registry){
+ var handlers = registry.get(event.eventName);
+ if (handlers){
+ handlers.each(function(responder){
+ responder(event);
+ });
+ }
+ }
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+ };
}
- event.eventName = eventName;
- event.memo = memo || { };
+ return function(element, eventName, options){
+ var memo;
- if (document.createEvent)
- element.dispatchEvent(event);
- else
- element.fireEvent(event.eventType, event);
+ // custom events take (element, eventName[, memo[, bubbles]]) arguments
+ if (eventName.include(':')){
+ memo = options;
+ options = {bubbles: Object.isUndefined(arguments[3]) ? true : arguments[3] };
+ } else {
+ eventName = _getDOMEventName(eventName);
+ options = Object.extend(Object.clone(defaultOptions.event), options);
+ memo = options.memo;
- return Event.extend(event);
- }
+ delete(options.memo);
+ }
+
+ var event = createEvent(eventName, options);
+ event.eventName = eventName;
+ event.memo = memo;
+
+ dispatchEvent($(element), event);
+
+ return Event.extend(event);
+ };
+ })();
Object.extend(Event, Event.Methods);
diff --git a/test/unit/event_test.js b/test/unit/event_test.js
index fc6df25..967c54f 100644
--- a/test/unit/event_test.js
+++ b/test/unit/event_test.js
@@ -1,7 +1,35 @@
var documentLoaded = document.loaded;
+// helpers for functional simulation test
+Element.addMethods({
+ passed: function(el, message) {
+ el = $(el);
+ el.className = 'passed';
+ (el.down('span') || el).update(message || 'Test passed!');
+ },
+
+ failed: function(el, message) {
+ el = $(el);
+ el.className = 'failed';
+ (el.down('span') || el).update(message || 'Test failed');
+ },
+
+ clear: function(el, message) {
+ el = $(el);
+ el.className = '';
+ (el.down('span') || el).update(message || '');
+ },
+
+ isPassed: function(el){
+ return $(el).className == 'passed';
+ }
+});
+
new Test.Unit.Runner({
-
+/*
+ * Prototype Unit tests
+ */
+
// test firing an event and observing it on the element it's fired from
testCustomEventFiring: function() {
var span = $("span"), fired = false, observer = function(event) {
@@ -235,6 +263,448 @@ new Test.Unit.Runner({
$('container').down().observe("test:somethingHappened", Prototype.emptyFunction);
$('container').innerHTML += $('container').innerHTML;
this.assertUndefined($('container').down(1)._prototypeEventID);
+ },
+
+/*
+ * Prototype current Functional tests
+ */
+
+ testBasicClickCallback: function(){
+ var runned = 0;
+ $('basic').observe('click', function(e){
+ $('basic').passed();
+
+ runned++;
+
+ if ($('basic_remove')){
+ $('basic_remove').show();
+ } else {
+ this.fail();
+ $('basic').failed();
+ }
+ }.bind(this));
+
+ $('basic_remove').observe('click', function(e){
+ el = $('basic');
+ el.passed('This test should now be inactive (try clicking)');
+ el.stopObserving('click');
+
+ $('basic_remove').remove();
+ }).hide();
+
+ $('basic').fire('click');
+
+ this.assertEqual(runned, 1);
+ this.assert($('basic_remove').visible());
+
+ $('basic_remove').fire('click');
+
+ $('basic').fire('click');
+
+ this.assertEqual(runned, 1);
+ this.assertNull($('basic_remove'));
+ },
+
+ testInlineEvents: function(){
+ // #inline_test onclick="Event.stop(event); $(this).passed();"
+ this.assert(!$('inline_test').isPassed());
+
+ $('inline_test').fire('click');
+
+ this.assert($('inline_test').isPassed());
+ },
+
+ testScopeOfTheHandler: function(){
+ var runned = false;
+
+ $('basic2').observe('click', function(e) {
+ runned = true;
+
+ if(this === window){
+ $('basic2').failed('Window scope! (needs scope correction)');
+ } else {
+ this.passed();
+ }
+ });
+
+ this.assert(!$('basic2').isPassed());
+
+ $('basic2').fire('click');
+
+ this.assert(runned);
+ this.assert($('basic2').isPassed());
+ },
+
+ testEventObjectAsFirstArgument: function(){
+ $('basic3').observe('click', function(evt) {
+ el = $('basic3');
+ if (typeof evt != 'object') this.failed('Expected event object for first argument');
+ else this.passed('Good first argument');
+ });
+
+ $('basic3').fire('click');
+
+ this.assert($('basic3').isPassed());
+ },
+
+ testLeftMouseClick: function(){
+ $w('left middle right').each(function(button){
+ Event.observe(button, 'mousedown', function(e){
+ if (Event['is' + button.capitalize() + 'Click'](e)){
+ this.passed('Squeak!')
+ } else {
+ this.failed('OH NO!');
+ }
+ });
+ });
+ var BUTTONS = {
+ left: 0,
+ middle: 1,
+ right: 2
+ };
+
+ $w('left middle right').each(function(id){
+ var element = $(id);
+
+ for(var button in BUTTONS){
+ element.clear();
+ element.fire('mousedown', { button: BUTTONS[button] });
+ this.assertEqual(id == button, element.isPassed(), id + " on " + button);
+ }
+ }.bind(this));
+
+ $('left').fire('mousedown');
+ this.assert($('left').isPassed());
+
+ $('middle').fire('mousedown', { button: BUTTONS.middle });
+ this.assert($('middle').isPassed());
+
+ $('right').fire('mousedown', { button: BUTTONS.right });
+ this.assert($('right').isPassed());
+ },
+
+ testContextMenuEvent: function(){
+ $('context').observe('contextmenu', function(e){
+ this.passed();
+ Event.stop(e);
+ });
+
+ $('context').fire('contextmenu');
+ this.assert($('context').isPassed());
+ },
+
+ testEventElementMethod: function(){
+ $('target').observe('click', function(e) {
+ if (e.element() == this && e.target == this) this.passed();
+ else this.failed();
+ });
+
+ $('target').fire('click');
+ this.assert($('target').isPassed());
+ },
+
+ testCurrentTarget: function(){
+ $('currentTarget').observe('click', function(e){
+ this[ e.element() == this ? 'passed' : 'failed']();
+ });
+
+ Element.Methods.clear('currentTarget');
+
+ $('currentTarget').fire('click');
+ this.assert($('currentTarget').isPassed());
+ },
+
+ testEventFindElementAfterClickEvent: function(){
+ $('findElement').observe('click', function(e){
+ if(e.findElement('p') == this && e.findElement('body') == document.body &&
+ e.findElement('foo') == null) this.passed();
+ else this.failed();
+ });
+
+ $('findElement').fire('click');
+ this.assert($('findElement').isPassed());
+ },
+
+ testObjectInspect: function(){
+ $('obj_inspect').observe('click', function(e){
+ el = $('obj_inspect')
+ try { el.passed(Object.inspect(e)) }
+ catch (err) { el.failed('Failed! Error thrown') }
+ });
+
+ $('obj_inspect').fire('click');
+ this.assert($('obj_inspect').isPassed());
+ },
+
+ testBindAsEventListener: function(){
+ $('bind').observe('click', function(e, str, arr){
+ el = $('bind')
+ try {
+ if (arguments.length != 3) throw arguments.length + ' arguments: ' + $A(arguments).inspect()
+ if (str != 'foo') throw 'wrong string: ' + str
+ if (arr.constructor != Array) throw '3rd parameter is not an array'
+ el.passed();
+ }
+ catch (err) { el.failed(err.toString()) }
+ }.bindAsEventListener(document.body, 'foo', [1,2,3]));
+
+ $('bind').fire('click');
+ this.assert($('bind').isPassed());
+ },
+
+ testStopPropagation: function(){
+ $('stop').observe('click', function(e){
+ e.stop();
+ this.passed();
+ });
+ $('container').observe('click', function(e){
+ $('stop').failed();
+ });
+
+
+ this.assert(!$('stop').isPassed());
+
+ $('stop').fire('click');
+
+ this.assert($('stop').isPassed());
+ },
+
+ testPreventDefault: function(){
+ $('checkbox').checked = false;
+ $('checkbox').observe('click', function(e){
+ $('prevent_default').passed();
+ e.preventDefault();
+ });
+
+ $('checkbox').fire('click');
+
+ this.assert(!$('checkbox').checked);
+ this.assert($('prevent_default').isPassed());
+ },
+
+ testNotStopingPropagation: function(){
+ $('container2').observe('click', function(e){
+ $('don_not_stop').passed();
+ });
+
+ this.assert(!$('don_not_stop').isPassed());
+
+ $('don_not_stop').fire('click');
+
+ this.assert($('don_not_stop').isPassed());
+ },
+
+ testKeyUp: function(){
+ $('keyup').observe('keyup', function(e){
+ this.assertEqual(65, e.keyCode);
+ this.assert(!e.charCode);
+
+ el = $('keyup_log');
+ el.passed('Key captured: the length is ' + $('keyup').value.length);
+ }.bind(this));
+
+ $('keyup').fire('keyup', {keyCode: 65, charCode: 0}); // 'a' char
+ this.assert($('keyup_log').isPassed());
+ },
+
+ testMouseEnterMouseLeave: function(){
+ var element = $('mouseenter'),
+ child = element.down(),
+ parent = element.up();
+
+ element.observe('mouseenter', function(event) {
+ if ($(event.relatedTarget).descendantOf(element)){
+ this.fail();
+ element.failed('<code id="mouseenter_child">mouseenter</code> failed');
+ } else {
+ element.passed('<code id="mouseenter_child">mouseenter</code> passed');
+ }
+ }.bind(this));
+
+ element.observe('mouseleave', function(event) {
+ if ($(event.relatedTarget).descendantOf($('mouseenter'))){
+ this.fail();
+ element.failed('<code id="mouseenter_child">mouseleave</code> failed');
+ } else {
+ element.passed('<code id="mouseenter_child">mouseleave</code> passed');
+ }
+ }.bind(this));
+
+ // for browser who do not support natively mouseenter/mouseleave make extra checks
+ if (!('onmouseenter' in document.documentElement && 'onmouseleave' in document.documentElement)){
+ element.fire('mouseover', { relatedTarget: child });
+ element.fire('mouseout', { relatedTarget: child });
+
+ this.assert(! element.className );
+
+ element.fire('mouseout', { relatedTarget: parent });
+ this.assert(element.isPassed());
+ }
+
+ Element.Methods.clear(element, '<code id="mouseenter_child">mouseenter/mouseleave</code> test');
+
+ element.fire('mouseenter', { relatedTarget: parent });
+
+ this.assert(element.isPassed());
+
+ Element.Methods.clear(element, '<code id="mouseenter_child">mouseenter/mouseleave</code> test');
+
+ element.fire('mouseleave', { relatedTarget: parent });
+
+ this.assert(element.isPassed());
+ },
+
+ testUnloadEvent: function(){
+ var runned = 0;
+
+ document.onunload = function(){ ++runned; }
+ Event.observe(document, 'unload', function(event){
+ if (!event.target) {
+ this.fail('event.target should not be null!');
+ }
+ ++runned;
+ }.bind(this));
+
+ Event.fire(document, 'unload');
+
+ this.assertEqual(2, runned);
+ },
+
+/*
+ * Prototype Event.fire tests
+ */
+
+ testFiringClickEvent: function(){
+ var doc = 0, body = 0, main = 0, main = 0, inner = 0;
+
+ document.observe('click', function(e){ if (e.element() == document) ++doc; });
+ $$('body').first().observe('click', function(e){ ++body; });
+ $('test-bubble').observe('click', function(e){ ++main; });
+ $('test-bubble-inner').observe('click', function(e){ ++inner; });
+
+ Event.fire(document, 'click');
+ this.assertEqual(1, doc);
+
+ Event.fire($$('body').first(), 'click');
+ this.assertEqual(1, doc);
+ this.assertEqual(1, body);
+
+ Event.fire('test-bubble', 'click');
+ this.assertEqual(1, doc);
+ this.assertEqual(2, body);
+ this.assertEqual(1, main);
+
+ Event.fire('test-bubble-inner', 'click');
+ this.assertEqual(1, doc);
+ this.assertEqual(3, body);
+ this.assertEqual(2, main);
+ this.assertEqual(1, inner);
+
+ // just in case re-test
+ Event.fire('test-bubble-inner', 'click');
+ this.assertEqual(1, doc);
+ this.assertEqual(4, body);
+ this.assertEqual(3, main);
+ this.assertEqual(2, inner);
+
+ Event.fire('test-bubble-inner', 'click', {bubbles: false});
+ this.assertEqual(1, doc);
+ this.assertEqual(4, body);
+ this.assertEqual(3, main);
+ this.assertEqual(3, inner);
+
+ document.stopObserving('click');
+ document.body.stopObserving('click');
+ $('test-bubble').stopObserving('click');
+ $('test-bubble-inner').stopObserving('click');
+ },
+
+ testStropingFiredEvent: function(){
+ var main = 0, inner = 0;
+
+ $('test-event-stop').observe('click', function(){ ++main; });
+ $('test-event-stop-inner').observe('click', function(e){ ++inner; e.stop(); });
+
+ Event.fire('test-event-stop-inner', 'click');
+ this.assertEqual(0, main);
+ this.assertEqual(1, inner);
+ },
+
+ testFiringKeyUpEvent: function(){
+ var doc = 0, body = 0, main = 0, main = 0, inner = 0;
+
+ document.observe('keyup', function(e){ if (e.element() == document) ++doc; });
+ $$('body').first().observe('keyup', function(e){ ++body; });
+ $('test-bubble2').observe('keyup', function(e){ ++main; });
+ $('test-bubble2-inner').observe('keyup', function(e){ ++inner; });
+
+ Event.fire(document, 'keyup');
+ this.assertEqual(1, doc);
+
+ Event.fire($$('body').first(), 'keyup');
+ this.assertEqual(1, doc);
+ this.assertEqual(1, body);
+
+ Event.fire('test-bubble2', 'keyup');
+ this.assertEqual(1, doc);
+ this.assertEqual(2, body);
+ this.assertEqual(1, main);
+
+ Event.fire('test-bubble2-inner', 'keyup');
+ this.assertEqual(1, doc);
+ this.assertEqual(3, body);
+ this.assertEqual(2, main);
+ this.assertEqual(1, inner);
+
+ // just in case re-test
+ Event.fire('test-bubble2-inner', 'keyup');
+ this.assertEqual(1, doc);
+ this.assertEqual(4, body);
+ this.assertEqual(3, main);
+ this.assertEqual(2, inner);
+
+ Event.fire('test-bubble2-inner', 'keyup', {bubbles: false});
+ this.assertEqual(1, doc);
+ this.assertEqual(4, body);
+ this.assertEqual(3, main);
+ this.assertEqual(3, inner);
+
+ document.stopObserving('keyup');
+ document.body.stopObserving('keyup');
+ $('test-bubble2').stopObserving('keyup');
+ $('test-bubble2-inner').stopObserving('keyup');
+ },
+ // focus event in IE's don't bubble (hope Prototype will fix this in next versions)
+ testFiringFocusInEvent: function(){
+ var doc = 0, body = 0, main = 0, main = 0, inner = 0;
+
+ document.observe('focusin', function(e){ if (e.element() == document) ++doc;});
+ $$('body').first().observe('focusin', function(e){ ++body; });
+ $('test-html-event').observe('focusin', function(e){ ++main; });
+ $('test-html-event-text').observe('focusin', function(e){ ++inner; });
+
+ Event.fire(document, 'focusin');
+ this.assertEqual(1, doc);
+
+ Event.fire($$('body').first(), 'focusin');
+ this.assertEqual(1, doc);
+ this.assertEqual(1, body);
+
+ Event.fire('test-html-event', 'focusin');
+ this.assertEqual(1, doc);
+ this.assertEqual(2, body);
+ this.assertEqual(1, main);
+
+ Event.fire('test-html-event-text', 'focusin');
+ this.assertEqual(1, doc);
+ this.assertEqual(3, body);
+ this.assertEqual(2, main);
+ this.assertEqual(1, inner);
+
+ document.stopObserving('focusin');
+ document.body.stopObserving('focusin');
+ $('test-html-event').stopObserving('focusin');
+ $('test-html-event-text').stopObserving('focusin');
}
});
diff --git a/test/unit/fixtures/event.html b/test/unit/fixtures/event.html
index baa88a7..3ecad09 100644
--- a/test/unit/fixtures/event.html
+++ b/test/unit/fixtures/event.html
@@ -2,3 +2,41 @@
<p id="inner">One two three <span id="span">four</span></p>
</div>
<div id="container"><div></div></div>
+<div id="test-bubble"><span id="test-bubble-inner"></span></div>
+<div id="test-event-stop"><span id="test-event-stop-inner"></span></div>
+<div id="test-bubble2"><span id="test-bubble2-inner"></span></div>
+<div id="test-html-event"><input type="text" id="test-html-event-text" value="" /></div>
+<p id="basic">A basic event test - <strong>click here</strong></p>
+<p id="basic_remove" class="subtest"><strong>click</strong> to stop observing the first test</p><p id="inline_test" onclick="Event.stop(event); $(this).passed();"><strong>click</strong> to ensure generic Event methods work on inline handlers</p>
+
+<p id="basic2"><strong>Scope</strong> test - scope of the handler should be this element</p>
+
+<p id="basic3"><strong>Event object</strong> test - should be present as a first argument</p>
+
+<p>Mouse click: <span class="button" id="left">left</span> <span class="button" id="middle">middle</span> <span class="button" id="right">right</span></p>
+
+<p id="context">Context menu event (tries to prevent default)</p>
+
+<p id="target">Event.element() test</p>
+
+<p id="currentTarget"><span>Event.currentTarget test</span></p>
+
+<p id="findElement"><span>Event.findElement() test</span></p>
+
+<p id="obj_inspect"><code>Object.inspect(event)</code> test</p>
+
+<p id="bind"><code>bindAsEventListener()</code> test</p>
+
+<div id="container"><p id="stop"><strong>Stop propagation</strong> test (bubbling)</p></div>
+
+<div id="container2"><p id="don_not_stop"><strong>Propagation</strong> test (bubbling)</p></div>
+
+<div>
+ <p id="keyup_log"><strong>Keyup</strong> test - focus on the textarea and type</p>
+ <textarea id="keyup" class="subtest"></textarea>
+</div>
+
+<div>
+ <p id="mouseenter"><code>mouseenter/mouseleave</code> test</p>
+</div>
+<p id="prevent_default"><span>Test - Event.preventDefault()</span><input type="checkbox" name="checkbox" id="checkbox"></p>
\ No newline at end of file
--
1.6.2.1 |
previous lighthouse ticket #697
by Radoslav Stankov
Today I have been trying to create tests for Event.delegate, and come to the conclusion that prototype needs Event.fire to fire not only custom events but custom too.
I digg a lot today for this issue, I created a Event.fire (looking mainly on old Event.fire and YUI's one)
http://github.com/RStankov/javascript-playground/tree/550554caf705a231a5aa545ab9b2014008dc6a8b/Event.fire
http://gist.github.com/121011
This version now pass all prototype.js tests in - event_test.js + basic tests I created. Tested in FF3 / Safary / IE. But I think there are not enough and I'm not very good at testing.
The text was updated successfully, but these errors were encountered: