<commit_before>
/**
 * Create a pseudorandom number generator, with a seed.
 * @param {array} seed "128-bit" integer, composed of 4x32-bit integers in big endian order.
 */
function XorShift(seed) {
  if (!Array.isArray(seed) || seed.length !== 4) {
    throw new TypeError('seed must be array with 4 elements');
  }

  // uint64_t s = [seed ...]
  this._state0U = seed[0] | 0;
  this._state0L = seed[1] | 0;
  this._state1U = seed[2] | 0;
  this._state1L = seed[3] | 0;
}

// There is nothing particularly scientific about this seed, it is just
// based on the clock.
module.exports = new XorShift([
  0, Date.now() / 65536,
  0, Date.now() % 65536
]);
/**
 * Returns a random number normalized [0, 1[, just like Math.random()
 * @return {number}
 */
XorShift.prototype.randint = function() {
  // uint64_t s1 = s[0]
  var s1U = this._state0U, s1L = this._state0L;
  // uint64_t s0 = s[1]
  var s0U = this._state1U, s0L = this._state1L;

  // s[0] = s0
  this._state0U = s0U;
  this._state0L = s0L;

  // - t1 = [0, 0]
  var t1U = 0, t1L = 0;
  // - t2 = [0, 0]
  var t2U = 0, t2L = 0;

  // s1 ^= s1 << 23;
  // :: t1 = s1 << 23
  var a1 = 23;
  var m1 = 0xFFFFFFFF << (32 - a1);
  t1U = (s1U << a1) | ((s1L & m1) >>> (32 - a1));
  t1L = s1L << a1;
  // :: s1 = s1 ^ t1
  s1U = s1U ^ t1U;
  s1L = s1L ^ t1L;

  // t1 = ( s1 ^ s0 ^ ( s1 >> 17 ) ^ ( s0 >> 26 ) )
  // :: t1 = s1 ^ s0
  t1U = s1U ^ s0U;
  t1L = s1L ^ s0L;
  // :: t2 = s1 >> 17
  var a2 = 17;
  var m2 = 0xFFFFFFFF >>> (32 - a2);
  t2U = s1U >>> a2;
  t2L = (s1L >>> a2) | ((s1U & m2) << (32 - a2));
  // :: t1 = t1 ^ t2
  t1U = t1U ^ t2U;
  t1L = t1L ^ t2L;
  // :: t2 = s0 >> 26
  var a3 = 26;
  var m3 = 0xFFFFFFFF >>> (32 - a3);
  t2U = s0U >>> a3;
  t2L = (s0L >>> a3) | ((s0U & m3) << (32 - a3));
  // :: t1 = t1 ^ t2
  t1U = t1U ^ t2U;
  t1L = t1L ^ t2L;

  // s[1] = t1
  this._state1U = t1U;
  this._state1L = t1L;

  // return t1 + s0
  // :: t2 = t1 + s0
  var sumL = (t1L >>> 0) + (s0L >>> 0);
  t2U = (t1U + s0U + (sumL / 2 >>> 31)) >>> 0;
  t2L = sumL >>> 0;

  // :: ret t2
  return [t2U, t2L];
};

/**
 * Returns a random number normalized [0, 1[, just like Math.random()
 * @return {number}
 */
XorShift.prototype.rand = function() {
  var t2 = this.randint();

  // :: ret t2 / 2**64
  return (t2[0] * 4294967296 + t2[1]) / 18446744073709551616;
};
<commit_msg>[review] change method names, iterate default rng<commit_after>
/**
 * Create a pseudorandom number generator, with a seed.
 * @param {array} seed "128-bit" integer, composed of 4x32-bit
 * integers in big endian order.
 */
function XorShift(seed) {
  // Note the extension, this === module.exports is required because
  // the `constructor` function will be used to generate new instances.
  // In that case `this` will point to the default RNG, and `this` will
  // be an instance of XorShift.
  if (!(this instanceof XorShift) || this === module.exports) {
    return new XorShift(seed);
  }

  if (!Array.isArray(seed) || seed.length !== 4) {
    throw new TypeError('seed must be an array with 4 numbers');
  }

  // uint64_t s = [seed ...]
  this._state0U = seed[0] | 0;
  this._state0L = seed[1] | 0;
  this._state1U = seed[2] | 0;
  this._state1L = seed[3] | 0;
}

/**
 * Returns a 64bit random number as a 2x32bit array
 * @return {array}
 */
XorShift.prototype.randomint = function() {
  // uint64_t s1 = s[0]
  var s1U = this._state0U, s1L = this._state0L;
  // uint64_t s0 = s[1]
  var s0U = this._state1U, s0L = this._state1L;

  // s[0] = s0
  this._state0U = s0U;
  this._state0L = s0L;

  // - t1 = [0, 0]
  var t1U = 0, t1L = 0;
  // - t2 = [0, 0]
  var t2U = 0, t2L = 0;

  // s1 ^= s1 << 23;
  // :: t1 = s1 << 23
  var a1 = 23;
  var m1 = 0xFFFFFFFF << (32 - a1);
  t1U = (s1U << a1) | ((s1L & m1) >>> (32 - a1));
  t1L = s1L << a1;
  // :: s1 = s1 ^ t1
  s1U = s1U ^ t1U;
  s1L = s1L ^ t1L;

  // t1 = ( s1 ^ s0 ^ ( s1 >> 17 ) ^ ( s0 >> 26 ) )
  // :: t1 = s1 ^ s0
  t1U = s1U ^ s0U;
  t1L = s1L ^ s0L;
  // :: t2 = s1 >> 17
  var a2 = 17;
  var m2 = 0xFFFFFFFF >>> (32 - a2);
  t2U = s1U >>> a2;
  t2L = (s1L >>> a2) | ((s1U & m2) << (32 - a2));
  // :: t1 = t1 ^ t2
  t1U = t1U ^ t2U;
  t1L = t1L ^ t2L;
  // :: t2 = s0 >> 26
  var a3 = 26;
  var m3 = 0xFFFFFFFF >>> (32 - a3);
  t2U = s0U >>> a3;
  t2L = (s0L >>> a3) | ((s0U & m3) << (32 - a3));
  // :: t1 = t1 ^ t2
  t1U = t1U ^ t2U;
  t1L = t1L ^ t2L;

  // s[1] = t1
  this._state1U = t1U;
  this._state1L = t1L;

  // return t1 + s0
  // :: t2 = t1 + s0
  var sumL = (t1L >>> 0) + (s0L >>> 0);
  t2U = (t1U + s0U + (sumL / 2 >>> 31)) >>> 0;
  t2L = sumL >>> 0;

  // :: ret t2
  return [t2U, t2L];
};

/**
 * Returns a random number normalized [0, 1), just like Math.random()
 * @return {number}
 */
XorShift.prototype.random = function() {
  var t2 = this.randomint();

  // :: ret t2 / 2**64
  return (t2[0] * 4294967296 + t2[1]) / 18446744073709551616;
};

// There is nothing particularly scientific about this seed, it is just
// based on the clock.
module.exports = new XorShift([
  0, Date.now() / 65536,
  0, Date.now() % 65536
]);

// Perform 20 iterations in the RNG, this prevens a short seed from generating
// pseudo predictable number.
(function () {
  var rng = module.exports;
  for (var i = 0; i < 20; i++) {
    rng.randomint();
  }
})();
<|endoftext|>


<commit_before>"use strict";
var Scroller = {
  Animate: null,
  calibrationBoundary: 150,
  maxCalibration: 1.6,
  minCalibration: 0.5,
  // high:  60f / 1000ms :  400ms / 24f
  // low:   15f /  250ms :   33ms /  2f
  maxInterval: 28,
  minDelay: 500,
  performScroll: function(el, di, amount) {
    var before;
    if (di) {
      if (el) {
        before = el.scrollTop;
        el.scrollTop += amount;
        return el.scrollTop !== before;
      } else {
        before = window.scrollY;
        window.scrollBy(0, amount);
        return window.scrollY !== before;
      }
    } else if (el) {
      before = el.scrollLeft;
      el.scrollLeft += amount;
      return el.scrollLeft !== before;
    } else {
      before = window.scrollX;
      window.scrollBy(amount, 0);
      return window.scrollX !== before;
    }
  },
  scroll: function(element, di, amount) {
    if (!amount) { return; }
    if (!Settings.values.smoothScroll) {
      this.performScroll(element, di, amount);
      DomUtils.isVisibile(Scroller.current) || (Scroller.current = element);
      return;
    }
    this.Animate(amount, di, element);
  }
};

Scroller = {
  Core: Scroller,
  current: null,
  keyIsDown: 0,
  Properties: [{
    axisName: "scrollLeft",
    max: "scrollWidth",
    viewSize: "clientWidth"
  }, {
    axisName: "scrollTop",
    max: "scrollHeight",
    viewSize: "clientHeight"
  }],
  scrollBy: function(direction, amount, factor, zoomX) {
    var element, di;
    di = direction === "y" ? 1 : 0;
    element = this.findScrollable(this.getActivatedElement(), di, amount, factor);
    amount *= this.getDimension(element, di, factor);
    if (zoomX && element && di === 0 && element.clientWidth <= element.clientHeight * 2) {
      amount = Math.ceil(amount * 0.6);
    }
    this.Core.scroll(element, di, amount);
  },
  scrollTo: function(direction, factor) {
    var amount, element, di = direction === "y" ? 1 : 0;;
    factor >= 0 ? (amount = factor, factor = "") : (amount = 1);
    element = this.findScrollable(this.getActivatedElement(), di, amount, factor);
    amount = amount * this.getDimension(element, di, factor) - (element
      ? element[this.Properties[di].axisName] : di ? window.scrollY : window.scrollX);
    this.Core.scroll(element, di, amount);
  },
  findScrollable: function(element, di, amount, factor) {
    while (element !== document.body && !(this.scrollDo(element, di, amount, factor)
        && this.shouldScroll(element, di))) {
      element = element.parentElement || document.body;
    }
    return element;
  },
  getActivatedElement: function() {
    var element = this.current;
    if (element) {
      return element;
    }
    element = document.body;
    return element = this.current = element
      ? (this.selectFirst(element) || element) : null;
  },
  getDimension: function(el, di, name) {
    return !name ? 1
      : (!el) ? document.documentElement[this.Properties[di][name]]
      : (name !== "viewSize" || el !== document.body) ? el[this.Properties[di][name]]
      : di ? window.innerHeight : window.innerWidth;
  },
  getSign: function(val) {
    return val === 0 ? 0 : val < 0 ? -1 : 1;
  },
  scrollDo: function(element, di, amount, factor) {
    amount = amount * this.getDimension(element, di, factor) > 0 ? 1 : -1;
    return this.Core.performScroll(element, di, amount) && this.Core.performScroll(element, di, -amount);
  },
  selectFirst: function(element) {
    if (this.scrollDo(element, 1, 1, "") || this.scrollDo(element, 1, -1, "")) {
      return element;
    }
    DomUtils.prepareCrop();
    var children = [], rect, _ref = element.children, _len = _ref.length;
    while (0 <= --_len) {
      element = _ref[_len];
      if (rect = DomUtils.getVisibleClientRect(element)) {
        children.push([(rect[2] - rect[0]) * (rect[3] - rect[1]), element]);
      }
    }
    if (_len = children.length) {
      children = children.sort(this.sortBy0);
      while (0 <= --_len) {
        if (element = this.selectFirst(children[_len][1])) {
          return element;
        }
      }
    }
    return null;
  },
  shouldScroll: function(element, di) {
    var computedStyle = window.getComputedStyle(element), _ref;
    return (computedStyle.getPropertyValue("display") === "none") //
      || (computedStyle.getPropertyValue(di ? "overflow-y" : "overflow-x") === "hidden") //
      || ((_ref = computedStyle.getPropertyValue("visibility")) === "hidden" || _ref === "collapse") //
      ? false : true;
  },
  sortBy0: function(a, b) {
    return a[0] - b[0];
  }
};

Scroller.Core.Animate = function () {
  var amount = 0, calibration = 1.0, di = 0, duration = 0, element = null, //
  sign = 0, timestamp = -1, totalDelta = 0, totalElapsed = 0.0, //
  animate = function(new_timestamp) {
    var int1 = timestamp, elapsed, _this;
    timestamp = new_timestamp;
    if (int1 === -1) {
      requestAnimationFrame(animate);
    }
    elapsed = new_timestamp - int1;
    int1 = (totalElapsed += elapsed);
    _this = Scroller.Core;
    if (Scroller.keyIsDown) {
      if (int1 >= 75) {
        if (int1 > _this.minDelay) { --Scroller.keyIsDown; }
        int1 = calibration;
        if (_this.minCalibration <= int1 && int1 <= _this.maxCalibration) {
          int1 = _this.calibrationBoundary / amount / int1;
          calibration *= (int1 > 1.05) ? 1.05 : (int1 < 0.95) ? 0.95 : 1.0;
        }
      }
      int1 = Math.ceil(amount * (elapsed / duration) * calibration);
    } else {
      int1 = Math.ceil(amount * (elapsed / duration) * calibration);
      int1 = Math.max(0, Math.min(int1, amount - totalDelta));
    }
    if (int1 && _this.performScroll(element, di, sign * int1)) {
      totalDelta += int1;
      requestAnimationFrame(animate);
    } else {
      DomUtils.isVisibile(Scroller.current) || (Scroller.current = element);
      if (elapsed !== 0) {
        element = null;
      }
    }
  };
  Scroller.Core.Animate = function(new_amount, new_di, new_el) {
    amount = Math.abs(new_amount), calibration = 1.0, di = new_di;
    duration = Math.max(100, 20 * Math.log(amount)), element = new_el;
    sign = Scroller.getSign(new_amount);
    timestamp = -1, totalDelta = 0, totalElapsed = 0.0;
    Scroller.keyIsDown = Scroller.Core.maxInterval;
    requestAnimationFrame(animate);
  };
  Scroller.Core.Animate.apply(null, arguments);
};
<commit_msg>Scroller: rework animate: remove useless logic<commit_after>"use strict";
var Scroller = {
  Animate: null,
  calibrationBoundary: 150,
  maxCalibration: 1.6,
  minCalibration: 0.5,
  // high:  60f / 1000ms :  400ms / 24f
  // low:   15f /  250ms :   33ms /  2f
  maxInterval: 28,
  minDelay: 500,
  performScroll: function(el, di, amount) {
    var before;
    if (di) {
      if (el) {
        before = el.scrollTop;
        el.scrollTop += amount;
        return el.scrollTop !== before;
      } else {
        before = window.scrollY;
        window.scrollBy(0, amount);
        return window.scrollY !== before;
      }
    } else if (el) {
      before = el.scrollLeft;
      el.scrollLeft += amount;
      return el.scrollLeft !== before;
    } else {
      before = window.scrollX;
      window.scrollBy(amount, 0);
      return window.scrollX !== before;
    }
  },
  scroll: function(element, di, amount) {
    if (!amount) { return; }
    if (!Settings.values.smoothScroll) {
      this.performScroll(element, di, amount);
      DomUtils.isVisibile(Scroller.current) || (Scroller.current = element);
      return;
    }
    this.Animate(amount, di, element);
  }
};

Scroller = {
  Core: Scroller,
  current: null,
  keyIsDown: 0,
  Properties: [{
    axisName: "scrollLeft",
    max: "scrollWidth",
    viewSize: "clientWidth"
  }, {
    axisName: "scrollTop",
    max: "scrollHeight",
    viewSize: "clientHeight"
  }],
  scrollBy: function(direction, amount, factor, zoomX) {
    var element, di;
    di = direction === "y" ? 1 : 0;
    element = this.findScrollable(this.getActivatedElement(), di, amount, factor);
    amount *= this.getDimension(element, di, factor);
    if (zoomX && element && di === 0 && element.clientWidth <= element.clientHeight * 2) {
      amount = Math.ceil(amount * 0.6);
    }
    this.Core.scroll(element, di, amount);
  },
  scrollTo: function(direction, factor) {
    var amount, element, di = direction === "y" ? 1 : 0;;
    factor >= 0 ? (amount = factor, factor = "") : (amount = 1);
    element = this.findScrollable(this.getActivatedElement(), di, amount, factor);
    amount = amount * this.getDimension(element, di, factor) - (element
      ? element[this.Properties[di].axisName] : di ? window.scrollY : window.scrollX);
    this.Core.scroll(element, di, amount);
  },
  findScrollable: function(element, di, amount, factor) {
    while (element !== document.body && !(this.scrollDo(element, di, amount, factor)
        && this.shouldScroll(element, di))) {
      element = element.parentElement || document.body;
    }
    return element;
  },
  getActivatedElement: function() {
    var element = this.current;
    if (element) {
      return element;
    }
    element = document.body;
    return element = this.current = element
      ? (this.selectFirst(element) || element) : null;
  },
  getDimension: function(el, di, name) {
    return !name ? 1
      : (!el) ? document.documentElement[this.Properties[di][name]]
      : (name !== "viewSize" || el !== document.body) ? el[this.Properties[di][name]]
      : di ? window.innerHeight : window.innerWidth;
  },
  getSign: function(val) {
    return val === 0 ? 0 : val < 0 ? -1 : 1;
  },
  scrollDo: function(element, di, amount, factor) {
    amount = amount * this.getDimension(element, di, factor) > 0 ? 1 : -1;
    return this.Core.performScroll(element, di, amount) && this.Core.performScroll(element, di, -amount);
  },
  selectFirst: function(element) {
    if (this.scrollDo(element, 1, 1, "") || this.scrollDo(element, 1, -1, "")) {
      return element;
    }
    DomUtils.prepareCrop();
    var children = [], rect, _ref = element.children, _len = _ref.length;
    while (0 <= --_len) {
      element = _ref[_len];
      if (rect = DomUtils.getVisibleClientRect(element)) {
        children.push([(rect[2] - rect[0]) * (rect[3] - rect[1]), element]);
      }
    }
    if (_len = children.length) {
      children = children.sort(this.sortBy0);
      while (0 <= --_len) {
        if (element = this.selectFirst(children[_len][1])) {
          return element;
        }
      }
    }
    return null;
  },
  shouldScroll: function(element, di) {
    var computedStyle = window.getComputedStyle(element), _ref;
    return (computedStyle.getPropertyValue("display") === "none") //
      || (computedStyle.getPropertyValue(di ? "overflow-y" : "overflow-x") === "hidden") //
      || ((_ref = computedStyle.getPropertyValue("visibility")) === "hidden" || _ref === "collapse") //
      ? false : true;
  },
  sortBy0: function(a, b) {
    return a[0] - b[0];
  }
};

Scroller.Core.Animate = function () {
  var amount = 0, calibration = 1.0, di = 0, duration = 0, element = null, //
  sign = 0, timestamp = -1, totalDelta = 0, totalElapsed = 0.0, //
  animate = function(new_timestamp) {
    var int1 = timestamp, elapsed, _this;
    timestamp = new_timestamp;
    if (int1 === -1) {
      requestAnimationFrame(animate);
      return;
    }
    elapsed = new_timestamp - int1;
    int1 = (totalElapsed += elapsed);
    _this = Scroller.Core;
    if (Scroller.keyIsDown) {
      if (int1 >= 75) {
        if (int1 > _this.minDelay) { --Scroller.keyIsDown; }
        int1 = calibration;
        if (_this.minCalibration <= int1 && int1 <= _this.maxCalibration) {
          int1 = _this.calibrationBoundary / amount / int1;
          calibration *= (int1 > 1.05) ? 1.05 : (int1 < 0.95) ? 0.95 : 1.0;
        }
      }
      int1 = Math.ceil(amount * (elapsed / duration) * calibration);
    } else {
      int1 = Math.ceil(amount * (elapsed / duration) * calibration);
      int1 = Math.max(0, Math.min(int1, amount - totalDelta));
    }
    if (int1 && _this.performScroll(element, di, sign * int1)) {
      totalDelta += int1;
      requestAnimationFrame(animate);
    } else if (Scroller.current !== element) {
      DomUtils.isVisibile(Scroller.current) || (Scroller.current = element);
    }
  };
  Scroller.Core.Animate = function(new_amount, new_di, new_el) {
    amount = Math.abs(new_amount), calibration = 1.0, di = new_di;
    duration = Math.max(100, 20 * Math.log(amount)), element = new_el;
    sign = Scroller.getSign(new_amount);
    timestamp = -1, totalDelta = 0, totalElapsed = 0.0;
    Scroller.keyIsDown = Scroller.Core.maxInterval;
    requestAnimationFrame(animate);
  };
  Scroller.Core.Animate.apply(null, arguments);
};
<|endoftext|>


<commit_before><commit_msg>Update forum.js<commit_after><|endoftext|>


<commit_before>var gTabDeque = {

    deque: undefined,
    currentlySelectedTab: undefined,

    mimickingAllTabMinimized: false,
    allTabsMinimizedMimic: undefined,

    onLoad: function() {
        if ('undefined' == typeof gBrowser) {
            return;
        }
        window.removeEventListener('load', gTabDeque.onLoad, false);
        window.addEventListener('SSWindowClosing', gTabDeque.onClose, false);
        window.addEventListener('unload', gTabDeque.onUnload, false);
        gBrowser.tabContainer.addEventListener("TabOpen", gTabDeque.onTabOpen, false);
        gBrowser.tabContainer.addEventListener("TabSelect", gTabDeque.onTabSelect, false);
        gBrowser.tabContainer.addEventListener("TabClose", gTabDeque.onTabClose, false);

        // TabSelect is not always called when tabs are being restored
        gTabDeque.handleTabListeners(gBrowser.selectedTab);
    },

    onClose: function() {
        // we don't want the mimic to be restored after restart...
        if (gTabDeque.allTabsMinimizedMimic) {
            // we need at least one tab unminimized, otherwise the mimic would
            // be restored right away
            gTabDeque.maximizeNextMinimizedTab();
            gBrowser.unpinTab(gTabDeque.allTabsMinimizedMimic);
            gBrowser.removeTab(gTabDeque.allTabsMinimizedMimic);
        }
    },

    onUnload: function() {
        window.removeEventListener('unload', gTabDeque.onUnload, false);
        window.removeEventListener('close', gTabDeque.onClose, false);
        gBrowser.tabContainer.removeEventListener("TabOpen", gTabDeque.onTabOpen, false);
        gBrowser.tabContainer.removeEventListener("TabSelect", gTabDeque.onTabSelect, false);
        gBrowser.tabContainer.removeEventListener("TabClose", gTabDeque.onTabClose, false);

        gTabDeque.handleTabListeners(undefined);
    },

    onTabOpen: function(anEvent) {
        if (!gTabDeque.mimickingAllTabMinimized) {
            var tab = anEvent.target;
            // can't check whether tab is being opened in background - start at
            // beginning and move to end of deque in onTabSelect if necessary
            gTabDeque.moveTabToDequeBeginning(tab);
            gBrowser.moveTabTo(tab, gBrowser.mCurrentTab.nextSibling._tPos);
        }
    },

    onTabSelect: function(anEvent) {
        gTabDeque.handleTabListeners(anEvent.target)
        // TabSelect is triggered when opening the mimic the first time and
        // when closing the last not minimized tab, but we don't want to add it
        // to the deque
        if (!gTabDeque.mimickingAllTabMinimized &&
            anEvent.target !== gTabDeque.allTabsMinimizedMimic) {
            gTabDeque.moveTabToDequeEnd(anEvent.target);
        }
        if (anEvent.target === gTabDeque.allTabsMinimizedMimic) {
            document.getElementById('nav-bar').collapsed = true;
        } else {
            document.getElementById('nav-bar').collapsed = false;
        }
    },

    handleTabListeners: function(tab) {
        if (gTabDeque.currentlySelectedTab) {
            gTabDeque.currentlySelectedTab.removeEventListener("mousedown", gTabDeque.onSelectedTabMouseDown, false);
            gTabDeque.currentlySelectedTab.removeEventListener("mouseup", gTabDeque.onSelectedTabMouseUp, false);
        }
        if (tab){
            gTabDeque.currentlySelectedTab = tab
            gTabDeque.currentlySelectedTab.hasMouseDown = false
            // have to split this up, otherwise click would be triggered even
            // on freshly selected tab
            gTabDeque.currentlySelectedTab.addEventListener("mousedown", gTabDeque.onSelectedTabMouseDown, false);
            gTabDeque.currentlySelectedTab.addEventListener("mouseup", gTabDeque.onSelectedTabMouseUp, false);
        }
    },

    onSelectedTabMouseDown: function(anEvent) {
        var tab = anEvent.target;
        if (anEvent.button == 0) {
            tab.hasMouseDown = true;
        }
    },

    onSelectedTabMouseUp: function(anEvent) {
        var tab = anEvent.target;
        if (tab.hasMouseDown && anEvent.button == 0) {
            gTabDeque.ensureInitialization();
            gTabDeque.minimizeTab(anEvent.target);
            tab.hasMouseDown = false;
        }
    },

    onTabClose: function(anEvent) {
        var closingTab = anEvent.target;
        gTabDeque.ensureInitialization();
        gTabDeque.removeTabFromDeque(closingTab);
        if (gTabDeque.deque.length == 0 && gBrowser.tabs.length <= 2) {
            // there aren't any minimized tabs
            gTabDeque.openTab();
        } else if (gTabDeque.deque.length == 0) {
            gTabDeque.mimicAllTabsMinimized();
        } else {
            if (closingTab.selected) {
                var currentIndex = gTabDeque.getTabIndex(closingTab);
                var nextIndex = gTabDeque.getTabIndex(gTabDeque.getNextTab());
                // the closing tab is still there when calculating the index,
                // but not when selecting
                var adjustment = currentIndex < nextIndex ? -1 : 0;
                gBrowser.selectTabAtIndex(nextIndex + adjustment);
            }
        }
    },

    minimizeCurrentTab: function() {
        gTabDeque.minimizeTab(gBrowser.selectedTab);
    },

    minimizeTab: function(tab) {
        gTabDeque.removeTabFromDeque(tab);
        if (gTabDeque.deque.length == 0) {
            gTabDeque.mimicAllTabsMinimized();
        } else {
            gBrowser.selectTabAtIndex(gTabDeque.getTabIndex(gTabDeque.getNextTab()));
        }
    },

    maximizeNextMinimizedTab: function() {
        for (var tabIndex = 0; tabIndex < gBrowser.tabs.length; tabIndex++) {
            visibleTab = gBrowser.tabs[tabIndex];
            if (visibleTab != gTabDeque.allTabsMinimizedMimic &&
                gTabDeque.deque.indexOf(visibleTab) == -1
                ) {
                gBrowser.selectTabAtIndex(gTabDeque.getTabIndex(visibleTab));
                return;
            }
        }
    },

    openTab: function(anEvent) {
        var preferences = Components
            .classes['@mozilla.org/preferences-service;1']
            .getService(Components.interfaces.nsIPrefBranch);
        var url = preferences.getCharPref("browser.newtab.url");
        return gBrowser.loadOneTab(url, null, null, null, false, false);
    },

    letTabOpenLinksInNewTab: function(tab) {
        var progressListener = {
            onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus){
                // abort at the very beginning
                if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
                    // open links in new tab while allowing reload
                    if (aBrowser === gBrowser.getBrowserForTab(tab) &&
                        aRequest.originalURI.asciiSpec != gBrowser.getBrowserForTab(tab).currentURI.asciiSpec
                    ) {
                        aRequest.cancel(Components.results.NS_BINDING_ABORTED);
                        gBrowser.loadOneTab(aRequest.name, null, null, null, false, false);
                    }
                }
            }
        }
        gBrowser.addTabsProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_STATE);
    },

    mimicAllTabsMinimized: function() {
        if (!gTabDeque.allTabsMinimizedMimic) {
            gTabDeque.mimickingAllTabMinimized = true;
            gTabDeque.allTabsMinimizedMimic = gTabDeque.openTab();
            gTabDeque.letTabOpenLinksInNewTab(gTabDeque.allTabsMinimizedMimic);
            gTabDeque.mimickingAllTabMinimized = false;
            gTabDeque.allTabsMinimizedMimic.collapsed = true;
            gTabDeque.allTabsMinimizedMimic.disabled = true;
            gBrowser.pinTab(gTabDeque.allTabsMinimizedMimic);
            // TabSelect is triggered before gTabDeque.allTabsMinimizedMimic is set
            document.getElementById('nav-bar').collapsed = true;
        } else {
            gBrowser.selectTabAtIndex(gTabDeque.getTabIndex(gTabDeque.allTabsMinimizedMimic));
        }
    },

    moveTabToDequeBeginning: function(tab) {
        gTabDeque.ensureInitialization();
        // getting duplicates sometimes...
        gTabDeque.removeTabFromDeque(tab);
        gTabDeque.deque.unshift(tab);
    },

    moveTabToDequeEnd: function(tab) {
        gTabDeque.ensureInitialization();
        // getting duplicates sometimes...
        gTabDeque.removeTabFromDeque(tab);
        gTabDeque.deque.push(tab);
    },

    // can't be sure that events are fired for all tabs on startup
    // tabs are missing if initialized too early, use this before first access
    ensureInitialization: function() {
        if (!gTabDeque.deque) {
            gTabDeque.initDeque();
        }
    },

    initDeque: function() {
        gTabDeque.deque = new Array();
        for (var tabIndex = 0; tabIndex < gBrowser.tabs.length; tabIndex++) {
            gTabDeque.deque.push(gBrowser.tabs[tabIndex]);
        }
        return gTabDeque.deque;
    },

    removeTabFromDeque: function(tab) {
        var dequeIndex = gTabDeque.deque.indexOf(tab)
        if (gTabDeque.deque.indexOf(tab) >= 0) {
            gTabDeque.deque.splice(gTabDeque.deque.indexOf(tab), 1);
        }
    },

    getTabIndex: function(givenTab) {
        for (var tabIndex = 0; tabIndex < gBrowser.tabs.length; tabIndex++) {
            if (gBrowser.tabs[tabIndex] === givenTab) {
                return tabIndex;
            }
        }
        return -1;
    },

    getNextTab: function() {
        return gTabDeque.deque[gTabDeque.deque.length - 1];
    },

    // for debugging
    getDequeURLs: function() {
        var urls = new Array();
        var length = gTabDeque.deque.length
        for (var tabIndex = 0; tabIndex < gTabDeque.deque.length; tabIndex++) {
            urls.push(gTabDeque.getTabURL(gTabDeque.deque[tabIndex]));
        }
        return urls;
    },

    getTabURL: function(tab) {
        var browser = gBrowser.getBrowserForTab(tab);
        return browser.currentURI.spec;
    }
};

window.addEventListener('load', gTabDeque.onLoad, false);

<commit_msg>Better formatting<commit_after>var gTabDeque = {

    deque: undefined,
    currentlySelectedTab: undefined,

    mimickingAllTabMinimized: false,
    allTabsMinimizedMimic: undefined,

    onLoad: function() {
        if ('undefined' == typeof gBrowser) {
            return;
        }
        window.removeEventListener('load', gTabDeque.onLoad, false);
        window.addEventListener('SSWindowClosing', gTabDeque.onClose, false);
        window.addEventListener('unload', gTabDeque.onUnload, false);
        gBrowser.tabContainer.addEventListener("TabOpen", gTabDeque.onTabOpen, false);
        gBrowser.tabContainer.addEventListener("TabSelect", gTabDeque.onTabSelect, false);
        gBrowser.tabContainer.addEventListener("TabClose", gTabDeque.onTabClose, false);

        // TabSelect is not always called when tabs are being restored
        gTabDeque.handleTabListeners(gBrowser.selectedTab);
    },

    onClose: function() {
        // we don't want the mimic to be restored after restart...
        if (gTabDeque.allTabsMinimizedMimic) {
            // we need at least one tab unminimized, otherwise the mimic would
            // be restored right away
            gTabDeque.maximizeNextMinimizedTab();
            gBrowser.unpinTab(gTabDeque.allTabsMinimizedMimic);
            gBrowser.removeTab(gTabDeque.allTabsMinimizedMimic);
        }
    },

    onUnload: function() {
        window.removeEventListener('unload', gTabDeque.onUnload, false);
        window.removeEventListener('close', gTabDeque.onClose, false);
        gBrowser.tabContainer.removeEventListener("TabOpen", gTabDeque.onTabOpen, false);
        gBrowser.tabContainer.removeEventListener("TabSelect", gTabDeque.onTabSelect, false);
        gBrowser.tabContainer.removeEventListener("TabClose", gTabDeque.onTabClose, false);

        gTabDeque.handleTabListeners(undefined);
    },

    onTabOpen: function(anEvent) {
        if (!gTabDeque.mimickingAllTabMinimized) {
            var tab = anEvent.target;
            // can't check whether tab is being opened in background - start at
            // beginning and move to end of deque in onTabSelect if necessary
            gTabDeque.moveTabToDequeBeginning(tab);
            gBrowser.moveTabTo(tab, gBrowser.mCurrentTab.nextSibling._tPos);
        }
    },

    onTabSelect: function(anEvent) {
        gTabDeque.handleTabListeners(anEvent.target)
        // TabSelect is triggered when opening the mimic the first time and
        // when closing the last not minimized tab, but we don't want to add it
        // to the deque
        if (!gTabDeque.mimickingAllTabMinimized &&
            anEvent.target !== gTabDeque.allTabsMinimizedMimic) {
            gTabDeque.moveTabToDequeEnd(anEvent.target);
        }
        if (anEvent.target === gTabDeque.allTabsMinimizedMimic) {
            document.getElementById('nav-bar').collapsed = true;
        } else {
            document.getElementById('nav-bar').collapsed = false;
        }
    },

    handleTabListeners: function(tab) {
        if (gTabDeque.currentlySelectedTab) {
            gTabDeque.currentlySelectedTab.removeEventListener("mousedown", gTabDeque.onSelectedTabMouseDown, false);
            gTabDeque.currentlySelectedTab.removeEventListener("mouseup", gTabDeque.onSelectedTabMouseUp, false);
        }
        if (tab){
            gTabDeque.currentlySelectedTab = tab
            gTabDeque.currentlySelectedTab.hasMouseDown = false
            // have to split this up, otherwise click would be triggered even
            // on freshly selected tab
            gTabDeque.currentlySelectedTab.addEventListener("mousedown", gTabDeque.onSelectedTabMouseDown, false);
            gTabDeque.currentlySelectedTab.addEventListener("mouseup", gTabDeque.onSelectedTabMouseUp, false);
        }
    },

    onSelectedTabMouseDown: function(anEvent) {
        var tab = anEvent.target;
        if (anEvent.button == 0) {
            tab.hasMouseDown = true;
        }
    },

    onSelectedTabMouseUp: function(anEvent) {
        var tab = anEvent.target;
        if (tab.hasMouseDown && anEvent.button == 0) {
            gTabDeque.ensureInitialization();
            gTabDeque.minimizeTab(anEvent.target);
            tab.hasMouseDown = false;
        }
    },

    onTabClose: function(anEvent) {
        var closingTab = anEvent.target;
        gTabDeque.ensureInitialization();
        gTabDeque.removeTabFromDeque(closingTab);
        if (gTabDeque.deque.length == 0 && gBrowser.tabs.length <= 2) {
            // there aren't any minimized tabs
            gTabDeque.openTab();
        } else if (gTabDeque.deque.length == 0) {
            gTabDeque.mimicAllTabsMinimized();
        } else {
            if (closingTab.selected) {
                var currentIndex = gTabDeque.getTabIndex(closingTab);
                var nextIndex = gTabDeque.getTabIndex(gTabDeque.getNextTab());
                // the closing tab is still there when calculating the index,
                // but not when selecting
                var adjustment = currentIndex < nextIndex ? -1 : 0;
                gBrowser.selectTabAtIndex(nextIndex + adjustment);
            }
        }
    },

    minimizeCurrentTab: function() {
        gTabDeque.minimizeTab(gBrowser.selectedTab);
    },

    minimizeTab: function(tab) {
        gTabDeque.removeTabFromDeque(tab);
        if (gTabDeque.deque.length == 0) {
            gTabDeque.mimicAllTabsMinimized();
        } else {
            var nextTabIndex = gTabDeque.getTabIndex(gTabDeque.getNextTab());
            gBrowser.selectTabAtIndex(nextTabIndex);
        }
    },

    maximizeNextMinimizedTab: function() {
        for (var tabIndex = 0; tabIndex < gBrowser.tabs.length; tabIndex++) {
            visibleTab = gBrowser.tabs[tabIndex];
            if (visibleTab != gTabDeque.allTabsMinimizedMimic &&
                gTabDeque.deque.indexOf(visibleTab) == -1
                ) {
                gBrowser.selectTabAtIndex(gTabDeque.getTabIndex(visibleTab));
                return;
            }
        }
    },

    openTab: function(anEvent) {
        var preferences = Components
            .classes['@mozilla.org/preferences-service;1']
            .getService(Components.interfaces.nsIPrefBranch);
        var url = preferences.getCharPref("browser.newtab.url");
        return gBrowser.loadOneTab(url, null, null, null, false, false);
    },

    abortNonReloads: function(aRequest, tabURI) {
        if (aRequest.originalURI.asciiSpec != tabURI.asciiSpec) {
            aRequest.cancel(Components.results.NS_BINDING_ABORTED);
            gBrowser.loadOneTab(aRequest.name, null, null, null, false, false);
        }
    },

    letTabOpenLinksInNewTab: function(tab) {
        var progressListener = {
            onStateChange: function(
                    aBrowser, aWebProgress, aRequest, aStateFlags, aStatus){
                // abort at the very beginning
                if (aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
                    aBrowser === gBrowser.getBrowserForTab(tab)
                    ) {
                    var tabURI = gBrowser.getBrowserForTab(tab).currentURI;
                    gTabDeque.abortNonReloads(aRequest, tabURI);
                }
            }
        }
        // don't listen on given tab's browser directly as then, the given
        // request doesn't contain all necessary information
        gBrowser.addTabsProgressListener(
            progressListener,
            Components.interfaces.nsIWebProgress.NOTIFY_STATE
        );
    },

    mimicAllTabsMinimized: function() {
        if (!gTabDeque.allTabsMinimizedMimic) {
            gTabDeque.mimickingAllTabMinimized = true;
            gTabDeque.allTabsMinimizedMimic = gTabDeque.openTab();
            gTabDeque.letTabOpenLinksInNewTab(gTabDeque.allTabsMinimizedMimic);
            gTabDeque.mimickingAllTabMinimized = false;
            gTabDeque.allTabsMinimizedMimic.collapsed = true;
            gTabDeque.allTabsMinimizedMimic.disabled = true;
            gBrowser.pinTab(gTabDeque.allTabsMinimizedMimic);
            document.getElementById('nav-bar').collapsed = true;
        } else {
            var mimicIndex =
                gTabDeque.getTabIndex(gTabDeque.allTabsMinimizedMimic);
            gBrowser.selectTabAtIndex(mimicIndex);
        }
    },

    moveTabToDequeBeginning: function(tab) {
        gTabDeque.ensureInitialization();
        // getting duplicates sometimes...
        gTabDeque.removeTabFromDeque(tab);
        gTabDeque.deque.unshift(tab);
    },

    moveTabToDequeEnd: function(tab) {
        gTabDeque.ensureInitialization();
        // getting duplicates sometimes...
        gTabDeque.removeTabFromDeque(tab);
        gTabDeque.deque.push(tab);
    },

    // can't be sure that events are fired for all tabs on startup
    // tabs are missing if initialized too early, use this before first access
    ensureInitialization: function() {
        if (!gTabDeque.deque) {
            gTabDeque.initDeque();
        }
    },

    initDeque: function() {
        gTabDeque.deque = new Array();
        for (var tabIndex = 0; tabIndex < gBrowser.tabs.length; tabIndex++) {
            gTabDeque.deque.push(gBrowser.tabs[tabIndex]);
        }
        return gTabDeque.deque;
    },

    removeTabFromDeque: function(tab) {
        var dequeIndex = gTabDeque.deque.indexOf(tab)
        if (gTabDeque.deque.indexOf(tab) >= 0) {
            gTabDeque.deque.splice(gTabDeque.deque.indexOf(tab), 1);
        }
    },

    getTabIndex: function(givenTab) {
        for (var tabIndex = 0; tabIndex < gBrowser.tabs.length; tabIndex++) {
            if (gBrowser.tabs[tabIndex] === givenTab) {
                return tabIndex;
            }
        }
        return -1;
    },

    getNextTab: function() {
        return gTabDeque.deque[gTabDeque.deque.length - 1];
    },

    // for debugging
    getDequeURLs: function() {
        var urls = new Array();
        var length = gTabDeque.deque.length
        for (var tabIndex = 0; tabIndex < gTabDeque.deque.length; tabIndex++) {
            urls.push(gTabDeque.getTabURL(gTabDeque.deque[tabIndex]));
        }
        return urls;
    },

    getTabURL: function(tab) {
        var browser = gBrowser.getBrowserForTab(tab);
        return browser.currentURI.spec;
    }
};

window.addEventListener('load', gTabDeque.onLoad, false);

<|endoftext|>


<commit_before>describe("inject-pattern", function() {
    var pattern;

    requireDependencies(["patterns/inject"], function(cls) {
        pattern = cls;
    });

    beforeEach(function() {
        $("
", {id: "lab"}).appendTo(document.body);
    });

    afterEach(function() {
        $("#lab").remove();
    });

    describe("Functional tests", function() {

        describe("extract/verifyConfig", function() {
            var $a, $target;

            beforeEach(function() {
                $a = $('link');
                $target = $('
');

                $("#lab").append($a).append($target);
            });

            it("fall back to href id", function() {
                var cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs.length).toBe(1);
                expect(cfgs[0].source).toBe('#someid');
                expect(cfgs[0].target).toBe('#someid');
            });

            it("take first positional option as source and target", function() {
                var cfgs;

                $a.attr('data-pat-inject', '#otherid');
                $target.attr('id', 'otherid');
                cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs[0].source).toBe('#otherid');
                expect(cfgs[0].target).toBe('#otherid');
            });

            it("take two positional options as source and target resp.", function() {
                var cfgs;

                $a.attr('data-pat-inject', '#otherid #yetanotherid');
                $target.attr('id', 'yetanotherid');
                cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs[0].source).toBe('#otherid');
                expect(cfgs[0].target).toBe('#yetanotherid');
            });

            it("create target if it doesn't exist", function() {
                var cfgs = pattern.extractConfig($a);

                $target.remove();
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                $target = $('#someid');
                this.after(function() { $target.remove(); });
                expect($target.length).toBeGreaterThan(0);
                expect($target.parent().prop('tagName')).toBe('BODY');
            });
        });
    });

    describe("DOM tests", function() {
        var answer = function(html) {
            expect($.ajax).toHaveBeenCalled();
            $.ajax.mostRecentCall.args[0]['success'](html, "ok", { responseText: html });
        };

        beforeEach(function() {
            spyOn($, "ajax");
        });

        describe("inject on anchor", function() {
            var $a, $div;

            beforeEach(function() {
                $a = $('link');
                $div = $('
');
                $("#lab").append($a).append($div);
            });

            it("fetches url on click", function() {
                pattern.init($a);

                $a.trigger("click");

                expect($.ajax).toHaveBeenCalled();
                expect($.ajax.mostRecentCall.args[0]['url']).toBe("test.html");
            });

            it("injects into existing div", function() {
                pattern.init($a);
                $a.trigger("click");
                answer('
replacement
');

                expect($div.html()).toBe("replacement");
            });

            it("injects multiple times", function() {
                pattern.init($a);
                $a.trigger("click");
                answer('
replacement
');
                expect($div.html()).toBe("replacement");

                $a.trigger("click");
                answer('
new replacement
');
                expect($div.html()).toBe("new replacement");
            });

            it("takes multiple source-target pairs", function() {
                $a.attr("data-pat-inject", "#someid1 #otherid1 && #someid2 #otherid2");
                $target1 = $('
');
                $target2 = $('
');
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl1
'
                       + '
repl2
'
                       + '');

                expect($target1.html()).toBe("repl1");
                expect($target2.html()).toBe("repl2");
            });

            it("acts on other selectors as well", function() {
                $a.attr("data-pat-inject", "target: #someid > .someclass");
                $target1 = $('
');
                $target2 = $('
');
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl
'
                       + '');

                expect($target1.html()).toBe("repl");
                expect($target2.html()).toBe("repl");
            });

            it("sets/unsets load class 'injecting'", function() {
                var callback = jasmine.createSpy("patterns-injected");
                $(document).on("patterns-injected", callback);

                pattern.init($a);
                $a.trigger("click");

                expect($div.hasClass("injecting")).toBeTruthy();

                answer(''
                       + '
repl
'
                       + '');

                // XXX: fails, probably due to misuse of jasmine (on
                // patterns demo page the injecting classes are
                // removed after a successful inject

                // expect($div.hasClass("injecting")).toBeFalsy();
                // expect(callback).toHaveBeenCalled();
            });

            it("copies into target if source has ::element", function() {
                $a.attr("data-pat-inject", "#otherid::element #someid");

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl
'
                       + '');

                expect($div.children().attr("id")).toBe("otherid");
                expect($div.children().attr("class")).toBe("someclass");
            });

            it("replaces target if both selectors have ::element", function() {
                $a.attr("data-pat-inject", "#someid::element #otherid::element");
                $div.append($('
'));

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl
'
                       + '');

                expect($div.children().attr("id")).toBe("someid");
                expect($div.children().attr("class")).toBe("someclass");
            });

            it("allows ::before and ::after in target selector", function() {
                $a.attr("data-pat-inject", "target: #target1::after && target: #target2::before");
                $target1 = $('
content
');
                $target2 = $('
content
');
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl
'
                       + '');

                expect($target1.html()).toBe("contentrepl");
                expect($target2.html()).toBe("replcontent");
            });

            it("allows mixing ::element and ::after in target", function() {
                $a.attr("data-pat-inject", "target: #otherid::element::after");
                $div.append($('
'));

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl
'
                       + '');

                expect($div.contents().last().text()).toBe("repl");
            });
        });

        describe("inject on forms", function() {
            var $form, $div;

            beforeEach(function() {
                $form = $('<form class="pat-inject" action="test.html#someid" />');
                $div = $('
');
                $("#lab").append($form).append($div);
            });

            it("trigger injection on submit", function() {
                pattern.init($form);
                $form.trigger('submit');
                answer(''
                       + '
repl
'
                       + '');

                expect($div.html()).toBe("repl");
            });

            it("pass get form parameters in ajax call as data", function() {
                $form.attr('method', 'get');
                $form.append($('<input type="text" name="param" value="somevalue" />'));

                pattern.init($form);
                $form.trigger('submit');

                expect($.ajax).toHaveBeenCalled();
                expect($.ajax.mostRecentCall.args[0].data).toContain('param=somevalue');
            });

            it("pass post form parameters in ajax call as data", function() {
                $form.attr('method', 'post');
                $form.append($('<input type="text" name="param" value="somevalue" />'));

                pattern.init($form);
                $form.trigger('submit');

                expect($.ajax).toHaveBeenCalled();
                expect($.ajax.mostRecentCall.args[0].data).toContain('param=somevalue');
            });
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>make tests/inject.js lint free<commit_after>describe("inject-pattern", function() {
    var pattern;

    requireDependencies(["patterns/inject"], function(cls) {
        pattern = cls;
    });

    beforeEach(function() {
        $("
", {id: "lab"}).appendTo(document.body);
    });

    afterEach(function() {
        $("#lab").remove();
    });

    describe("Functional tests", function() {

        describe("extract/verifyConfig", function() {
            var $a, $target;

            beforeEach(function() {
                $a = $("link");
                $target = $("
");

                $("#lab").append($a).append($target);
            });

            it("fall back to href id", function() {
                var cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs.length).toBe(1);
                expect(cfgs[0].source).toBe("#someid");
                expect(cfgs[0].target).toBe("#someid");
            });

            it("take first positional option as source and target", function() {
                var cfgs;

                $a.attr("data-pat-inject", "#otherid");
                $target.attr("id", "otherid");
                cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs[0].source).toBe("#otherid");
                expect(cfgs[0].target).toBe("#otherid");
            });

            it("take two positional options as source and target resp.", function() {
                var cfgs;

                $a.attr("data-pat-inject", "#otherid #yetanotherid");
                $target.attr("id", "yetanotherid");
                cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs[0].source).toBe("#otherid");
                expect(cfgs[0].target).toBe("#yetanotherid");
            });

            it("create target if it doesn't exist", function() {
                var cfgs = pattern.extractConfig($a);

                $target.remove();
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                $target = $("#someid");
                this.after(function() { $target.remove(); });
                expect($target.length).toBeGreaterThan(0);
                expect($target.parent().prop("tagName")).toBe("BODY");
            });
        });
    });

    describe("DOM tests", function() {
        var answer = function(html) {
            expect($.ajax).toHaveBeenCalled();
            $.ajax.mostRecentCall.args[0].success(html, "ok", { responseText: html });
        };

        beforeEach(function() {
            spyOn($, "ajax");
        });

        describe("inject on anchor", function() {
            var $a, $div;

            beforeEach(function() {
                $a = $("link");
                $div = $("
");
                $("#lab").append($a).append($div);
            });

            it("fetches url on click", function() {
                pattern.init($a);

                $a.trigger("click");

                expect($.ajax).toHaveBeenCalled();
                expect($.ajax.mostRecentCall.args[0].url).toBe("test.html");
            });

            it("injects into existing div", function() {
                pattern.init($a);
                $a.trigger("click");
                answer("
replacement
");

                expect($div.html()).toBe("replacement");
            });

            it("injects multiple times", function() {
                pattern.init($a);
                $a.trigger("click");
                answer("
replacement
");
                expect($div.html()).toBe("replacement");

                $a.trigger("click");
                answer("
new replacement
");
                expect($div.html()).toBe("new replacement");
            });

            it("takes multiple source-target pairs", function() {
                $a.attr("data-pat-inject", "#someid1 #otherid1 && #someid2 #otherid2");
                var $target1 = $("
"),
                    $target2 = $("
");
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer("" +
                       "
repl1
" +
                       "
repl2
" +
                       "");

                expect($target1.html()).toBe("repl1");
                expect($target2.html()).toBe("repl2");
            });

            it("acts on other selectors as well", function() {
                $a.attr("data-pat-inject", "target: #someid > .someclass");
                var $target1 = $("
"),
                    $target2 = $("
");
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer("" +
                       "
repl
" +
                       "");

                expect($target1.html()).toBe("repl");
                expect($target2.html()).toBe("repl");
            });

            it("sets/unsets load class 'injecting'", function() {
                var callback = jasmine.createSpy("patterns-injected");
                $(document).on("patterns-injected", callback);

                pattern.init($a);
                $a.trigger("click");

                expect($div.hasClass("injecting")).toBeTruthy();

                answer("" +
                       "
repl
" +
                       "");

                // XXX: fails, probably due to misuse of jasmine (on
                // patterns demo page the injecting classes are
                // removed after a successful inject

                // expect($div.hasClass("injecting")).toBeFalsy();
                // expect(callback).toHaveBeenCalled();
            });

            it("copies into target if source has ::element", function() {
                $a.attr("data-pat-inject", "#otherid::element #someid");

                pattern.init($a);
                $a.trigger("click");
                answer("" +
                       "
repl
" +
                       "");

                expect($div.children().attr("id")).toBe("otherid");
                expect($div.children().attr("class")).toBe("someclass");
            });

            it("replaces target if both selectors have ::element", function() {
                $a.attr("data-pat-inject", "#someid::element #otherid::element");
                $div.append($("
"));

                pattern.init($a);
                $a.trigger("click");
                answer("" +
                       "
repl
" +
                       "");

                expect($div.children().attr("id")).toBe("someid");
                expect($div.children().attr("class")).toBe("someclass");
            });

            it("allows ::before and ::after in target selector", function() {
                $a.attr("data-pat-inject", "target: #target1::after && target: #target2::before");
                var $target1 = $("
content
"),
                    $target2 = $("
content
");
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer("" +
                       "
repl
" +
                       "");

                expect($target1.html()).toBe("contentrepl");
                expect($target2.html()).toBe("replcontent");
            });

            it("allows mixing ::element and ::after in target", function() {
                $a.attr("data-pat-inject", "target: #otherid::element::after");
                $div.append($("
"));

                pattern.init($a);
                $a.trigger("click");
                answer("" +
                       "
repl
" +
                       "");

                expect($div.contents().last().text()).toBe("repl");
            });
        });

        describe("inject on forms", function() {
            var $form, $div;

            beforeEach(function() {
                $form = $("<form class=\"pat-inject\" action=\"test.html#someid\" />");
                $div = $("
");
                $("#lab").append($form).append($div);
            });

            it("trigger injection on submit", function() {
                pattern.init($form);
                $form.trigger("submit");
                answer("" +
                       "
repl
" +
                       "");

                expect($div.html()).toBe("repl");
            });

            it("pass get form parameters in ajax call as data", function() {
                $form.attr("method", "get");
                $form.append($("<input type=\"text\" name=\"param\" value=\"somevalue\" />"));

                pattern.init($form);
                $form.trigger("submit");

                expect($.ajax).toHaveBeenCalled();
                expect($.ajax.mostRecentCall.args[0].data).toContain("param=somevalue");
            });

            it("pass post form parameters in ajax call as data", function() {
                $form.attr("method", "post");
                $form.append($("<input type=\"text\" name=\"param\" value=\"somevalue\" />"));

                pattern.init($form);
                $form.trigger("submit");

                expect($.ajax).toHaveBeenCalled();
                expect($.ajax.mostRecentCall.args[0].data).toContain("param=somevalue");
            });
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>"use strict";

import React from "react";
import store from "./redux/store";
import ContextMenuContainer from "./menu-container";

let { PropTypes } = React;

const ContextMenu = React.createClass({
    displayName: "ContextMenu",
    propTypes: {
        identifier: PropTypes.string.isRequired
    },
    childContextTypes: {
        store: PropTypes.object
    },
    getInitialState() {
        return store.getState();
    },
    getChildContext() {
        return {
            store
        };
    },
    componentDidMount() {
        this.unsubscribe = store.subscribe(this.handleUpdate);
    },
    componentWillUnmount() {
        if (this.unsubscribe) this.unsubscribe();
    },
    handleUpdate() {
        this.setState(this.getInitialState());
    },
    render() {
        return (
            <ContextMenuContainer {...this.props} {...this.state}/>
        );
    }
});

export default ContextMenu;
<commit_msg>remove context usage<commit_after>"use strict";

import React from "react";
import store from "./redux/store";
import ContextMenuContainer from "./menu-container";

let { PropTypes } = React;

const ContextMenu = React.createClass({
    displayName: "ContextMenu",
    propTypes: {
        identifier: PropTypes.string.isRequired
    },
    getInitialState() {
        return store.getState();
    },
    componentDidMount() {
        this.unsubscribe = store.subscribe(this.handleUpdate);
    },
    componentWillUnmount() {
        if (this.unsubscribe) this.unsubscribe();
    },
    handleUpdate() {
        this.setState(this.getInitialState());
    },
    render() {
        return (
            <ContextMenuContainer {...this.props} {...this.state}/>
        );
    }
});

export default ContextMenu;
<|endoftext|>


<commit_before>'use strict';

var TYPES = require('../parsers').TYPES;
var valueType = require('../parsers').valueType;

var partsRegEx = /\s*,\s*/;
module.exports.isValid = function isValid(v) {
    var parts = v.split(partsRegEx);
    var len = parts.len;
    var i;
    var type;
    for (i = 0; i < len; i++) {
        type = valueType(parts[i]);
        if (type === TYPES.STRING || type === TYPES.KEYWORD) {
            return true;
        }
    }
    return false;
};

module.exports.definition = {
    set: function (v) {
        this._setProperty('font-family', v);
    },
    get: function () {
        return this.getPropertyValue('font-family');
    },
    enumerable: true,
    configurable: true
};
<commit_msg>Fixed length type<commit_after>'use strict';

var TYPES = require('../parsers').TYPES;
var valueType = require('../parsers').valueType;

var partsRegEx = /\s*,\s*/;
module.exports.isValid = function isValid(v) {
    var parts = v.split(partsRegEx);
    var len = parts.length;
    var i;
    var type;
    for (i = 0; i < len; i++) {
        type = valueType(parts[i]);
        if (type === TYPES.STRING || type === TYPES.KEYWORD) {
            return true;
        }
    }
    return false;
};

module.exports.definition = {
    set: function (v) {
        this._setProperty('font-family', v);
    },
    get: function () {
        return this.getPropertyValue('font-family');
    },
    enumerable: true,
    configurable: true
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

module.exports = function(context) {
  throw new Error('Check AllowBacup plugin start work');
  var fs = context.requireCordovaModule('fs'),
    path = context.requireCordovaModule('path');

  var platformRoot = path.join(context.opts.projectRoot, 'platforms/android');

  var manifestFile = path.join(platformRoot, 'AndroidManifest.xml');

  if (fs.existsSync(manifestFile)) {

    fs.readFile(manifestFile, 'utf8', function (err,data) {
      if (err) {
        throw new Error('Unable to find AndroidManifest.xml: ' + err);
      }
      var appClass = ' android:allowBackup="true" ';
      if (data.indexOf(appClass) == -1) {
        var result = data.replace(/<application/g, '<application ' + appClass);
        fs.writeFile(manifestFile, result, 'utf8', function (err) {
          if (err) throw new Error('Unable to write into AndroidManifest.xml: ' + err);
        })
      }
    });
  }

};
<commit_msg>Update androidBeforeInstall.js<commit_after>module.exports = function(ctx) {
  var fs = ctx.requireCordovaModule('fs'),
  path = ctx.requireCordovaModule('path'),
  xml = ctx.requireCordovaModule('cordova-common').xmlHelpers;

 var manifestPath = path.join(ctx.opts.projectRoot, 'platforms/android/AndroidManifest.xml');
 var doc = xml.parseElementtreeSync(manifestPath);
 if (doc.getroot().tag !== 'manifest') {
    throw new Error(manifestPath + ' has incorrect root node name (expected "manifest")');
 }

 doc.getroot().find('./application').attrib['android:allowBackup'] = "false";

 //write the manifest file
 fs.writeFileSync(manifestPath, doc.write({
    indent: 4
 }), 'utf-8');
};
<|endoftext|>