Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / style / xbl-marquee / xbl-marquee.xml
blob46caa50d34c6b23f421919dacd8dc0b4122bfa66
1 <?xml version="1.0"?>
2 <!-- ***** BEGIN LICENSE BLOCK *****
3    - Version: MPL 1.1/GPL 2.0/LGPL 2.1
4    -
5    - The contents of this file are subject to the Mozilla Public License Version
6    - 1.1 (the "License"); you may not use this file except in compliance with
7    - the License. You may obtain a copy of the License at
8    - http://www.mozilla.org/MPL/
9    -
10    - Software distributed under the License is distributed on an "AS IS" basis,
11    - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12    - for the specific language governing rights and limitations under the
13    - License.
14    -
15    - The Original Code is Netscape's XBL Marquee Emulation code.
16    -
17    - The Initial Developer of the Original Code is
18    - Netscape Communications Corporation.
19    - Portions created by the Initial Developer are Copyright (C) 2002
20    - the Initial Developer. All Rights Reserved.
21    -
22    - Contributor(s):
23    -   Doron Rosenberg <doron@netscape.com>
24    -   L. David Baron <dbaron@dbaron.org>
25    -
26    - Alternatively, the contents of this file may be used under the terms of
27    - either the GNU General Public License Version 2 or later (the "GPL"), or
28    - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29    - in which case the provisions of the GPL or the LGPL are applicable instead
30    - of those above. If you wish to allow use of your version of this file only
31    - under the terms of either the GPL or the LGPL, and not to allow others to
32    - use your version of this file under the terms of the MPL, indicate your
33    - decision by deleting the provisions above and replace them with the notice
34    - and other provisions required by the LGPL or the GPL. If you do not delete
35    - the provisions above, a recipient may use your version of this file under
36    - the terms of any one of the MPL, the GPL or the LGPL.
37    -
38    - ***** END LICENSE BLOCK ***** -->
40 <bindings id="marqueeBindings"
41           xmlns="http://www.mozilla.org/xbl"
42           xmlns:html="http://www.w3.org/1999/xhtml"
43           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
44           xmlns:xbl="http://www.mozilla.org/xbl">
47   <binding id="marquee">
49     <resources>
50       <stylesheet src="chrome://xbl-marquee/content/xbl-marquee.css"/>
51     </resources>
52     <implementation>
54       <field name="_scrollAmount">6</field>
55       <property name="scrollAmount">
56         <getter>
57           <![CDATA[
58           var val = parseInt(this.getAttribute("scrollamount"));
60           if (val <= 0 || isNaN(val))
61             return this._scrollAmount;
63           return val;
64           ]]>
65         </getter>
66         <setter>
67           this.setAttribute("scrollamount", val);
68         </setter>
69       </property>
71       <field name="_scrollDelay">85</field>
72       <property name="scrollDelay">
73         <getter>
74           <![CDATA[
75           var val = parseInt(this.getAttribute("scrolldelay"));
77           if (val <= 0 || isNaN(val))
78             return this._scrollDelay;
80           return val;
81           ]]>
82         </getter>
83         <setter>
84           this.setAttribute("scrolldelay", val);
85         </setter>
86       </property>
88       <property name="trueSpeed">
89         <getter>
90           <![CDATA[
91           if (!this.hasAttribute("truespeed"))
92             return false;
94           return true;
95           ]]>
96         </getter>
97         <setter>
98           <![CDATA[
99           if (val)
100             this.setAttribute("truespeed", "truespeed");
101           else
102             this.removeAttribute('truespeed');
103           ]]>
104         </setter>
105       </property>
107       <property name="direction">
108         <getter>
109           return this.getAttribute("direction");
110         </getter>
111         <setter>
112           this.setAttribute("direction", val);
113         </setter>
114       </property>
116       <field name="_direction">"left"</field>
118       <property name="behavior">
119         <getter>
120           return this._behavior;
121         </getter>
122         <setter>
123           this.setAttribute("behavior", val);
124         </setter>
125       </property>
127       <field name="_behavior">"scroll"</field>
129       <property name="loop">
130         <getter>
131           <![CDATA[
132           var val = parseInt(this.getAttribute('loop'));
133     
134           if (val < -1 || isNaN(val))
135             return this._loop;
137           return val;
138           ]]>
139         </getter>
140         <setter>
141           this.setAttribute("loop", val);
142         </setter>
143       </property>
145       <field name="_loop">-1</field>
147       <property name="onstart">
148         <getter>
149           return this.getAttribute("onstart");
150         </getter>
151         <setter>
152           this._setEventListener("start", val, true);
153           this.setAttribute("onstart", val);
154         </setter>
155       </property>
157       <field name="_onstart"></field>
159       <property name="onfinish">
160         <getter>
161           return this.getAttribute("onfinish");
162         </getter>
163         <setter>
164           this._setEventListener("finish", val, true);
165           this.setAttribute("onfinish", val);
166         </setter>
167       </property>
169       <field name="_onfinish"></field>
171       <property name="onbounce">
172         <getter>
173           return this.getAttribute("onbounce");
174         </getter>
175         <setter>
176           this._setEventListener("bounce", val, true);
177           this.setAttribute("onbounce", val);
178         </setter>
179       </property>
181       <field name="_onbounce"></field>
183       <field name="dirsign">1</field>
184       <field name="startAt">0</field>
185       <field name="stopAt">0</field>
186       <field name="newPosition">0</field>
187       <field name="runId">0</field>
189       <field name="originalHeight">0</field>
190       <field name="startNewDirection">true</field>
192       <property name="outerDiv"
193         onget="return document.getAnonymousNodes(this)[0]"
194       />
196       <property name="innerDiv"
197         onget="return document.getAnonymousElementByAttribute(this, 'class', 'innerDiv');"
198       />
200       <property name="height"
201         onget="return this.getAttribute('height');"
202         onset="this.setAttribute('height', val);"
203       />
205       <property name="width"
206         onget="return this.getAttribute('width');"
207         onset="this.setAttribute('width', val);"
208       />
210       <!-- For sniffing purposes -->
211       <field name="nsMarqueeVersion">"0.9.7"</field>
213       <method name="_set_scrollDelay">
214         <parameter name="aValue"/>
215         <body>
216         <![CDATA[
217           if (aValue <= 0 || isNaN(aValue) || aValue == null)
218             return false;
220           if (aValue < 60) {
221             if (this.trueSpeed == true)
222               this._scrollDelay = aValue;
223             else
224               this._scrollDelay = 60;
225           }
226           else {
227             this._scrollDelay = aValue;
228           }
229           return true;
230         ]]>
231         </body>
232       </method>
234       <method name="_set_scrollAmount">
235         <parameter name="aValue"/>
236         <body>
237         <![CDATA[
238           if (aValue < 0 || isNaN(aValue) || aValue == null)
239             return false;
241           this._scrollAmount = aValue;
242           return true;
243         ]]>
244         </body>
245       </method>
247       <method name="_set_behavior">
248         <parameter name="aValue"/>
249         <body>
250         <![CDATA[
251           if (typeof aValue == 'string')
252             aValue = aValue.toLowerCase();
253           if (aValue != 'alternate' && aValue != 'slide' && aValue != 'scroll')
254             return false;
256           this._behavior = aValue;
257           return true;
258         ]]>
259         </body>
260       </method>
262       <method name="_set_direction">
263         <parameter name="aValue"/>
264         <body>
265         <![CDATA[
266           if (typeof aValue == 'string')
267             aValue = aValue.toLowerCase();
268           if (aValue != 'left' && aValue != 'right' && aValue != 'up' && aValue != 'down')
269             return false;
271           if (aValue != this._direction)
272             this.startNewDirection = true;
273           this._direction = aValue;
274           return true;
275         ]]>
276         </body>
277       </method>
279       <method name="_set_loop">
280         <parameter name="aValue"/>
281         <body>
282           <![CDATA[
283           if (!aValue || isNaN(aValue))
284             return false;
286           if (aValue < -1)
287             aValue = -1;
289           this._loop = aValue;
290           return true;
291           ]]>
292         </body>
293       </method>
295       <method name="_setEventListener">
296         <parameter name="aName"/>
297         <parameter name="aValue"/>
298         <parameter name="aIgnoreNextCall"/>
299         <body>
300           <![CDATA[
301           if (this._ignoreNextCall)
302             return this._ignoreNextCall = false;
304           if (aIgnoreNextCall)
305             this._ignoreNextCall = true;
307           if (typeof this["_on" + aName] == 'function')
308             this.removeEventListener(aName, this["_on" + aName], false);
310           switch (typeof aValue)
311           {
312             case "function":
313               this["_on" + aName] = aValue;
314               this.addEventListener(aName, this["_on" + aName], false);
315             break;
317             case "string":
318               if (!aIgnoreNextCall) {
319                 try {
320                   this["_on" + aName] = new Function("event", aValue);
321                 }
322                 catch(e) {
323                   return false;
324                 }
325                 this.addEventListener(aName, this["_on" + aName], false);
326               }
327               else {
328                 this["_on" + aName] = aValue;
329               }
330             break;
332             case "object":
333               this["_on" + aName] = aValue;
334             break;
336             default:
337               this._ignoreNextCall = false;
338               throw new Error("Invalid argument for Marquee::on" + aName);
339           }
340           return true;
341           ]]>
342         </body>
343       </method>
345       <method name="_fireEvent">
346         <parameter name="aName"/>
347         <parameter name="aBubbles"/>
348         <parameter name="aCancelable"/>
349         <body>
350         <![CDATA[
351           var e = document.createEvent("Events");
352           e.initEvent(aName, aBubbles, aCancelable);
353           this.dispatchEvent(e);
354         ]]>
355         </body>
356       </method>
358       <method name="start">
359         <body>
360         <![CDATA[
361           if (this.runId == 0) {
362             var myThis = this;
363             var lambda = function myTimeOutFunction(){myThis._doMove(false);}
364             this.runId = window.setTimeout(lambda, this._scrollDelay - this._deltaStartStop);
365             this._deltaStartStop = 0;
366           }
367         ]]>
368         </body>
369       </method>
371       <method name="stop">
372         <body>
373         <![CDATA[
374           if (this.runId != 0) {
375             this._deltaStartStop = Date.now()- this._lastMoveDate;
376             clearTimeout(this.runId);
377           }
379           this.runId = 0;
380         ]]>
381         </body>
382       </method>
384       <method name="_doMove">
385         <parameter name="aResetPosition"/>
386         <body>
387         <![CDATA[
388           this._lastMoveDate = Date.now();
390           //startNewDirection is true at first load and whenever the direction is changed
391           if (this.startNewDirection) {
392             this.startNewDirection = false; //we only want this to run once every scroll direction change
394             var corrvalue = 0;
396             switch (this._direction)
397             {
398               case "up":
399                 var height = document.defaultView.getComputedStyle(this, "").height;
400                 this.outerDiv.style.height = height;
401                 if (this.originalHeight > this.outerDiv.offsetHeight)
402                     corrvalue = this.originalHeight - this.outerDiv.offsetHeight;
403                 this.innerDiv.style.padding = height + " 0";
404                 this.dirsign = 1;
405                 this.startAt = (this._behavior == 'alternate') ? (this.originalHeight - corrvalue) : 0;
406                 this.stopAt  = (this._behavior == 'alternate' || this._behavior == 'slide') ? 
407                                 (parseInt(height) + corrvalue) : (this.originalHeight + parseInt(height));
408               break;
410               case "down":
411                 var height = document.defaultView.getComputedStyle(this, "").height;
412                 this.outerDiv.style.height = height;
413                 if (this.originalHeight > this.outerDiv.offsetHeight)
414                     corrvalue = this.originalHeight - this.outerDiv.offsetHeight;
415                 this.innerDiv.style.padding = height + " 0";
416                 this.dirsign = -1;
417                 this.startAt  = (this._behavior == 'alternate') ?
418                                 (parseInt(height) + corrvalue) : (this.originalHeight + parseInt(height));
419                 this.stopAt = (this._behavior == 'alternate' || this._behavior == 'slide') ? 
420                               (this.originalHeight - corrvalue) : 0;
421               break;
423               case "right":
424                 if (this.innerDiv.offsetWidth > this.outerDiv.offsetWidth)
425                     corrvalue = this.innerDiv.offsetWidth - this.outerDiv.offsetWidth;
426                 this.dirsign = -1;
427                 this.stopAt  = (this._behavior == 'alternate' || this._behavior == 'slide') ? 
428                                (this.innerDiv.offsetWidth - corrvalue) : 0;
429                 this.startAt = this.outerDiv.offsetWidth + ((this._behavior == 'alternate') ? 
430                                corrvalue : (this.innerDiv.offsetWidth + this.stopAt));   
431               break;
433               case "left":
434               default:
435                 if (this.innerDiv.offsetWidth > this.outerDiv.offsetWidth)
436                     corrvalue = this.innerDiv.offsetWidth - this.outerDiv.offsetWidth;
437                 this.dirsign = 1;
438                 this.startAt = (this._behavior == 'alternate') ? (this.innerDiv.offsetWidth - corrvalue) : 0;
439                 this.stopAt  = this.outerDiv.offsetWidth + 
440                                ((this._behavior == 'alternate' || this._behavior == 'slide') ? 
441                                corrvalue : (this.innerDiv.offsetWidth + this.startAt));
442             }
444             if (aResetPosition) {
445               this.newPosition = this.startAt;
446               this._fireEvent("start", false, false);
447             }
448           } //end if
450           this.newPosition = this.newPosition + (this.dirsign * this._scrollAmount);
452           if ((this.dirsign == 1 && this.newPosition > this.stopAt) ||
453               (this.dirsign == -1 && this.newPosition < this.stopAt))
454           {
455             switch (this._behavior) 
456             {
457               case 'alternate':
458                 // lets start afresh
459                 this.startNewDirection = true;
461                 // swap direction
462                 const swap = {left: "right", down: "up", up: "down", right: "left"};
463                 this._direction = swap[this._direction];
464                 this.newPosition = this.stopAt;
466                 if ((this._direction == "up") || (this._direction == "down"))
467                   this.outerDiv.scrollTop = this.newPosition;
468                 else
469                   this.outerDiv.scrollLeft = this.newPosition;
471                 if (this._loop != 1)
472                   this._fireEvent("bounce", false, true);
473               break;
475               case 'slide':
476                 if (this._loop > 1)
477                   this.newPosition = this.startAt;
478               break;
480               default:
481                 this.newPosition = this.startAt;
483                 if ((this._direction == "up") || (this._direction == "down"))
484                   this.outerDiv.scrollTop = this.newPosition;
485                 else
486                   this.outerDiv.scrollLeft = this.newPosition;
488                 //dispatch start event, even when this._loop == 1, comp. with IE6
489                 this._fireEvent("start", false, false);
490             }
492             if (this._loop > 1)
493               this._loop--;
494             else if (this._loop == 1) {
495               if ((this._direction == "up") || (this._direction == "down"))
496                 this.outerDiv.scrollTop = this.stopAt;
497               else
498                 this.outerDiv.scrollLeft = this.stopAt;
499               this.stop();
500               this._fireEvent("finish", false, true);
501               return;
502             }
503           }
504           else {
505             if ((this._direction == "up") || (this._direction == "down"))
506               this.outerDiv.scrollTop = this.newPosition;
507             else
508               this.outerDiv.scrollLeft = this.newPosition;
509           }
511           var myThis = this;
512           var lambda = function myTimeOutFunction(){myThis._doMove(false);}
513           this.runId = window.setTimeout(lambda, this._scrollDelay);
514         ]]>
515         </body>
516       </method>
518       <method name="init">
519         <body>
520         <![CDATA[
521           this.stop();
523           if ((this._direction != "up") && (this._direction != "down")) {
524             var width = window.getComputedStyle(this, "").width;
525             this.innerDiv.parentNode.style.margin = '0 ' + width;
527             //XXX Adding the margin sometimes causes the marquee to widen, 
528             // see testcase from bug bug 364434: 
529             // https://bugzilla.mozilla.org/attachment.cgi?id=249233
530             // Just add a fixed width with current marquee's width for now
531             if (width != window.getComputedStyle(this, "").width) {
532               var width = window.getComputedStyle(this, "").width;
533               this.outerDiv.style.width = width;
534               this.innerDiv.parentNode.style.margin = '0 ' + width;
535             }
536           }
537           else {
538             // store the original height before we add padding
539             this.innerDiv.style.padding = 0;
540             this.originalHeight = this.innerDiv.offsetHeight;
541           }
543           this._doMove(true);
544         ]]>
545         </body>
546       </method>
548       <constructor>
549         <![CDATA[
550           // hack needed to fix js error, see bug 386470
551           var myThis = this;
552           var lambda = function myScopeFunction() { if (myThis.init) myThis.init(); }
554           this._set_direction(this.getAttribute('direction'));
555           this._set_behavior(this.getAttribute('behavior'));
556           this._set_scrollDelay(this.getAttribute('scrolldelay'));
557           this._set_scrollAmount(this.getAttribute('scrollamount'));
558           this._set_loop(this.getAttribute('loop'));
559           this._setEventListener("start", this.getAttribute("onstart"));
560           this._setEventListener("finish", this.getAttribute("onfinish"));
561           this._setEventListener("bounce", this.getAttribute("onbounce"));
562           this.startNewDirection = true;
564           // init needs to be run after the page has loaded in order to calculate
565           // the correct height/width
566           window.addEventListener("load", lambda, false);
567         ]]>
568       </constructor>
569     </implementation>
571     <handlers>
572       <handler event="DOMAttrModified" phase="target">
573         <![CDATA[
574           var attrName = event.attrName.toLowerCase();
575           var oldValue = event.prevValue.toLowerCase();
576           var newValue = event.newValue.toLowerCase();
577           var attributeRemoval = false;
578           if (event.attrChange == event.REMOVAL) {
579             newValue = null;
580             attributeRemoval = true;
581           };
583           if (oldValue != newValue) {
584             switch (attrName) {
585               case "loop":
586                 if (!this._set_loop(newValue)) {
587                   if (attributeRemoval) {
588                     this._loop = -1;
589                     if (this.runId == 0)
590                       this.start();
591                   }
592                   else
593                     throw new Error("Invalid argument for Marquee::loop");
594                 }
595                 if (this.rundId == 0)
596                   this.start();
597                 break;
598               case "scrollamount":
599                 if (!this._set_scrollAmount(newValue)) {
600                   if (attributeRemoval)
601                     this._scrollAmount = 6;
602                   else
603                     throw new Error("Invalid argument for Marquee::scrollAmount");
604                 }
605                 break;
606               case "scrolldelay":
607                 if (!this._set_scrollDelay(newValue)) {
608                   if (attributeRemoval)
609                     this._scrollDelay = 85;
610                   else
611                     throw new Error("Invalid argument for Marquee::scrollDelay");
612                 }
613                 this.stop();
614                 this.start();
615                 break;
616               case "truespeed":
617                 //needed to update this._scrollDelay
618                 var myThis = this;
619                 var lambda = function() {myThis._set_scrollDelay(myThis.getAttribute('scrolldelay'));}
620                 window.setTimeout(lambda, 0);
621                 break;
622               case "behavior":
623                 if (!this._set_behavior(newValue)) {
624                   if (attributeRemoval)
625                     this._behavior = "scroll";
626                   else
627                     throw new Error("Invalid argument for Marquee::behavior");
628                 }
630                 this.startNewDirection = true;
631                 if ((oldValue == "slide" && this.newPosition == this.stopAt) ||
632                     newValue == "alternate" || newValue == "slide") {
633                   this.stop();
634                   this._doMove(true);
635                 }
636                 break;
637               case "direction":
638                 if (!this._set_direction(newValue)) {
639                   if (attributeRemoval)
640                     this._direction = "left";
641                   else
642                     throw new Error("Invalid argument for Marquee::direction");
643                 }
644                 break;
645               case "width":
646               case "height":
647                 this.startNewDirection = true;
648                 break;
649               case "onstart":
650                 this._setEventListener("start", newValue);
651                 break;
652               case "onfinish":
653                 this._setEventListener("finish", newValue);
654                 break;
655               case "onbounce":
656                 this._setEventListener("bounce", newValue);
657                 break;
658             }
659           }
660         ]]>
661       </handler>
662     </handlers>
664   </binding>
666   <binding id="marquee-horizontal"
667            extends="chrome://xbl-marquee/content/xbl-marquee.xml#marquee"
668            inheritstyle="false">
670     <!-- White-space isn't allowed because a marquee could be 
671          inside 'white-space: pre' -->
672     <content>
673       <html:div style="display: -moz-box; overflow: hidden; width: -moz-available;"
674         ><html:div style="display: -moz-box;"
675           ><html:div class="innerDiv" style="display: table; border-spacing: 0;"
676             ><html:div
677               ><children
678             /></html:div
679           ></html:div
680         ></html:div
681       ></html:div>
682     </content>
684   </binding>
686   <binding id="marquee-vertical"
687            extends="chrome://xbl-marquee/content/xbl-marquee.xml#marquee"
688            inheritstyle="false">
690     <!-- White-space isn't allowed because a marquee could be 
691          inside 'white-space: pre' -->
692     <content>
693       <html:div style="overflow: hidden; width: -moz-available;"
694         ><html:div class="innerDiv"
695           ><children
696         /></html:div
697       ></html:div>
698     </content>
700   </binding>
702   <binding id="marquee-horizontal-editable"
703            inheritstyle="false">
705     <!-- White-space isn't allowed because a marquee could be 
706          inside 'white-space: pre' -->
707     <content>
708       <html:div style="display: -moz-box; overflow: auto; width: -moz-available;"
709         ><children
710       /></html:div>
711     </content>
713   </binding>
715   <binding id="marquee-vertical-editable"
716            inheritstyle="false">
718     <!-- White-space isn't allowed because a marquee could be 
719          inside 'white-space: pre' -->
720     <content>
721       <html:div style="overflow: auto; height: inherit; width: -moz-available;"
722         ><children/></html:div>
723     </content>
725   </binding>
727 </bindings>