<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
   - License, v. 2.0. If a copy of the MPL was not distributed with this
   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->


<bindings id="progressmeterBindings"
   xmlns="http://www.mozilla.org/xbl"
   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   xmlns:xbl="http://www.mozilla.org/xbl">

  <binding id="progressmeter" role="xul:progressmeter">
    <resources>
      <stylesheet src="chrome://global/skin/progressmeter.css"/>
    </resources>

    <content>
      <xul:spacer class="progress-bar" xbl:inherits="mode"/>
      <xul:spacer class="progress-remainder" xbl:inherits="mode"/>
    </content>

    <implementation>
      <property name="mode" onset="if (this.mode != val) this.setAttribute('mode', val); return val;"
                            onget="return this.getAttribute('mode');"/>

      <property name="value" onget="return this.getAttribute('value') || '0';">
        <setter><![CDATA[
          var p = Math.round(val);
          var max = Math.round(this.max);
          if (p < 0)
            p = 0;
          else if (p > max)
            p = max;
          var c = this.value;
          if (p != c) {
            var delta = p - c;
            if (delta < 0)
              delta = -delta;
            if (delta > 3 || p == 0 || p == max) {
              this.setAttribute("value", p);
              // Fire DOM event so that accessible value change events occur
              var event = document.createEvent('Events');
              event.initEvent('ValueChange', true, true);
              this.dispatchEvent(event);
            }
          }

          return val;
        ]]></setter>
      </property>
      <property name="max"
                onget="return this.getAttribute('max') || '100';"
                onset="this.setAttribute('max', isNaN(val) ? 100 : Math.max(val, 1));
                       this.value = this.value;
                       return val;" />
    </implementation>
  </binding>

  <binding id="progressmeter-undetermined"
           extends="chrome://global/content/bindings/progressmeter.xml#progressmeter">
    <content>
      <xul:stack class="progress-remainder" flex="1" anonid="stack" style="overflow: -moz-hidden-unscrollable;">
        <xul:spacer class="progress-bar" anonid="spacer" top="0" style="margin-right: -1000px;"/>
      </xul:stack>
    </content>

    <implementation>
      <field name="_alive">true</field>
      <method name="_init">
        <body><![CDATA[
          var stack =
            document.getAnonymousElementByAttribute(this, "anonid", "stack");
          var spacer =
            document.getAnonymousElementByAttribute(this, "anonid", "spacer");
          var isLTR =
           document.defaultView.getComputedStyle(this, null).direction == "ltr";
          var startTime = performance.now();
          var self = this;

          function nextStep(t) {
            try {
              var width = stack.boxObject.width;
              if (!width) {
                // Maybe we've been removed from the document.
                if (self._alive)
                  requestAnimationFrame(nextStep);
                return;
              }

              var elapsedTime = t - startTime;

              // Width of chunk is 1/5 (determined by the ratio 2000:400) of the
              // total width of the progress bar. The left edge of the chunk
              // starts at -1 and moves all the way to 4. It covers the distance
              // in 2 seconds.
              var position = isLTR ? ((elapsedTime % 2000) / 400) - 1 :
                                     ((elapsedTime % 2000) / -400) + 4;

              width = width >> 2;
              spacer.height = stack.boxObject.height;
              spacer.width = width;
              spacer.left = width * position;

              requestAnimationFrame(nextStep);
            } catch (e) {
            }
          }
          requestAnimationFrame(nextStep);
        ]]></body>
      </method>

      <constructor>this._init();</constructor>
    </implementation>
  </binding>

</bindings>
