Bug 848291 - Update TransitionEvent to be compatible with the spec, r=dbaron

This commit is contained in:
Olli Pettay 2013-05-04 17:41:20 +03:00
parent f6f5713fa6
commit cbb79393f6
8 changed files with 108 additions and 26 deletions

View File

@ -829,7 +829,8 @@ nsDOMEvent::DuplicatePrivateData()
static_cast<nsTransitionEvent*>(mEvent);
newEvent = new nsTransitionEvent(false, msg,
oldTransitionEvent->propertyName,
oldTransitionEvent->elapsedTime);
oldTransitionEvent->elapsedTime,
oldTransitionEvent->pseudoElement);
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
break;
}

View File

@ -15,7 +15,8 @@ nsDOMTransitionEvent::nsDOMTransitionEvent(mozilla::dom::EventTarget* aOwner,
: nsDOMEvent(aOwner, aPresContext,
aEvent ? aEvent : new nsTransitionEvent(false, 0,
EmptyString(),
0.0))
0.0,
EmptyString()))
{
if (aEvent) {
mEventIsInternal = false;
@ -45,6 +46,23 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMPL_ADDREF_INHERITED(nsDOMTransitionEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMTransitionEvent, nsDOMEvent)
//static
already_AddRefed<nsDOMTransitionEvent>
nsDOMTransitionEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
const nsAString& aType,
const mozilla::dom::TransitionEventInit& aParam,
mozilla::ErrorResult& aRv)
{
nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.Get());
nsRefPtr<nsDOMTransitionEvent> e = new nsDOMTransitionEvent(t, nullptr, nullptr);
bool trusted = e->Init(t);
aRv = e->InitTransitionEvent(aType, aParam.mBubbles, aParam.mCancelable,
aParam.mPropertyName, aParam.mElapsedTime,
aParam.mPseudoElement);
e->SetTrusted(trusted);
return e.forget();
}
NS_IMETHODIMP
nsDOMTransitionEvent::GetPropertyName(nsAString & aPropertyName)
{
@ -59,19 +77,27 @@ nsDOMTransitionEvent::GetElapsedTime(float *aElapsedTime)
return NS_OK;
}
NS_IMETHODIMP
nsDOMTransitionEvent::GetPseudoElement(nsAString& aPseudoElement)
{
aPseudoElement = TransitionEvent()->pseudoElement;
return NS_OK;
}
NS_IMETHODIMP
nsDOMTransitionEvent::InitTransitionEvent(const nsAString & typeArg,
bool canBubbleArg,
bool cancelableArg,
const nsAString & propertyNameArg,
float elapsedTimeArg)
float elapsedTimeArg,
const nsAString& aPseudoElement)
{
nsresult rv = nsDOMEvent::InitEvent(typeArg, canBubbleArg, cancelableArg);
NS_ENSURE_SUCCESS(rv, rv);
TransitionEvent()->propertyName = propertyNameArg;
TransitionEvent()->elapsedTime = elapsedTimeArg;
TransitionEvent()->pseudoElement = aPseudoElement;
return NS_OK;
}

View File

@ -25,6 +25,12 @@ public:
NS_FORWARD_TO_NSDOMEVENT
NS_DECL_NSIDOMTRANSITIONEVENT
static already_AddRefed<nsDOMTransitionEvent>
Constructor(const mozilla::dom::GlobalObject& aGlobal,
const nsAString& aType,
const mozilla::dom::TransitionEventInit& aParam,
mozilla::ErrorResult& aRv);
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
{
@ -33,6 +39,7 @@ public:
// xpidl implementation
// GetPropertyName(nsAString& aPropertyName)
// GetPseudoElement(nsAString& aPreudoElement)
float ElapsedTime()
{
@ -44,10 +51,12 @@ public:
bool aCancelable,
const nsAString& aPropertyName,
float aElapsedTime,
const mozilla::dom::Optional<nsAString>& aPseudoElement,
mozilla::ErrorResult& aRv)
{
aRv = InitTransitionEvent(aType, aCanBubble, aCancelable, aPropertyName,
aElapsedTime);
aElapsedTime, aPseudoElement.WasPassed() ?
aPseudoElement.Value() : EmptyString());
}
private:
nsTransitionEvent* TransitionEvent() {

View File

@ -11,13 +11,15 @@
* http://dev.w3.org/csswg/css3-transitions/#transition-events-
*/
[scriptable, builtinclass, uuid(9013310a-e376-40bc-b141-9b9ae3085daa)]
[scriptable, builtinclass, uuid(eca50ac5-087a-4e50-bdf6-b341f0f9f8ab)]
interface nsIDOMTransitionEvent : nsIDOMEvent {
readonly attribute DOMString propertyName;
readonly attribute float elapsedTime;
readonly attribute DOMString pseudoElement;
void initTransitionEvent(in DOMString typeArg,
in boolean canBubbleArg,
in boolean cancelableArg,
in DOMString propertyNameArg,
in float elapsedTimeArg);
in float elapsedTimeArg,
[optional] in DOMString pseudoElement);
};

View File

@ -11,14 +11,27 @@
* liability, trademark and document use rules apply.
*/
[Constructor(DOMString type, optional TransitionEventInit eventInitDict)]
interface TransitionEvent : Event {
readonly attribute DOMString propertyName;
readonly attribute float elapsedTime;
readonly attribute DOMString pseudoElement;
};
dictionary TransitionEventInit : EventInit {
DOMString propertyName = "";
float elapsedTime = 0;
DOMString pseudoElement = "";
};
// initTransitionEvent is a legacy method, and removed from the latest version
// of the specification.
partial interface TransitionEvent {
[Throws]
void initTransitionEvent(DOMString aType,
boolean aCanBubble,
boolean aCancelable,
DOMString aPropertyName,
float aElapsedTime);
float aElapsedTime,
optional DOMString pseudoElement);
};

View File

@ -967,11 +967,11 @@ struct TransitionEventInfo {
nsTransitionEvent mEvent;
TransitionEventInfo(nsIContent *aElement, nsCSSProperty aProperty,
TimeDuration aDuration)
TimeDuration aDuration, const nsAString& aPseudoElement)
: mElement(aElement),
mEvent(true, NS_TRANSITION_END,
NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aProperty)),
aDuration.ToSeconds())
aDuration.ToSeconds(), aPseudoElement)
{
}
@ -980,7 +980,8 @@ struct TransitionEventInfo {
TransitionEventInfo(const TransitionEventInfo &aOther)
: mElement(aOther.mElement),
mEvent(true, NS_TRANSITION_END,
aOther.mEvent.propertyName, aOther.mEvent.elapsedTime)
aOther.mEvent.propertyName, aOther.mEvent.elapsedTime,
aOther.mEvent.pseudoElement)
{
}
};
@ -1048,18 +1049,21 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags)
et->mPropertyTransitions.RemoveElementAt(i);
}
} else if (pt.mStartTime + pt.mDuration <= now) {
// Fire transitionend events only for transitions on elements
// and not those on pseudo-elements, since we can't target an
// event at pseudo-elements.
if (et->mElementProperty == nsGkAtoms::transitionsProperty) {
nsCSSProperty prop = pt.mProperty;
if (nsCSSProps::PropHasFlags(prop, CSS_PROPERTY_REPORT_OTHER_NAME))
{
prop = nsCSSProps::OtherNameFor(prop);
}
events.AppendElement(
TransitionEventInfo(et->mElement, prop, pt.mDuration));
nsCSSProperty prop = pt.mProperty;
if (nsCSSProps::PropHasFlags(prop, CSS_PROPERTY_REPORT_OTHER_NAME))
{
prop = nsCSSProps::OtherNameFor(prop);
}
nsIAtom* ep = et->mElementProperty;
NS_NAMED_LITERAL_STRING(before, "::before");
NS_NAMED_LITERAL_STRING(after, "::after");
events.AppendElement(
TransitionEventInfo(et->mElement, prop, pt.mDuration,
ep == nsGkAtoms::transitionsProperty ?
EmptyString() :
ep == nsGkAtoms::transitionsOfBeforeProperty ?
before :
after));
// Leave this transition in the list for one more refresh
// cycle, since we haven't yet processed its style change, and

View File

@ -30,7 +30,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=531585
transition-timing-function: cubic-bezier(0, 1, 1, 0);
}
/* make sure we don't get events for the pseudo-elements */
#seven::before, #seven::after {
content: "x";
transition-duration: 50ms;
@ -80,6 +79,7 @@ var got_three_left = false;
var got_four_root = false;
var got_body = false;
var did_stops = false;
var got_before = false;
document.documentElement.addEventListener("transitionend",
function(event) {
@ -114,6 +114,15 @@ document.documentElement.addEventListener("transitionend",
"elapsedTime for transitionend on body");
got_body = true;
finished_test();
} else if (event.target == $("seven")) {
if (!got_before) {
got_before = true;
is(event.pseudoElement, "::before");
} else {
is(event.pseudoElement, "::after");
}
is(event.propertyName, "color");
is(event.isTrusted, true);
} else {
if (!did_stops &&
(event.target == $("five") || event.target == $("six"))) {
@ -263,7 +272,6 @@ $("five").style.color = "lime";
// then changing the value, so we should get no event.
$("six").style.color = "lime";
// We should get no events from transitions on pseudo-elements.
$("seven").setAttribute("foo", "bar");
setTimeout(function() {
@ -290,6 +298,22 @@ setTimeout(poll_start_reversal, 200);
// And make our own event to dispatch to the body.
started_test();
var e = new TransitionEvent("foo",
{
bubbles: true,
cancelable: true,
propertyName: "name",
elapsedTime: 0.5,
pseudoElement: "pseudo"
});
is(e.bubbles, true);
is(e.cancelable, true);
is(e.propertyName, "name");
is(e.elapsedTime, "0.5");
is(e.pseudoElement, "pseudo");
is(e.isTrusted, false)
var ev = document.createEvent("TransitionEvent"); // FIXME: un-specified
ev.initTransitionEvent("transitionend", true, true,
"some-unknown-prop", -4.75);

View File

@ -1758,14 +1758,17 @@ class nsTransitionEvent : public nsEvent
{
public:
nsTransitionEvent(bool isTrusted, uint32_t msg,
const nsString &propertyNameArg, float elapsedTimeArg)
const nsAString& propertyNameArg, float elapsedTimeArg,
const nsAString& pseudoElementArg)
: nsEvent(isTrusted, msg, NS_TRANSITION_EVENT),
propertyName(propertyNameArg), elapsedTime(elapsedTimeArg)
propertyName(propertyNameArg), elapsedTime(elapsedTimeArg),
pseudoElement(pseudoElementArg)
{
}
nsString propertyName;
float elapsedTime;
nsString pseudoElement;
};
class nsAnimationEvent : public nsEvent