Bug 1160342 - Implement marquee using mutation observers, r=smaug

This commit is contained in:
Martijn Wargers 2016-02-17 18:47:14 +01:00
parent ac975a3e11
commit 842cd6d33f
7 changed files with 352 additions and 93 deletions

View File

@ -168,4 +168,5 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s
[test_bug1022869.html]
[test_bug1112040.html]
[test_bug1160342_marquee.html]
[test_bug1171215.html]

View File

@ -0,0 +1,228 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1160342
-->
<head>
<title>Test for Bug 411103</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1160342">Mozilla Bug 1160342</a>
<p id="display"></p>
<div id="content">
<marquee id="a">marquee</marquee>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var x=document.getElementById('a');
SimpleTest.waitForExplicitFinish();
setTimeout(function() {
is(x.behavior, "scroll", "Wrong behavior value");
x.setAttribute('behavior', 'alternate');
is(x.behavior, "alternate", "Wrong behavior value");
x.setAttribute('behavior', 'invalid');
todo_is(x.behavior, "scroll", "Wrong behavior value");;
x.setAttribute('behavior', 'Scroll');
is(x.behavior, "scroll", "Wrong behavior value");
x.setAttribute('behavior', 'Slide');
is(x.behavior, "slide", "Wrong behavior value");
x.removeAttribute('behavior');
is(x.behavior, "scroll", "Wrong behavior value");
x.behavior = 'alternate';
is(x.behavior, "alternate", "Wrong behavior value");
try {
x.behavior = 'invalid';
todo_is(false, true, "marquee.behavior = 'invalid' should throw");
} catch(e) {
ok(true, "Exception was raised");
}
is(x.behavior, "alternate", "Wrong behavior value");
x.behavior = 'Slide';
is(x.behavior, "slide", "Wrong behavior value");
try {
x.behavior = 'invalid';
todo_is(false, true, "marquee.behavior = 'invalid' should throw");
} catch(e) {
ok(true, "Exception was raised");
}
is(x.behavior, "slide", "Wrong behavior value");
is(x.loop, -1, "Wrong loop value");
x.setAttribute('loop', '1');
is(x.loop, 1, "Wrong loop value");
x.setAttribute('loop', 'invalid');
todo_is(x.loop, -1, "Wrong loop value");
x.setAttribute('loop', '1000');
is(x.loop, 1000, "Wrong loop value");
x.setAttribute('loop', '-1');
is(x.loop, -1, "Wrong loop value");
x.setAttribute('loop', '1000');
is(x.loop, 1000, "Wrong loop value");
x.removeAttribute('loop');
is(x.loop, -1, "Wrong loop value");
x.loop = 1;
is(x.loop, 1, "Wrong loop value");
try {
x.loop = -2;
todo_is(false, true, "marquee.loop = -2 should throw");
} catch(e) {
ok(true, "Exception was raised");
}
todo_is(x.loop, 1, "Wrong loop value");
try {
x.loop = 'invalid';
todo_is(false, true, ".loop = 'invalid' should throw");
} catch(e) {
ok(true, "Exception was raised");
}
todo_is(x.loop, 1, "Wrong loop value");
try {
x.loop = null;
todo_is(false, true, "marquee.loop = null should throw");
} catch(e) {
ok(true, "Exception was raised");
}
todo_is(x.loop, 1, "Wrong loop value");
x.loop = -1;
is(x.loop, -1, "Wrong loop value");
x.loop = '100';
is(x.loop, 100, "Wrong loop value");
is(x.scrollAmount, 6, "Wrong scrollAmount value");
x.setAttribute('scrollAmount', '1');
is(x.scrollAmount, 1, "Wrong scrollAmount value");
x.setAttribute('scrollAmount', 'invalid');
todo_is(x.scrollAmount, 6, "Wrong scrollAmount value");
x.setAttribute('scrollAmount', '1000');
is(x.scrollAmount, 1000, "Wrong scrollAmount value");
x.setAttribute('scrollAmount', '-1');
is(x.scrollAmount, 1000, "Wrong scrollAmount value");
x.setAttribute('scrollAmount', '999');
is(x.scrollAmount, 999, "Wrong scrollAmount value");
x.removeAttribute('scrollAmount');
is(x.scrollAmount, 6, "Wrong scrollAmount value");
x.scrollAmount = 1;
is(x.scrollAmount, 1, "Wrong scrollAmount value");
try {
x.scrollAmount = -2;
todo_is(false, true, "marquee.scrollAmount = -2 should throw");
} catch(e) {
ok(true, "Exception was raised");
}
is(x.scrollAmount, 1, "Wrong scrollAmount value");
x.scrollAmount = 'invalid';
todo_is(x.scrollAmount, 0, "Wrong scrollAmount value");
x.scrollAmount = 1;
x.scrollAmount = null;
todo_is(x.scrollAmount, 0, "Wrong scrollAmount value");
x.scrollAmount = '2';
is(x.scrollAmount, 2, "Wrong scrollAmount value");
is(x.scrollDelay, 85, "Wrong scrollDelay value");
x.setAttribute('scrollDelay', '1');
is(x.scrollDelay, 1, "Wrong scrollDelay value");
x.setAttribute('scrollDelay', 'invalid');
todo_is(x.scrollDelay, 85, "Wrong scrollDelay value");
x.setAttribute('scrollDelay', '70');
is(x.scrollDelay, 70, "Wrong scrollDelay value");
x.setAttribute('scrollDelay', '59');
is(x.scrollDelay, 59, "Wrong scrollDelay value");
x.setAttribute('scrollDelay', '1000');
is(x.scrollDelay, 1000, "Wrong scrollDelay value");
x.setAttribute('scrollDelay', '-1');
is(x.scrollDelay, 1000, "Wrong scrollDelay value");
x.removeAttribute('scrollDelay');
is(x.scrollDelay, 85, "Wrong scrollDelay value");
x.scrollDelay = 100;
is(x.scrollDelay, 100, "Wrong scrollDelay value");
try {
x.scrollDelay = -2;
todo_is(false, true, "marquee.scrollDelay = -2 should throw");
} catch(e) {
ok(true, "Exception was raised");
}
is(x.scrollDelay, 100, "Wrong scrollDelay value");
try {
x.scrollDelay = 'invalid';
todo_is(false, true, "marquee.scrollDelay = 'invalid' should throw");
} catch(e) {
ok(true, "Exception was raised");
}
is(x.scrollDelay, 100, "Wrong scrollDelay value");
try {
x.scrollDelay = null;
todo_is(false, true, "marquee.scrollDelay = null should throw");
} catch(e) {
ok(true, "Exception was raised");
}
is(x.scrollDelay, 100, "Wrong scrollDelay value");
try {
x.scrollDelay = -1;
todo_is(false, true, "marquee.scrollDelay = -1 should throw");
} catch(e) {
ok(true, "Exception was raised");
}
is(x.scrollDelay, 100, "Wrong scrollDelay value");
x.scrollDelay = '50';
is(x.scrollDelay, 50, "Wrong scrollDelay value");
is(x.trueSpeed, false, "Wrong trueSpeed value");
x.setAttribute('trueSpeed', '1');
is(x.trueSpeed, true, "Wrong trueSpeed value");
x.setAttribute('trueSpeed', 'false');
is(x.trueSpeed, true, "Wrong trueSpeed value");
x.removeAttribute('trueSpeed');
is(x.trueSpeed, false, "Wrong trueSpeed value");
x.trueSpeed = 1;
is(x.trueSpeed, true, "Wrong trueSpeed value");
x.trueSpeed = -2;
is(x.trueSpeed, true, "Wrong trueSpeed value");
x.trueSpeed = null;
is(x.trueSpeed, false, "Wrong trueSpeed value");
x.trueSpeed = '100';
is(x.trueSpeed, true, "Wrong trueSpeed value");
todo_is(x.direction, "left", "Wrong direction value");
x.setAttribute('direction', 'right');
is(x.direction, "right", "Wrong direction value");
x.setAttribute('direction', 'invalid');
todo_is(x.direction, "left", "Wrong direction value");
x.setAttribute('direction', 'RIGHT');
todo_is(x.direction, "right", "Wrong direction value");
x.removeAttribute('direction');
todo_is(x.direction, "left", "Wrong direction value");
x.direction = 'right';
is(x.direction, "right", "Wrong direction value");
try {
x.direction = 1;
todo_is(false, true, "marquee.direction = 1 should throw");
} catch(e) {
ok(true, "Exception was raised");
}
todo_is(x.direction, "right", "Wrong direction value");
try {
x.direction = null;
todo_is(false, true, "marquee.direction = null should throw");
} catch(e) {
ok(true, "Exception was raised");
}
todo_is(x.direction, "right", "Wrong direction value");
SimpleTest.finish();
}, 0);
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>Bug 1160342 - Implement marquee using mutation observers</title>
</head>
<body onload="document.getElementById('a').setAttribute('behavior', 'alternate')">
<marquee id="a" scrollamount=0 direction=right>
This text should be visible
</marquee>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>Bug 1160342 - Implement marquee using mutation observers</title>
</head>
<body onload="document.getElementById('a').setAttribute('direction', 'right')">
<marquee id="a" behavior=alternate scrollamount=0>
This text should be visible
</marquee>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>Bug 1160342 - Implement marquee using mutation observers</title>
</head>
<body>
<marquee id="a" behavior=alternate scrollamount=0 direction=right>
This text should be visible
</marquee>
</body>
</html>

View File

@ -7,3 +7,5 @@ fuzzy-if(Android&&AndroidVersion>=15,8,220) == 413027-4.html 413027-4-ref.html
fuzzy-if(Android&&AndroidVersion>=15,8,30) == 425247-1.html 425247-1-ref.html
fuzzy-if(Android&&AndroidVersion>=15,8,30) == 425247-2.html 425247-2-ref.html
random == 429849-1.html 429849-1-ref.html # bug 432288
== 1160342-1.html 1160342-ref.html
== 1160342-2.html 1160342-ref.html

View File

@ -20,6 +20,7 @@
<property name="scrollAmount" exposeToUntrustedContent="true">
<getter>
<![CDATA[
this._mutationActor(this._mutationObserver.takeRecords());
var val = parseInt(this.getAttribute("scrollamount"));
if (val <= 0 || isNaN(val))
@ -36,6 +37,7 @@
<property name="scrollDelay" exposeToUntrustedContent="true">
<getter>
<![CDATA[
this._mutationActor(this._mutationObserver.takeRecords());
var val = parseInt(this.getAttribute("scrolldelay"));
if (val <= 0 || isNaN(val))
@ -79,6 +81,7 @@
<property name="behavior" exposeToUntrustedContent="true">
<getter>
this._mutationActor(this._mutationObserver.takeRecords());
return this._behavior;
</getter>
<setter>
@ -90,6 +93,7 @@
<property name="loop" exposeToUntrustedContent="true">
<getter>
<![CDATA[
this._mutationActor(this._mutationObserver.takeRecords());
var val = parseInt(this.getAttribute('loop'));
if (val < -1 || isNaN(val))
@ -156,6 +160,7 @@
<parameter name="aValue"/>
<body>
<![CDATA[
aValue = parseInt(aValue);
if (aValue <= 0 || isNaN(aValue) || aValue == null)
return false;
@ -177,6 +182,7 @@
<parameter name="aValue"/>
<body>
<![CDATA[
aValue = parseInt(aValue);
if (aValue < 0 || isNaN(aValue) || aValue == null)
return false;
@ -488,6 +494,88 @@
</body>
</method>
<method name="_mutationActor">
<parameter name="aMutations"/>
<body>
<![CDATA[
while (aMutations.length > 0) {
var mutation = aMutations.shift();
var attrName = mutation.attributeName.toLowerCase();
var oldValue = mutation.oldValue;
var target = mutation.target;
var newValue = target.getAttribute(attrName);
if (oldValue != newValue) {
switch (attrName) {
case "loop":
if (!target._set_loop(newValue)) {
if (!newValue) {
target._loop = -1;
if (target.runId == 0)
target.start();
}
}
if (target.rundId == 0)
target.start();
break;
case "scrollamount":
if (!newValue)
target._scrollAmount = 6;
else
target._set_scrollAmount(newValue);
break;
case "scrolldelay":
if (!newValue)
target._scrollDelay = 85;
else
target._set_scrollDelay(newValue);
target.stop();
target.start();
break;
case "truespeed":
//needed to update target._scrollDelay
var myThis = target;
var lambda = function() {myThis._set_scrollDelay(myThis.getAttribute('scrolldelay'));}
window.setTimeout(lambda, 0);
break;
case "behavior":
if (!newValue)
target._behavior = "scroll";
else
target._set_behavior(newValue);
target.startNewDirection = true;
if ((oldValue == "slide" && target.newPosition == target.stopAt) ||
newValue == "alternate" || newValue == "slide") {
target.stop();
target._doMove(true);
}
break;
case "direction":
if (!newValue)
target._direction = "left";
else
target._set_direction(newValue);
break;
case "width":
case "height":
target.startNewDirection = true;
break;
case "onstart":
target._setEventListener("start", newValue);
break;
case "onfinish":
target._setEventListener("finish", newValue);
break;
case "onbounce":
target._setEventListener("bounce", newValue);
break;
}
}
}
]]>
</body>
</method>
<constructor>
<![CDATA[
// Set up state.
@ -518,6 +606,9 @@
this._setEventListener("bounce", this.getAttribute("onbounce"));
this.startNewDirection = true;
this._mutationObserver = new MutationObserver(this._mutationActor);
this._mutationObserver.observe(this, { attributes: true, attributeOldValue: true });
// init needs to be run after the page has loaded in order to calculate
// the correct height/width
if (document.readyState == "complete")
@ -528,99 +619,6 @@
</constructor>
</implementation>
<handlers>
<handler event="DOMAttrModified" phase="target">
<![CDATA[
var attrName = event.attrName.toLowerCase();
var oldValue = event.prevValue.toLowerCase();
var newValue = event.newValue.toLowerCase();
var attributeRemoval = false;
if (event.attrChange == event.REMOVAL) {
newValue = null;
attributeRemoval = true;
};
if (oldValue != newValue) {
switch (attrName) {
case "loop":
if (!this._set_loop(newValue)) {
if (attributeRemoval) {
this._loop = -1;
if (this.runId == 0)
this.start();
}
else
throw new Error("Invalid argument for Marquee::loop");
}
if (this.rundId == 0)
this.start();
break;
case "scrollamount":
if (!this._set_scrollAmount(newValue)) {
if (attributeRemoval)
this._scrollAmount = 6;
else
throw new Error("Invalid argument for Marquee::scrollAmount");
}
break;
case "scrolldelay":
if (!this._set_scrollDelay(newValue)) {
if (attributeRemoval)
this._scrollDelay = 85;
else
throw new Error("Invalid argument for Marquee::scrollDelay");
}
this.stop();
this.start();
break;
case "truespeed":
//needed to update this._scrollDelay
var myThis = this;
var lambda = function() {myThis._set_scrollDelay(myThis.getAttribute('scrolldelay'));}
window.setTimeout(lambda, 0);
break;
case "behavior":
if (!this._set_behavior(newValue)) {
if (attributeRemoval)
this._behavior = "scroll";
else
throw new Error("Invalid argument for Marquee::behavior");
}
this.startNewDirection = true;
if ((oldValue == "slide" && this.newPosition == this.stopAt) ||
newValue == "alternate" || newValue == "slide") {
this.stop();
this._doMove(true);
}
break;
case "direction":
if (!this._set_direction(newValue)) {
if (attributeRemoval)
this._direction = "left";
else
throw new Error("Invalid argument for Marquee::direction");
}
break;
case "width":
case "height":
this.startNewDirection = true;
break;
case "onstart":
this._setEventListener("start", newValue);
break;
case "onfinish":
this._setEventListener("finish", newValue);
break;
case "onbounce":
this._setEventListener("bounce", newValue);
break;
}
}
]]>
</handler>
</handlers>
</binding>
<binding id="marquee-horizontal" bindToUntrustedContent="true"