diff options
Diffstat (limited to 'dom/events')
-rwxr-xr-x | dom/events/Event.cpp | 7 | ||||
-rw-r--r-- | dom/events/EventListenerManager.cpp | 42 | ||||
-rw-r--r-- | dom/events/EventNameList.h | 30 | ||||
-rw-r--r-- | dom/events/EventStateManager.cpp | 66 | ||||
-rw-r--r-- | dom/events/EventStateManager.h | 10 | ||||
-rw-r--r-- | dom/events/KeyNameList.h | 4 | ||||
-rw-r--r-- | dom/events/TouchEvent.cpp | 2 | ||||
-rw-r--r-- | dom/events/WheelHandlingHelper.cpp | 1 | ||||
-rw-r--r-- | dom/events/moz.build | 5 | ||||
-rw-r--r-- | dom/events/test/mochitest.ini | 1 | ||||
-rw-r--r-- | dom/events/test/test_bug1304044.html | 133 | ||||
-rw-r--r-- | dom/events/test/test_eventTimeStamp.html | 36 | ||||
-rw-r--r-- | dom/events/test/test_legacy_event.html | 21 |
13 files changed, 228 insertions, 130 deletions
diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp index 7e19cd74d..4b9776c0a 100755 --- a/dom/events/Event.cpp +++ b/dom/events/Event.cpp @@ -1146,16 +1146,11 @@ Event::TimeStampImpl() const return perf->GetDOMTiming()->TimeStampToDOMHighRes(mEvent->mTimeStamp); } - // For dedicated workers, we should make times relative to the navigation - // start of the document that created the worker, which is the same as the - // timebase for performance.now(). workers::WorkerPrivate* workerPrivate = workers::GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); - TimeDuration duration = - mEvent->mTimeStamp - workerPrivate->NowBaseTimeStamp(); - return duration.ToMilliseconds(); + return workerPrivate->TimeStampToDOMHighRes(mEvent->mTimeStamp); } bool diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index a8c48ede8..fe896870c 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -13,9 +13,6 @@ #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/EventDispatcher.h" #include "mozilla/EventListenerManager.h" -#ifdef MOZ_B2G -#include "mozilla/Hal.h" -#endif // #ifdef MOZ_B2G #include "mozilla/HalSensor.h" #include "mozilla/InternalMutationEvent.h" #include "mozilla/JSEventHandler.h" @@ -355,18 +352,10 @@ EventListenerManager::AddEventListenerInternal( EnableDevice(eDeviceLight); } else if (aTypeAtom == nsGkAtoms::ondevicemotion) { EnableDevice(eDeviceMotion); -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) } else if (aTypeAtom == nsGkAtoms::onorientationchange) { EnableDevice(eOrientationChange); #endif -#ifdef MOZ_B2G - } else if (aTypeAtom == nsGkAtoms::onmoztimechange) { - EnableDevice(eTimeChange); - } else if (aTypeAtom == nsGkAtoms::onmoznetworkupload) { - EnableDevice(eNetworkUpload); - } else if (aTypeAtom == nsGkAtoms::onmoznetworkdownload) { - EnableDevice(eNetworkDownload); -#endif // MOZ_B2G } else if (aTypeAtom == nsGkAtoms::ontouchstart || aTypeAtom == nsGkAtoms::ontouchend || aTypeAtom == nsGkAtoms::ontouchmove || @@ -492,14 +481,9 @@ EventListenerManager::IsDeviceType(EventMessage aEventMessage) case eDeviceLight: case eDeviceProximity: case eUserProximity: -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) case eOrientationChange: #endif -#ifdef MOZ_B2G - case eTimeChange: - case eNetworkUpload: - case eNetworkDownload: -#endif return true; default: break; @@ -545,20 +529,11 @@ EventListenerManager::EnableDevice(EventMessage aEventMessage) window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION); window->EnableDeviceSensor(SENSOR_GYROSCOPE); break; -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) case eOrientationChange: window->EnableOrientationChangeListener(); break; #endif -#ifdef MOZ_B2G - case eTimeChange: - window->EnableTimeChangeNotifications(); - break; - case eNetworkUpload: - case eNetworkDownload: - window->EnableNetworkEvent(aEventMessage); - break; -#endif default: NS_WARNING("Enabling an unknown device sensor."); break; @@ -600,20 +575,11 @@ EventListenerManager::DisableDevice(EventMessage aEventMessage) case eDeviceLight: window->DisableDeviceSensor(SENSOR_LIGHT); break; -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) case eOrientationChange: window->DisableOrientationChangeListener(); break; #endif -#ifdef MOZ_B2G - case eTimeChange: - window->DisableTimeChangeNotifications(); - break; - case eNetworkUpload: - case eNetworkDownload: - window->DisableNetworkEvent(aEventMessage); - break; -#endif // MOZ_B2G default: NS_WARNING("Disabling an unknown device sensor."); break; diff --git a/dom/events/EventNameList.h b/dom/events/EventNameList.h index ba2427623..214b844e7 100644 --- a/dom/events/EventNameList.h +++ b/dom/events/EventNameList.h @@ -164,6 +164,10 @@ EVENT(change, eFormChange, EventNameType_HTMLXUL, eBasicEventClass) +EVENT(auxclick, + eMouseAuxClick, + EventNameType_All, + eMouseEventClass) EVENT(click, eMouseClick, EventNameType_All, @@ -559,7 +563,7 @@ WINDOW_EVENT(online, eOnline, EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly, eBasicEventClass) -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) WINDOW_EVENT(orientationchange, eOrientationChange, EventNameType_HTMLBodyOrFramesetOnly, @@ -633,22 +637,6 @@ WINDOW_ONLY_EVENT(appinstalled, EventNameType_None, eBasicEventClass) - -#ifdef MOZ_B2G -WINDOW_ONLY_EVENT(moztimechange, - eTimeChange, - EventNameType_None, - eBasicEventClass) -WINDOW_ONLY_EVENT(moznetworkupload, - eNetworkUpload, - EventNameType_None, - eBasicEventClass) -WINDOW_ONLY_EVENT(moznetworkdownload, - eNetworkDownload, - EventNameType_None, - eBasicEventClass) -#endif // MOZ_B2G - TOUCH_EVENT(touchstart, eTouchStart, EventNameType_All, @@ -1003,6 +991,10 @@ EVENT(transitionend, eTransitionEnd, EventNameType_All, eTransitionEventClass) +EVENT(transitioncancel, + eTransitionCancel, + EventNameType_All, + eTransitionEventClass) EVENT(animationstart, eAnimationStart, EventNameType_All, @@ -1015,6 +1007,10 @@ EVENT(animationiteration, eAnimationIteration, EventNameType_All, eAnimationEventClass) +EVENT(animationcancel, + eAnimationCancel, + EventNameType_All, + eAnimationEventClass) // Webkit-prefixed versions of Transition & Animation events, for web compat: EVENT(webkitAnimationEnd, diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index c6b304183..7bbfe21b7 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -492,6 +492,7 @@ IsMessageMouseUserActivity(EventMessage aMessage) return aMessage == eMouseMove || aMessage == eMouseUp || aMessage == eMouseDown || + aMessage == eMouseAuxClick || aMessage == eMouseDoubleClick || aMessage == eMouseClick || aMessage == eMouseActivate || @@ -4633,6 +4634,32 @@ EventStateManager::SetClickCount(WidgetMouseEvent* aEvent, } nsresult +EventStateManager::InitAndDispatchClickEvent(WidgetMouseEvent* aEvent, + nsEventStatus* aStatus, + EventMessage aMessage, + nsIPresShell* aPresShell, + nsIContent* aMouseTarget, + nsWeakFrame aCurrentTarget, + bool aNoContentDispatch) +{ + WidgetMouseEvent event(aEvent->IsTrusted(), aMessage, + aEvent->mWidget, WidgetMouseEvent::eReal); + + event.mRefPoint = aEvent->mRefPoint; + event.mClickCount = aEvent->mClickCount; + event.mModifiers = aEvent->mModifiers; + event.buttons = aEvent->buttons; + event.mTime = aEvent->mTime; + event.mTimeStamp = aEvent->mTimeStamp; + event.mFlags.mNoContentDispatch = aNoContentDispatch; + event.button = aEvent->button; + event.inputSource = aEvent->inputSource; + + return aPresShell->HandleEventWithTarget(&event, aCurrentTarget, + aMouseTarget, aStatus); +} + +nsresult EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent, nsEventStatus* aStatus) { @@ -4651,17 +4678,7 @@ EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent, (aEvent->button == WidgetMouseEvent::eMiddleButton || aEvent->button == WidgetMouseEvent::eRightButton); - WidgetMouseEvent event(aEvent->IsTrusted(), eMouseClick, - aEvent->mWidget, WidgetMouseEvent::eReal); - event.mRefPoint = aEvent->mRefPoint; - event.mClickCount = aEvent->mClickCount; - event.mModifiers = aEvent->mModifiers; - event.buttons = aEvent->buttons; - event.mTime = aEvent->mTime; - event.mTimeStamp = aEvent->mTimeStamp; - event.mFlags.mNoContentDispatch = notDispatchToContents; - event.button = aEvent->button; - event.inputSource = aEvent->inputSource; + bool fireAuxClick = notDispatchToContents; nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell(); if (presShell) { @@ -4680,23 +4697,22 @@ EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent, // HandleEvent clears out mCurrentTarget which we might need again nsWeakFrame currentTarget = mCurrentTarget; - ret = presShell->HandleEventWithTarget(&event, currentTarget, - mouseContent, aStatus); + ret = InitAndDispatchClickEvent(aEvent, aStatus, eMouseClick, + presShell, mouseContent, currentTarget, + notDispatchToContents); + if (NS_SUCCEEDED(ret) && aEvent->mClickCount == 2 && mouseContent && mouseContent->IsInComposedDoc()) { //fire double click - WidgetMouseEvent event2(aEvent->IsTrusted(), eMouseDoubleClick, - aEvent->mWidget, WidgetMouseEvent::eReal); - event2.mRefPoint = aEvent->mRefPoint; - event2.mClickCount = aEvent->mClickCount; - event2.mModifiers = aEvent->mModifiers; - event2.buttons = aEvent->buttons; - event2.mFlags.mNoContentDispatch = notDispatchToContents; - event2.button = aEvent->button; - event2.inputSource = aEvent->inputSource; - - ret = presShell->HandleEventWithTarget(&event2, currentTarget, - mouseContent, aStatus); + ret = InitAndDispatchClickEvent(aEvent, aStatus, eMouseDoubleClick, + presShell, mouseContent, currentTarget, + notDispatchToContents); + } + if (NS_SUCCEEDED(ret) && mouseContent && fireAuxClick && + mouseContent->IsInComposedDoc()) { + ret = InitAndDispatchClickEvent(aEvent, aStatus, eMouseAuxClick, + presShell, mouseContent, currentTarget, + false); } } } diff --git a/dom/events/EventStateManager.h b/dom/events/EventStateManager.h index 49ecf0586..d0461e7fa 100644 --- a/dom/events/EventStateManager.h +++ b/dom/events/EventStateManager.h @@ -415,6 +415,13 @@ protected: */ void UpdateDragDataTransfer(WidgetDragEvent* dragEvent); + static nsresult InitAndDispatchClickEvent(WidgetMouseEvent* aEvent, + nsEventStatus* aStatus, + EventMessage aMessage, + nsIPresShell* aPresShell, + nsIContent* aMouseTarget, + nsWeakFrame aCurrentTarget, + bool aNoContentDispatch); nsresult SetClickCount(WidgetMouseEvent* aEvent, nsEventStatus* aStatus); nsresult CheckForAndDispatchClick(WidgetMouseEvent* aEvent, nsEventStatus* aStatus); @@ -1046,6 +1053,7 @@ private: #define NS_EVENT_NEEDS_FRAME(event) \ (!(event)->HasPluginActivationEventMessage() && \ (event)->mMessage != eMouseClick && \ - (event)->mMessage != eMouseDoubleClick) + (event)->mMessage != eMouseDoubleClick && \ + (event)->mMessage != eMouseAuxClick) #endif // mozilla_EventStateManager_h_ diff --git a/dom/events/KeyNameList.h b/dom/events/KeyNameList.h index 35fbe2d5f..361122ec7 100644 --- a/dom/events/KeyNameList.h +++ b/dom/events/KeyNameList.h @@ -32,10 +32,6 @@ DEFINE_KEYNAME_INTERNAL(PrintableKey, "MozPrintableKey") DEFINE_KEYNAME_INTERNAL(SoftLeft, "MozSoftLeft") DEFINE_KEYNAME_INTERNAL(SoftRight, "MozSoftRight") -#ifdef MOZ_B2G -DEFINE_KEYNAME_INTERNAL(HomeScreen, "MozHomeScreen") -#endif // #ifdef MOZ_B2G - /****************************************************************************** * Modifier Keys *****************************************************************************/ diff --git a/dom/events/TouchEvent.cpp b/dom/events/TouchEvent.cpp index cc9684eb3..9b7a74ac2 100644 --- a/dom/events/TouchEvent.cpp +++ b/dom/events/TouchEvent.cpp @@ -203,7 +203,7 @@ TouchEvent::PrefEnabled(nsIDocShell* aDocShell) enabled = false; } else { if (sPrefCacheValue == 2) { -#if defined(MOZ_B2G) || defined(MOZ_WIDGET_ANDROID) +#if defined(MOZ_WIDGET_ANDROID) // Touch support is always enabled on B2G and android. enabled = true; #elif defined(XP_WIN) || MOZ_WIDGET_GTK == 3 diff --git a/dom/events/WheelHandlingHelper.cpp b/dom/events/WheelHandlingHelper.cpp index 7665ee922..81f2b6bfa 100644 --- a/dom/events/WheelHandlingHelper.cpp +++ b/dom/events/WheelHandlingHelper.cpp @@ -257,6 +257,7 @@ WheelTransaction::OnEvent(WidgetEvent* aEvent) case eMouseUp: case eMouseDown: case eMouseDoubleClick: + case eMouseAuxClick: case eMouseClick: case eContextMenu: case eDrop: diff --git a/dom/events/moz.build b/dom/events/moz.build index ee4946038..ec3813207 100644 --- a/dom/events/moz.build +++ b/dom/events/moz.build @@ -153,10 +153,5 @@ LOCAL_INCLUDES += [ '/layout/xul/tree/', ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': - LOCAL_INCLUDES += [ - '/dom/wifi', - ] - if CONFIG['GNU_CXX']: CXXFLAGS += ['-Wno-error=shadow'] diff --git a/dom/events/test/mochitest.ini b/dom/events/test/mochitest.ini index e100e60a1..0397487bb 100644 --- a/dom/events/test/mochitest.ini +++ b/dom/events/test/mochitest.ini @@ -184,3 +184,4 @@ skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM [test_wheel_default_action.html] [test_bug687787.html] [test_bug1298970.html] +[test_bug1304044.html] diff --git a/dom/events/test/test_bug1304044.html b/dom/events/test/test_bug1304044.html new file mode 100644 index 000000000..0911dcf73 --- /dev/null +++ b/dom/events/test/test_bug1304044.html @@ -0,0 +1,133 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1304044 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1304044</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + var eventsFired = []; + var target; + var eventsExpected; + + function GetNodeString(node) { + if (node == window) + return "window"; + if (node == document) + return "document"; + if (node.id) + return node.id; + if (node.nodeName) + return node.nodeName; + return node; + } + + function TargetAndListener(listener, target) { + this.listener = listener; + this.target = target; + } + + TargetAndListener.prototype.toString = function() { + var targetName = GetNodeString(this.target); + var listenerName = GetNodeString(this.listener); + return "(listener: " + listenerName + ", target: " + targetName + ")"; + } + + var tests = [ + TestAuxClickBubblesForEventListener, + TestAuxClickBubblesForOnAuxClick, + ]; + + function CompareEvents(evt, expected) { + return evt && expected && evt.listener == expected.listener && + evt.target == expected.target; + } + + function ResetEventsFired() { + eventsFired = []; + } + + function ClearEventListeners() { + for (i in arguments) { + arguments[i].removeEventListener("auxclick", log_event); + } + } + + function ClickTarget(tgt) { + synthesizeMouseAtCenter(tgt, {type : "mousedown", button: 2}, window); + synthesizeMouseAtCenter(tgt, {type : "mouseup", button: 2}, window); + } + + function log_event(e) { + eventsFired[eventsFired.length] = new TargetAndListener(this, e.target); + } + + function CompareEventsToExpected(expected, actual) { + for (var i = 0; i < expected.length || i < actual.length; i++) { + ok(CompareEvents(actual[i], expected[i]), + "Auxclick receiver's don't match: TargetAndListener " + + i + ": Expected: " + expected[i] + ", Actual: " + actual[i]); + } + } + + function TestAuxClickBubblesForEventListener() { + target.addEventListener("auxclick", log_event); + document.addEventListener("auxclick", log_event); + window.addEventListener("auxclick", log_event); + + ClickTarget(target) + CompareEventsToExpected(eventsExpected, eventsFired); + ResetEventsFired(); + ClearEventListeners(target, document, window); + } + + function TestAuxClickBubblesForOnAuxClick() { + target.onauxclick = log_event; + document.onauxclick = log_event; + window.onauxclick = log_event; + + ClickTarget(target); + CompareEventsToExpected(eventsExpected, eventsFired); + ResetEventsFired(); + } + + function RunTests(){ + for (var i = 0; i < tests.length; i++) { + tests[i](); + } + } + + function Begin() { + target = document.getElementById("target"); + eventsExpected = [ + new TargetAndListener(target, target), + new TargetAndListener(document, target), + new TargetAndListener(window, target), + ]; + RunTests(); + target.remove(); + SimpleTest.finish(); + } + + window.onload = function() { + SimpleTest.waitForExplicitFinish(); + SimpleTest.executeSoon(Begin); + } + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1304044">Mozilla Bug 1304044</a> +<p id="display"> + <div id="target">Target</div> +</p> +<div id="content" style:"display:none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/events/test/test_eventTimeStamp.html b/dom/events/test/test_eventTimeStamp.html index 107a21f87..056203e92 100644 --- a/dom/events/test/test_eventTimeStamp.html +++ b/dom/events/test/test_eventTimeStamp.html @@ -17,7 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=77992 <script type="text/js-worker" id="worker-src"> // Simply returns the event timestamp onmessage = function(evt) { - postMessage(evt.timeStamp); + postMessage(evt.timeStamp + performance.timeOrigin); } </script> <script type="text/js-worker" id="shared-worker-src"> @@ -25,7 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=77992 onconnect = function(evt) { var port = evt.ports[0]; port.onmessage = function(messageEvt) { - port.postMessage(messageEvt.timeStamp); + port.postMessage(messageEvt.timeStamp + performance.timeOrigin); }; }; </script> @@ -57,9 +57,9 @@ function testRegularEvents() { finishTests(); return; } - var timeBeforeEvent = window.performance.now(); - window.addEventListener("load", function(evt) { - var timeAfterEvent = window.performance.now(); + var timeBeforeEvent = performance.now(); + addEventListener("load", function(evt) { + var timeAfterEvent = performance.now(); ok(evt.timeStamp >= timeBeforeEvent && evt.timeStamp <= timeAfterEvent, "Event timestamp (" + evt.timeStamp + ") is in expected range: (" + @@ -71,19 +71,18 @@ function testRegularEvents() { function testWorkerEvents() { var blob = new Blob([ document.getElementById("worker-src").textContent ], { type: "text/javascript" }); - var worker = new Worker(window.URL.createObjectURL(blob)); + var worker = new Worker(URL.createObjectURL(blob)); worker.onmessage = function(evt) { - var timeAfterEvent = window.performance.now(); - // Comparing times across timelines may break now - // ok(evt.data >= timeBeforeEvent && - // evt.data <= timeAfterEvent, + var timeAfterEvent = performance.now() + performance.timeOrigin; + ok(evt.data >= timeBeforeEvent && + evt.data <= timeAfterEvent, // "Event timestamp in dedicated worker (" + evt.data + // ") is in expected range: (" + // timeBeforeEvent + ", " + timeAfterEvent + ")"); worker.terminate(); testSharedWorkerEvents(); }; - var timeBeforeEvent = window.performance.now(); + var timeBeforeEvent = performance.now() + performance.timeOrigin; worker.postMessage(""); } @@ -93,17 +92,16 @@ function testSharedWorkerEvents() { { type: "text/javascript" }); // Delay creation of worker slightly so it is easier to distinguish // shared worker creation time from this document's navigation start - window.setTimeout(function() { - var timeBeforeWorkerCreation = window.performance.now(); - var worker = new SharedWorker(window.URL.createObjectURL(blob)); + setTimeout(function() { + var timeBeforeEvent = performance.now() + performance.timeOrigin; + var worker = new SharedWorker(URL.createObjectURL(blob)); worker.port.onmessage = function(evt) { - var timeAfterEvent = window.performance.now(); - // Comparing times across timelines may break now - // ok(evt.data >= 0 && - // evt.data <= timeAfterEvent - timeBeforeWorkerCreation, + var timeAfterEvent = performance.now() + performance.timeOrigin; + ok(evt.data >= timeBeforeEvent && + evt.data <= timeAfterEvent, // "Event timestamp in shared worker (" + evt.data + // ") is in expected range: (0, " + - // (timeAfterEvent - timeBeforeWorkerCreation) + ")"); + // timeBeforeEvent + ", " + timeAfterEvent + ")"); worker.port.close(); finishTests(); }; diff --git a/dom/events/test/test_legacy_event.html b/dom/events/test/test_legacy_event.html index d772be106..b2105a6df 100644 --- a/dom/events/test/test_legacy_event.html +++ b/dom/events/test/test_legacy_event.html @@ -73,22 +73,15 @@ function triggerShortAnimation(node) { node.style.animation = "anim1 1ms linear"; } -// This function triggers a long animation with two iterations, which is -// *nearly* at the end of its first iteration. It will hit the end of that -// iteration (firing an event) almost immediately, 1ms in the future. +// This function triggers a very short (10ms long) animation with many +// iterations, which will cause a start event followed by an iteration event +// on each subsequent tick, to fire. // -// NOTE: It's important that this animation have a *long* duration. If it were -// short (e.g. 1ms duration), then we might jump past all its iterations in -// a single refresh-driver tick. And if that were to happens, we'd *never* fire -// any animationiteration events -- the CSS Animations spec says this event -// must not be fired "...when an animationend event would fire at the same time" -// (which would be the case in this example with a 1ms duration). So, to make -// sure our event does fire, we use a long duration and a nearly-as-long -// negative delay. This ensures we hit the end of the first iteration right -// away, and that we don't risk hitting the end of the second iteration at the -// same time. +// NOTE: We need the many iterations since if an animation frame coincides +// with the animation starting or ending we dispatch only the start or end +// event and not the iteration event. function triggerAnimationIteration(node) { - node.style.animation = "anim1 300s -299.999s linear 2"; + node.style.animation = "anim1 10ms linear 20000"; } // GENERAL UTILITY FUNCTIONS |