<commit_before>/*!
 * benchmark.js
 * Copyright Mathias Bynens <http://mths.be/>
 * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
 * Modified by John-David Dalton <http://allyoucanleet.com/>
 * Available under MIT license <http://mths.be/mit>
 */

(function(global) {

  // MAX_COUNT divisors used to avoid hz of Infinity
  var CYCLE_DIVISORS = { '1': 8, '2': 6, '3': 4, '4': 2, '5': 1 };

  /*--------------------------------------------------------------------------*/

  function Benchmark(fn, options) {
    options = extend({ }, options);
    extend(this, options);
    this.fn = fn;
    this.options = options;
  }

  function Calibration(fn, options) {
    Benchmark.call(this, fn, options);
  }

  function Klass() { }

  Klass.prototype = Benchmark.prototype;

  (function(proto) {
    // bypass calibrating the Calibration tests
    function run(count, synchronous) {
      var me = this;
      me.reset();
      me.running = true;
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
    proto.constructor = Calibration;
    proto.run = run;
  }(Calibration.prototype = new Klass));

  /*--------------------------------------------------------------------------*/

  // fires callback after calibration or returns false
  function calibrate(callback) {
    var cal = Benchmark.CALIBRATION;
    if (!cal.cycles) {
      cal.onComplete = callback;
      cal.average();
      return true;
    }
    return false;
  }

  // call method sync or async (to allow UI redraws)
  function call(me, callback, synchronous) {
    synchronous
      ? callback(me, synchronous)
      : setTimeout(function() { callback(me); }, me.CYCLE_DELAY * 1e3);
  }

  // merge source results with destinations
  function merge(destination, source) {
    destination.count = source.count;
    destination.cycles += source.cycles;
    destination.error = source.error;
    destination.hz = source.hz;
    destination.period = source.period;
    return destination;
  }

  // copies source properties to destination object
  function extend(destination, source) {
    source || (source = { });
    for (var key in source) {
      destination[key] = source[key];
    }
    return destination;
  }

  // generic Array#filter
  function filter(array, callback) {
    var length = array.length,
        result = [];

    while (length--) {
      if (length in array && callback(array[length], length, array)) {
        result.unshift(array[length]);
      }
    }
    return result;
  }

  // generic Array#reduce
  function reduce(array, callback, accumulator) {
    var length = array.length;
    while (length--) {
      if (length in array) {
        accumulator = callback(accumulator, array[length], length, array);
      }
    }
    return accumulator;
  }

  /*--------------------------------------------------------------------------*/

  // clock the time it takes to execute a function N times (milliseconds)
  var clock;

  // variable names are prefixed with $ to replace during compilation
  (function() {

    var interval = Function('$m,$c',
          'var $i=$m.count,$f=$m.fn,$t=new $c.Interval;' +
          '$t.start();while($i--){$f()}$t.stop();' +
          '$m.time=$t.microseconds()/1e3'),

        now = Function('$m',
          'var $i=$m.count,$f=$m.fn,$t=Date.now();' +
          'while($i--){$f()}' +
          '$m.time=Date.now()-$t'),

        time = Function('$m',
          'var $i=$m.count,$f=$m.fn,$t=(new Date).getTime();' +
          'while($i--){$f()}' +
          '$m.time=(new Date).getTime()-$t'),

        // create a new function with fn's body embedded into $clock's while-loop
        embed = function(fn) {
          var snippet = String(fn).match(/^[^{]+{([\s\S]*)}\s*$/);
          return Function(fnArg, fnBody.replace(fnToken, snippet && snippet[1]));
        },

        // enable benchmarking via the --enable-benchmarking flag
        // in at least Chrome 7 to use chrome.Interval
        $c = typeof global.chrome != 'undefined' ? chrome :
          typeof global.chromium != 'undefined' ? chromium : null,

        // choose which timing api to use
        $clock = ($c && typeof $c.Interval == 'function') ? interval :
          (typeof Date.now == 'function') ? now : time,

        // used for method compilation
        uid     = +new Date,
        fnToken = '$f' + uid + '()',
        fnArg   = '$m' + uid + ',$c' + uid,
        fnBody  = ('return(' + String($clock).replace('anonymous', '') +
                  ')($m,$c)').replace(/(\$[a-z])/g, '$1' + uid);

    // if supported, compile tests to avoid extra function calls
    if (function() {
          try { return embed(function() { return 1; })({ 'count': 1 }, $c); } catch(e) { }
        }()) {

      clock = function(me) {
        var error;
        try {
          embed(me.fn)(me, $c);
        } catch(e) {
          error = 1;
        }
        if (error) {
          $clock(me, $c);
        }
      };
    }
    else {
      clock = function(me) {
        $clock(me, $c);
      };
    }
  }());

  /*--------------------------------------------------------------------------*/

  function getPlatform() {
    var build,
        description = [],
        ua = navigator.userAgent,
        os = (ua.match(/(?:Windows 98;|Windows |iP[ao]d|iPhone|Mac OS X|Linux)(?:[^);]| )*/) || [])[0],
        name = (ua.match(/Chrome|MSIE|Safari|Opera|Firefox|Minefield/) || [])[0],
        version = {}.toString.call(global.opera) == '[object Opera]' && opera.version(),
        mses = { '6.1': '7', '6.0': 'Vista', '5.2': 'Server 2003 / XP x64', '5.1': 'XP', '5.0': '2000', '4.0': 'NT', '4.9': 'ME' };

    // IE platform tokens
    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
    mses = os && os.indexOf('Windows') > -1 && mses[(os.match(/[456]\.\d/) || [])[0]];
    if (mses) {
      os = 'Windows ' + mses;
    } else if (/iP[ao]d|iPhone/.test(os)) {
      os = (ua.match(/\bOS ([\d_]+)/) || [])[1];
      os = 'iOS' + (os ? ' ' + os : '');
    }
    // detect non Opera versions
    if (!version) {
      version = typeof document.documentMode == 'number'
        ? document.documentMode
        : (ua.match(RegExp('(?:version|' + name + ')[ /]([^ ;]*)', 'i')) || [])[1];
    }
    // detect early Safari versions
    if (parseInt(version) > 45) {
      build = (ua.match(/AppleWebKit\/(\d+)/) || [])[1] || Infinity;
      version = build < 400 ? '1.x' : build < 500 ? '2.x' : version;
    }
    return {
      'name':        name ? description.push(name) && name : null,
      'version':     name && version ? description.push(version) && version : null,
      'os':          os ? description.push('on ' + (os = os.replace(/_/g, '.'))) && os : null,
      'description': description.length ? description.join(' ') : 'unknown platform',
      'toString':    function() { return this.description; }
    };
  }

  /*--------------------------------------------------------------------------*/

  function average(times, count, synchronous) {
    var deviation,
        mean,
        stopped,
        me = this,
        clones = [],
        i = times || (times = me.DEFAULT_AVERAGE);

    function cbSum(sum, clone) {
      return sum + clone.period;
    }

    function cbVariance(sum, clone) {
      return sum + Math.pow(clone.period - mean, 2);
    }

    function cbOutlier(clone) {
      return clone.period < (mean + deviation) && clone.period > (mean - deviation);
    }

    function onCycle(clone) {
      // stop clone and raise flag if host has stopped running
      if (stopped = !me.running) {
        clone.stop();
      } else {
        // update host and fire its onCycle callback
        me.onCycle(merge(me, clone));
      }
    }

    function onComplete(clone) {
      // if host has stopped or this is the last clone to finish
      if (stopped || !--times) {
        if (!stopped && !me.error) {
          // compute average period and sample standard deviation
          mean = reduce(clones, cbSum, 0) / clones.length;
          deviation = Math.sqrt(reduce(clones, cbVariance, 0) / (clones.length - 1));

          if (deviation) {
            // remove outliers and compute average period on filtered results
            clones = filter(clones, cbOutlier);
            mean = reduce(clones, cbSum, 0) / clones.length;
          }
          // set host results
          me.count = clones[0].count;
          me.hz = mean ? Math.round(1 / mean) : Number.MAX_VALUE;
          me.period = mean;
          me.time = mean * me.count;
        }
        me.running = false;
        me.onCycle(me);
        me.onComplete(me);
      }
      else if (!synchronous) {
        // run next clone in the sample
        clone = clones[times];
        call(clone, function() { clone.run(); });
      }
    }

    me.reset();
    me.running = true;
    me.onStart(me);

    while (i--) {
      // create clone and add to sample
      clones.push(me.clone({
        'averaging': true,
        'onStart': onCycle,
        'onCycle': onCycle,
        'onComplete': onComplete
      }));
      // run instantly if synchronous or initiate asynchronous averaging
      if (synchronous || !i) {
        clones[clones.length - 1].run(count, synchronous);
      }
    }
  }

  /*--------------------------------------------------------------------------*/

  function clone(options) {
    var key,
        me = this,
        result = new me.constructor(me.fn, extend(extend({ }, me.options), options));

    // copy manually added properties
    for (key in me) {
      if (!result[key]) {
        result[key] = me[key];
      }
    }
    result.reset();
    return result;
  }

  function noop() {
    // no operation performed
  }

  function stop() {
    var me = this,
        cal = Benchmark.CALIBRATION,
        error = me.error;

    if (me.running) {
      if (me != cal && cal.running) {
        cal.stop();
      }
      me.reset();
      me.error = error;
      me.onStop(me);
    }
  }

  function reset() {
    var me = this,
        proto = this.constructor.prototype;

    me.count = proto.count;
    me.cycles = proto.cycles;
    me.error = proto.error;
    me.hz = proto.hz;
    me.period = proto.period;
    me.running = proto.running;
    me.time = proto.time;
    me.onReset(me);
  }

  function run(count, synchronous) {
    var me = this;
    me.reset();
    me.running = true;

    // ensure calibration test has run
    if (!calibrate(function() {
          function rerun() {
            // continue, if not stopped during calibration
            if (me.running) {
              me.run(count, synchronous);
            } else {
              me.onStart(me);
              me.onStop(me);
              me.onComplete(me);
            }
          }
          call(me, rerun, synchronous);
        })) {
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
  }

  function _run(me, synchronous) {
    var divisor,
        period,
        time,
        cal = me.constructor.CALIBRATION,
        count = me.count,
        cycles = me.cycles,
        maxCount = me.MAX_COUNT,
        minTime = me.MIN_TIME;

    // continue, if not stopped between cycles
    if (me.running) {

      if (cycles) {
        cycles = ++me.cycles;
      } else {
        cycles = me.cycles = 1;
      }
      try {
        // clock executions of me.fn
        clock(me);

        time = me.time =
          // ensure positive numbers
          Math.max(0,
          // convert time from milliseconds to seconds
          (me.time / 1e3) -
          // calibrate by subtracting the base loop time
          (cal && cal.period || 0) * count);

        // per-operation time
        period = me.period = time / count;

        // ops per second
        me.hz = period ? Math.round(1 / period) : Number.MAX_VALUE;

        // do we need to do another cycle?
        me.running = time < minTime;

        // if so, compute the iteration count needed
        if (me.running) {
          // tests may return an initial time of 0 when INIT_COUNT is a small number,
          // to avoid that we set its count to something a bit higher
          if (!time && (divisor = CYCLE_DIVISORS[cycles])) {
            // try a fraction of the MAX_COUNT
            count = Math.floor(maxCount / divisor);
          }
          else {
            // calculate how many more iterations it will take to achive the min testing time
            count += Math.ceil((minTime - time) / period)

            // to avoid freezing the browser stop running if the
            // next cycle would exceed the max count allowed
            if (count > maxCount) {
              me.running = false;
            }
          }
          // update count for next cycle
          if (me.running) {
            me.count = count;
          }
        }
      }
      catch(e) {
        me.reset();
        me.error = e;
      }
      me.onCycle(me);
    }

    // figure out what to do next
    if (me.running) {
      call(me, _run, synchronous);
    }
    else if (me.averaging || me.error || (me.time * me.DEFAULT_AVERAGE) > 1) {
      me.onComplete(me);
    }
    else {
      // fast tests get their results averaged
      me.average(Math.max(me.DEFAULT_AVERAGE, Math.floor(1 / me.time)), null, synchronous);
    }
  }

  /*--------------------------------------------------------------------------*/

  // test to establish iteration loop overhead
  Benchmark.CALIBRATION = new Calibration(noop, { 'INIT_COUNT': 3e3 });

  Benchmark.getPlatform = getPlatform;

  Benchmark.noop = noop;

  extend(Benchmark.prototype, {
    // delay between test cycles (secs)
    'CYCLE_DELAY': 0.01,

    // number of runs to average
    'DEFAULT_AVERAGE': 10,

    // initial number of iterations
    'INIT_COUNT': 10,

    // max iterations allowed per cycle (used avoid locking up the browser)
    'MAX_COUNT': 1e6, // 1 million

    // minimum time a test should take to get valid results (secs)
    'MIN_TIME': 0.2,

    // number of times a test was executed
    'count': null,

    // number of cycles performed during testing
    'cycles': null,

    // an error object if the test failed
    'error': null,

    // number of test executions per second
    'hz': null,

    // time a test takes to do one execution (secs)
    'period': null,

    // flag to indicate if the test is running
    'running': false,

    // time a test takes to do the `count` number of executions (secs)
    'time': null,

    // callback invoked when testing is complete
    'onComplete': noop,

    // callback invoked when one test cycle ends
    'onCycle': noop,

    // callback invoked when test is reset
    'onReset': noop,

    // callback invoked when testing is started
    'onStart': noop,

    // callback invoked when testing is stopped
    'onStop': noop,

    // runs the test `n` times and returns the averaged test results
    'average': average,

    // create new benchmark with the same test function and options
    'clone': clone,

    // reset test state
    'reset': reset,

    // run the test
    'run': run,

    // stop testing (does not record times)
    'stop': stop
  });

  // expose
  global.Benchmark = Benchmark;

}(this));<commit_msg>benchmark.js: Add early exit detection to clock() and cleanup code. [jddalton]<commit_after>/*!
 * benchmark.js
 * Copyright Mathias Bynens <http://mths.be/>
 * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
 * Modified by John-David Dalton <http://allyoucanleet.com/>
 * Available under MIT license <http://mths.be/mit>
 */

(function(global) {

  // MAX_COUNT divisors used to avoid hz of Infinity
  var CYCLE_DIVISORS = { '1': 8, '2': 6, '3': 4, '4': 2, '5': 1 };

  /*--------------------------------------------------------------------------*/

  function Benchmark(fn, options) {
    options = extend({ }, options);
    extend(this, options);
    this.fn = fn;
    this.options = options;
  }

  function Calibration(fn, options) {
    Benchmark.call(this, fn, options);
  }

  function Klass() { }

  Klass.prototype = Benchmark.prototype;

  (function(proto) {
    // bypass calibrating the Calibration tests
    function run(count, synchronous) {
      var me = this;
      me.reset();
      me.running = true;
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
    proto.constructor = Calibration;
    proto.run = run;
  }(Calibration.prototype = new Klass));

  /*--------------------------------------------------------------------------*/

  // fires callback after calibration or returns false
  function calibrate(callback) {
    var cal = Benchmark.CALIBRATION;
    if (!cal.cycles) {
      cal.onComplete = callback;
      cal.average();
      return true;
    }
    return false;
  }

  // call method sync or async (to allow UI redraws)
  function call(me, callback, synchronous) {
    synchronous
      ? callback(me, synchronous)
      : setTimeout(function() { callback(me); }, me.CYCLE_DELAY * 1e3);
  }

  // merge source results with destinations
  function merge(destination, source) {
    destination.count = source.count;
    destination.cycles += source.cycles;
    destination.error = source.error;
    destination.hz = source.hz;
    destination.period = source.period;
    return destination;
  }

  // copies source properties to destination object
  function extend(destination, source) {
    source || (source = { });
    for (var key in source) {
      destination[key] = source[key];
    }
    return destination;
  }

  // generic Array#filter
  function filter(array, callback) {
    var length = array.length,
        result = [];

    while (length--) {
      if (length in array && callback(array[length], length, array)) {
        result.unshift(array[length]);
      }
    }
    return result;
  }

  // generic Array#reduce
  function reduce(array, callback, accumulator) {
    var length = array.length;
    while (length--) {
      if (length in array) {
        accumulator = callback(accumulator, array[length], length, array);
      }
    }
    return accumulator;
  }

  /*--------------------------------------------------------------------------*/

  // clock the time it takes to execute a function N times (milliseconds)
  var clock = (function() {
    var fallback,
        supported,
        uid = +new Date,
        args = 'm' + uid + ',c' + uid,
        code = 'var r$,i$=m$.count,f$=m$.fn,#{0};while(i$--){f$()}#{1};m$.time=r$;return"$"',
        co = typeof global.chrome != 'undefined' ? chrome : typeof global.chromium != 'undefined' ? chromium : { };

    function clock(me) {
      var errored,
          result;
      if (supported) {
        try {
          result = embed(me.fn)(me, co);
        } catch(e) {
          errored = 1;
        }
        // did test exit early?
        if (result != uid) {
          errored = 1;
        }
      }
      if (errored || !supported) {
        fallback(me, co);
      }
    }

    function embed(fn) {
      var body = String(fn).match(/^[^{]+{([\s\S]*)}\s*$/);
      return Function(args, code.replace('f' + uid + '()', body && body[1]));
    }

    // enable benchmarking via the --enable-benchmarking flag
    // in at least Chrome 7 to use chrome.Interval
    if (typeof co.Interval == 'function') {
      code = code.replace('#{0}', 't$=new c$.Interval;t$.start()')
        .replace('#{1}', 't$.stop();r$=t$.microseconds()/1e3');
    }
    else if (typeof Date.now == 'function') {
      code = code.replace('#{0}', 't$=Date.now()')
        .replace('#{1}', 'r$=Date.now()-t$');
    }
    else {
      code = code.replace('#{0}', 't$=(new Date).getTime()')
        .replace('#{1}', 'r$=(new Date).getTime()-t$');
    }

    // inject uid into variable names to avoid collisions with embedded tests
    code = code.replace(/\$/g, uid);

    // non embeding fallback
    fallback = Function(args, code);

    // is embedding supported?
    try {
      supported = embed(function() { return 1; })({ 'count': 1 }, co);
    } catch(e) { }

    return clock;
  }());

  /*--------------------------------------------------------------------------*/

  function getPlatform() {
    var build,
        description = [],
        ua = navigator.userAgent,
        os = (ua.match(/(?:Windows 98;|Windows |iP[ao]d|iPhone|Mac OS X|Linux)(?:[^);]| )*/) || [])[0],
        name = (ua.match(/Chrome|MSIE|Safari|Opera|Firefox|Minefield/) || [])[0],
        version = {}.toString.call(global.opera) == '[object Opera]' && opera.version(),
        mses = { '6.1': '7', '6.0': 'Vista', '5.2': 'Server 2003 / XP x64', '5.1': 'XP', '5.0': '2000', '4.0': 'NT', '4.9': 'ME' };

    // IE platform tokens
    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
    mses = os && os.indexOf('Windows') > -1 && mses[(os.match(/[456]\.\d/) || [])[0]];
    if (mses) {
      os = 'Windows ' + mses;
    } else if (/iP[ao]d|iPhone/.test(os)) {
      os = (ua.match(/\bOS ([\d_]+)/) || [])[1];
      os = 'iOS' + (os ? ' ' + os : '');
    }
    // detect non Opera versions
    if (!version) {
      version = typeof document.documentMode == 'number'
        ? document.documentMode
        : (ua.match(RegExp('(?:version|' + name + ')[ /]([^ ;]*)', 'i')) || [])[1];
    }
    // detect early Safari versions
    if (parseInt(version) > 45) {
      build = (ua.match(/AppleWebKit\/(\d+)/) || [])[1] || Infinity;
      version = build < 400 ? '1.x' : build < 500 ? '2.x' : version;
    }
    return {
      'name':        name ? description.push(name) && name : null,
      'version':     name && version ? description.push(version) && version : null,
      'os':          os ? description.push('on ' + (os = os.replace(/_/g, '.'))) && os : null,
      'description': description.length ? description.join(' ') : 'unknown platform',
      'toString':    function() { return this.description; }
    };
  }

  /*--------------------------------------------------------------------------*/

  function average(times, count, synchronous) {
    var deviation,
        mean,
        stopped,
        me = this,
        clones = [],
        i = times || (times = me.DEFAULT_AVERAGE);

    function cbSum(sum, clone) {
      return sum + clone.period;
    }

    function cbVariance(sum, clone) {
      return sum + Math.pow(clone.period - mean, 2);
    }

    function cbOutlier(clone) {
      return clone.period < (mean + deviation) && clone.period > (mean - deviation);
    }

    function onCycle(clone) {
      // stop clone and raise flag if host has stopped running
      if (stopped = !me.running) {
        clone.stop();
      } else {
        // update host and fire its onCycle callback
        me.onCycle(merge(me, clone));
      }
    }

    function onComplete(clone) {
      // if host has stopped or this is the last clone to finish
      if (stopped || !--times) {
        if (!stopped && !me.error) {
          // compute average period and sample standard deviation
          mean = reduce(clones, cbSum, 0) / clones.length;
          deviation = Math.sqrt(reduce(clones, cbVariance, 0) / (clones.length - 1));

          if (deviation) {
            // remove outliers and compute average period on filtered results
            clones = filter(clones, cbOutlier);
            mean = reduce(clones, cbSum, 0) / clones.length;
          }
          // set host results
          me.count = clones[0].count;
          me.hz = mean ? Math.round(1 / mean) : Number.MAX_VALUE;
          me.period = mean;
          me.time = mean * me.count;
        }
        me.running = false;
        me.onCycle(me);
        me.onComplete(me);
      }
      else if (!synchronous) {
        // run next clone in the sample
        clone = clones[times];
        call(clone, function() { clone.run(); });
      }
    }

    me.reset();
    me.running = true;
    me.onStart(me);

    while (i--) {
      // create clone and add to sample
      clones.push(me.clone({
        'averaging': true,
        'onStart': onCycle,
        'onCycle': onCycle,
        'onComplete': onComplete
      }));
      // run instantly if synchronous or initiate asynchronous averaging
      if (synchronous || !i) {
        clones[clones.length - 1].run(count, synchronous);
      }
    }
  }

  /*--------------------------------------------------------------------------*/

  function clone(options) {
    var key,
        me = this,
        result = new me.constructor(me.fn, extend(extend({ }, me.options), options));

    // copy manually added properties
    for (key in me) {
      if (!result[key]) {
        result[key] = me[key];
      }
    }
    result.reset();
    return result;
  }

  function noop() {
    // no operation performed
  }

  function stop() {
    var me = this,
        cal = Benchmark.CALIBRATION,
        error = me.error;

    if (me.running) {
      if (me != cal && cal.running) {
        cal.stop();
      }
      me.reset();
      me.error = error;
      me.onStop(me);
    }
  }

  function reset() {
    var me = this,
        proto = this.constructor.prototype;

    me.count = proto.count;
    me.cycles = proto.cycles;
    me.error = proto.error;
    me.hz = proto.hz;
    me.period = proto.period;
    me.running = proto.running;
    me.time = proto.time;
    me.onReset(me);
  }

  function run(count, synchronous) {
    var me = this;
    me.reset();
    me.running = true;

    // ensure calibration test has run
    if (!calibrate(function() {
          function rerun() {
            // continue, if not stopped during calibration
            if (me.running) {
              me.run(count, synchronous);
            } else {
              me.onStart(me);
              me.onStop(me);
              me.onComplete(me);
            }
          }
          call(me, rerun, synchronous);
        })) {
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
  }

  function _run(me, synchronous) {
    var divisor,
        period,
        time,
        cal = me.constructor.CALIBRATION,
        count = me.count,
        cycles = me.cycles,
        maxCount = me.MAX_COUNT,
        minTime = me.MIN_TIME;

    // continue, if not stopped between cycles
    if (me.running) {

      if (cycles) {
        cycles = ++me.cycles;
      } else {
        cycles = me.cycles = 1;
      }
      try {
        // clock executions of me.fn
        clock(me);

        time = me.time =
          // ensure positive numbers
          Math.max(0,
          // convert time from milliseconds to seconds
          (me.time / 1e3) -
          // calibrate by subtracting the base loop time
          (cal && cal.period || 0) * count);

        // per-operation time
        period = me.period = time / count;

        // ops per second
        me.hz = period ? Math.round(1 / period) : Number.MAX_VALUE;

        // do we need to do another cycle?
        me.running = time < minTime;

        // if so, compute the iteration count needed
        if (me.running) {
          // tests may return an initial time of 0 when INIT_COUNT is a small number,
          // to avoid that we set its count to something a bit higher
          if (!time && (divisor = CYCLE_DIVISORS[cycles])) {
            // try a fraction of the MAX_COUNT
            count = Math.floor(maxCount / divisor);
          }
          else {
            // calculate how many more iterations it will take to achive the min testing time
            count += Math.ceil((minTime - time) / period)

            // to avoid freezing the browser stop running if the
            // next cycle would exceed the max count allowed
            if (count > maxCount) {
              me.running = false;
            }
          }
          // update count for next cycle
          if (me.running) {
            me.count = count;
          }
        }
      }
      catch(e) {
        me.reset();
        me.error = e;
      }
      me.onCycle(me);
    }

    // figure out what to do next
    if (me.running) {
      call(me, _run, synchronous);
    }
    else if (me.averaging || me.error || (me.time * me.DEFAULT_AVERAGE) > 1) {
      me.onComplete(me);
    }
    else {
      // fast tests get their results averaged
      me.average(Math.max(me.DEFAULT_AVERAGE, Math.floor(1 / me.time)), null, synchronous);
    }
  }

  /*--------------------------------------------------------------------------*/

  // test to establish iteration loop overhead
  Benchmark.CALIBRATION = new Calibration(noop, { 'INIT_COUNT': 3e3 });

  Benchmark.getPlatform = getPlatform;

  Benchmark.noop = noop;

  extend(Benchmark.prototype, {
    // delay between test cycles (secs)
    'CYCLE_DELAY': 0.01,

    // number of runs to average
    'DEFAULT_AVERAGE': 10,

    // initial number of iterations
    'INIT_COUNT': 10,

    // max iterations allowed per cycle (used avoid locking up the browser)
    'MAX_COUNT': 1e6, // 1 million

    // minimum time a test should take to get valid results (secs)
    'MIN_TIME': 0.2,

    // number of times a test was executed
    'count': null,

    // number of cycles performed during testing
    'cycles': null,

    // an error object if the test failed
    'error': null,

    // number of test executions per second
    'hz': null,

    // time a test takes to do one execution (secs)
    'period': null,

    // flag to indicate if the test is running
    'running': false,

    // time a test takes to do the `count` number of executions (secs)
    'time': null,

    // callback invoked when testing is complete
    'onComplete': noop,

    // callback invoked when one test cycle ends
    'onCycle': noop,

    // callback invoked when test is reset
    'onReset': noop,

    // callback invoked when testing is started
    'onStart': noop,

    // callback invoked when testing is stopped
    'onStop': noop,

    // runs the test `n` times and returns the averaged test results
    'average': average,

    // create new benchmark with the same test function and options
    'clone': clone,

    // reset test state
    'reset': reset,

    // run the test
    'run': run,

    // stop testing (does not record times)
    'stop': stop
  });

  // expose
  global.Benchmark = Benchmark;

}(this));<|endoftext|>


<commit_before>describe('Expandable', function () {
    var expandable1 = $("#expandable-1").expandable(),
        showEvent = jasmine.createSpy('showEvent'),
        hideEvent = jasmine.createSpy('hideEvent'),
        readyEvent = jasmine.createSpy('readyEvent'),
        expandable2 = $("#expandable-2").expandable({
            'container': $('#container-2')
        }),
        expandable3 = $("#expandable-3").expandable({
            'shown': true,
            'toggle': false
        });

    expandable1
        .on('ready', function () { readyEvent(); })
        .on('show', function () { showEvent(); })
        .on('hide', function () { hideEvent(); });

    it('Should be defined on ch object', function () {
        expect(ch.hasOwnProperty('Expandable')).toBeTruthy();
        expect(typeof ch.Expandable).toEqual('function');
    });

    it('Should be defined on $ object', function () {
        expect($.fn.hasOwnProperty('expandable')).toBeTruthy();
        expect(typeof $.fn.expandable).toEqual('function');
    });

    it('Should be return a new instance', function () {
        expect(expandable1 instanceof ch.Expandable).toBeTruthy();
    });

    it('Should emit the "ready" event when it\'s ready', function () {
        waits(50);
        runs(function () {
            expect(readyEvent).toHaveBeenCalled();
        });
    });

    describe('Should have the following public properties:', function () {

        it('.el', function () {
            expect(expandable1.el).not.toEqual(undefined);
            expect(expandable1.el.nodeType).toEqual(1);
        });

        it('.$el', function () {
            expect(expandable1.$el).not.toEqual(undefined);
            expect(expandable1.$el instanceof $).toBeTruthy();
        });

        it('.name', function () {
            expect(expandable1.name).not.toEqual(undefined);
            expect(typeof expandable1.name).toEqual('string');
            expect(expandable1.name).toEqual('expandable');
        });

        it('.constructor', function () {
            expect(expandable1.constructor).not.toEqual(undefined);
            expect(typeof expandable1.constructor).toEqual('function');
        });

        it('.uid', function () {
            expect(expandable1.uid).not.toEqual(undefined);
            expect(typeof expandable1.uid).toEqual('number');
        });

    });

    describe('Should have the following public methods:', function () {

        it('.show()', function () {
            expect(expandable1.show).not.toEqual(undefined);
            expect(typeof expandable1.show).toEqual('function');
        });

        it('.hide()', function () {
            expect(expandable1.hide).not.toEqual(undefined);
            expect(typeof expandable1.hide).toEqual('function');
        });

        it('.isShow()', function () {
            expect(expandable1.isShown).not.toEqual(undefined);
            expect(typeof expandable1.isShown).toEqual('function');
        });

        it('.on()', function () {
            expect(expandable1.on).not.toEqual(undefined);
            expect(typeof expandable1.on).toEqual('function');
        });

        it('.once()', function () {
            expect(expandable1.once).not.toEqual(undefined);
            expect(typeof expandable1.once).toEqual('function');
        });

        it('.off()', function () {
            expect(expandable1.off).not.toEqual(undefined);
            expect(typeof expandable1.off).toEqual('function');
        });

        it('.emit()', function () {
            expect(expandable1.emit).not.toEqual(undefined);
            expect(typeof expandable1.emit).toEqual('function');
        });

        it('.content()', function () {
            expect(expandable1.content).not.toEqual(undefined);
            expect(typeof expandable1.content).toEqual('function');
        });
    });

    describe('Should have a trigger:', function () {
        var $trigger = expandable1.$trigger;

        it('It should exist.', function () {
            expect($trigger).not.toEqual(undefined);
            expect($trigger[0].nodeType).toEqual(1);
            expect($trigger instanceof $).toBeTruthy();
        });

        it('It should have the WAI-ARIA attribute "aria-controls"', function () {
           expect($trigger.attr('aria-controls')).toEqual(expandable1.$container[0].id);
        });

        describe('It should have the following class names:', function () {

            it('.ch-expandable-trigger', function () {
                expect($trigger.hasClass('ch-expandable-trigger')).toBeTruthy();
            });

            it('.ch-expandable-ico', function () {
                expect($trigger.hasClass('ch-expandable-ico')).toBeTruthy();
            });

            it('.ch-user-no-select', function () {
                expect($trigger.hasClass('ch-user-no-select')).toBeTruthy();
            });
        });

    });

    describe('Should have a container:', function () {
        var $container = expandable1.$container;

        it('It should exist.', function () {
            expect($container).not.toEqual(undefined);
            expect($container[0].nodeType).toEqual(1);
            expect($container instanceof $).toBeTruthy();
        });

        it('It shold be hidden.', function () {
            expect($container.hasClass('ch-hide')).toBeTruthy();
        });

        it('It should have the WAI-ARIA attribute "aria-expanded" in "false"', function () {
           expect($container.attr('aria-expanded')).toEqual('false');
        });

        describe('It should have the following class names:', function () {

            it('.ch-expandable-container', function () {
                expect($container.hasClass('ch-expandable-container')).toBeTruthy();
            });

        });
    });

    describe('Show method', function () {
        var $trigger = expandable1.$trigger,
            $container = expandable1.$container,
            show;

        it('Should add "ch-expandable-trigger-on" class name to trigger', function () {
            expect($trigger.hasClass('ch-expandable-trigger-on')).toBeFalsy();
            show = expandable1.show();
            expect($trigger.hasClass('ch-expandable-trigger-on')).toBeTruthy();
        });

        it('Should remove "ch-hide" class name from container.', function () {
            expect($container.hasClass('ch-hide')).toBeFalsy();
        });

        it('Should update the WAI-ARIA attribute "aria-expanded" to "true" on container', function () {
            expect($container.attr('aria-expanded')).toEqual('true');
        });

        it('Should emit the "show" event', function () {
            expect(showEvent).toHaveBeenCalled();
        });

        describe('Public instance', function () {
            it('Should return the same instance than initialized widget', function () {
                expect(show).toEqual(expandable1);
            });
        });
    });

    describe('Hide method', function () {
        var $trigger = expandable1.$trigger,
            $container = expandable1.$container,
            hide;

        it('Should remove "ch-expandable-trigger-on" class name to trigger', function () {
            hide = expandable1.hide();
            expect($trigger.hasClass('ch-expandable-trigger-on')).toBeFalsy();
        });

        it('Should add "ch-hide" class name to container', function () {
            expect($container.hasClass('ch-hide')).toBeTruthy();
        });

        it('Should update the WAI-ARIA attribute "aria-expanded" to "false" on container', function () {
            expect($container.attr('aria-expanded')).toEqual('false');
        });

        it('Should emit the "hide" event', function () {
            expect(showEvent).toHaveBeenCalled();
        });

        describe('Public instance', function () {
            it('Should return the same instance than initialized widget', function () {
                expect(hide).toEqual(expandable1);
            });
        });
    });

    describe('isShown method', function () {
        var isShown;

        it('Should return "true" when the widget is shown', function () {
            expandable1.show();
            isShown = expandable1.isShown();

            expect(typeof isShown).toEqual('boolean');
            expect(isShown).toBeTruthy();
        });

        it('Should return "false" when the widget is hidden', function () {
            expandable1.hide();
            isShown = expandable1.isShown();

            expect(typeof isShown).toEqual('boolean');
            expect(isShown).toBeFalsy();
        });

        expandable1.hide();
    });

    describe('An instance configured', function () {

        it('with custom container', function () {
            var $container = expandable2.$container;
            expect($container).not.toEqual(undefined);
            expect($container[0].nodeType).toEqual(1);
            expect($container instanceof $).toBeTruthy();
            expect($container).toEqual($('#container-2'));
        });

        it('shown by default', function () {
            expect(expandable3.$trigger.hasClass('ch-expandable-trigger-on')).toBeTruthy();
        });

        it('without toggle', function () {
            expandable3.show();
            expect(expandable3.$trigger.hasClass('ch-expandable-trigger-on')).toBeTruthy();

            expandable3.hide();
            expect(expandable3.$trigger.hasClass('ch-expandable-trigger-on')).toBeFalsy();
        });

    });
});<commit_msg>#987 Expandable: Fix isShown test.<commit_after>describe('Expandable', function () {
    var expandable1 = $("#expandable-1").expandable(),
        showEvent = jasmine.createSpy('showEvent'),
        hideEvent = jasmine.createSpy('hideEvent'),
        readyEvent = jasmine.createSpy('readyEvent'),
        expandable2 = $("#expandable-2").expandable({
            'container': $('#container-2')
        }),
        expandable3 = $("#expandable-3").expandable({
            'shown': true,
            'toggle': false
        });

    expandable1
        .on('ready', function () { readyEvent(); })
        .on('show', function () { showEvent(); })
        .on('hide', function () { hideEvent(); });

    it('Should be defined on ch object', function () {
        expect(ch.hasOwnProperty('Expandable')).toBeTruthy();
        expect(typeof ch.Expandable).toEqual('function');
    });

    it('Should be defined on $ object', function () {
        expect($.fn.hasOwnProperty('expandable')).toBeTruthy();
        expect(typeof $.fn.expandable).toEqual('function');
    });

    it('Should be return a new instance', function () {
        expect(expandable1 instanceof ch.Expandable).toBeTruthy();
    });

    it('Should emit the "ready" event when it\'s ready', function () {
        waits(50);
        runs(function () {
            expect(readyEvent).toHaveBeenCalled();
        });
    });

    describe('Should have the following public properties:', function () {

        it('.el', function () {
            expect(expandable1.el).not.toEqual(undefined);
            expect(expandable1.el.nodeType).toEqual(1);
        });

        it('.$el', function () {
            expect(expandable1.$el).not.toEqual(undefined);
            expect(expandable1.$el instanceof $).toBeTruthy();
        });

        it('.name', function () {
            expect(expandable1.name).not.toEqual(undefined);
            expect(typeof expandable1.name).toEqual('string');
            expect(expandable1.name).toEqual('expandable');
        });

        it('.constructor', function () {
            expect(expandable1.constructor).not.toEqual(undefined);
            expect(typeof expandable1.constructor).toEqual('function');
        });

        it('.uid', function () {
            expect(expandable1.uid).not.toEqual(undefined);
            expect(typeof expandable1.uid).toEqual('number');
        });

    });

    describe('Should have the following public methods:', function () {

        it('.show()', function () {
            expect(expandable1.show).not.toEqual(undefined);
            expect(typeof expandable1.show).toEqual('function');
        });

        it('.hide()', function () {
            expect(expandable1.hide).not.toEqual(undefined);
            expect(typeof expandable1.hide).toEqual('function');
        });

        it('.isShown()', function () {
            expect(expandable1.isShown).not.toEqual(undefined);
            expect(typeof expandable1.isShown).toEqual('function');
        });

        it('.on()', function () {
            expect(expandable1.on).not.toEqual(undefined);
            expect(typeof expandable1.on).toEqual('function');
        });

        it('.once()', function () {
            expect(expandable1.once).not.toEqual(undefined);
            expect(typeof expandable1.once).toEqual('function');
        });

        it('.off()', function () {
            expect(expandable1.off).not.toEqual(undefined);
            expect(typeof expandable1.off).toEqual('function');
        });

        it('.emit()', function () {
            expect(expandable1.emit).not.toEqual(undefined);
            expect(typeof expandable1.emit).toEqual('function');
        });

        it('.content()', function () {
            expect(expandable1.content).not.toEqual(undefined);
            expect(typeof expandable1.content).toEqual('function');
        });
    });

    describe('Should have a trigger:', function () {
        var $trigger = expandable1.$trigger;

        it('It should exist.', function () {
            expect($trigger).not.toEqual(undefined);
            expect($trigger[0].nodeType).toEqual(1);
            expect($trigger instanceof $).toBeTruthy();
        });

        it('It should have the WAI-ARIA attribute "aria-controls"', function () {
           expect($trigger.attr('aria-controls')).toEqual(expandable1.$container[0].id);
        });

        describe('It should have the following class names:', function () {

            it('.ch-expandable-trigger', function () {
                expect($trigger.hasClass('ch-expandable-trigger')).toBeTruthy();
            });

            it('.ch-expandable-ico', function () {
                expect($trigger.hasClass('ch-expandable-ico')).toBeTruthy();
            });

            it('.ch-user-no-select', function () {
                expect($trigger.hasClass('ch-user-no-select')).toBeTruthy();
            });
        });

    });

    describe('Should have a container:', function () {
        var $container = expandable1.$container;

        it('It should exist.', function () {
            expect($container).not.toEqual(undefined);
            expect($container[0].nodeType).toEqual(1);
            expect($container instanceof $).toBeTruthy();
        });

        it('It shold be hidden.', function () {
            expect($container.hasClass('ch-hide')).toBeTruthy();
        });

        it('It should have the WAI-ARIA attribute "aria-expanded" in "false"', function () {
           expect($container.attr('aria-expanded')).toEqual('false');
        });

        describe('It should have the following class names:', function () {

            it('.ch-expandable-container', function () {
                expect($container.hasClass('ch-expandable-container')).toBeTruthy();
            });

        });
    });

    describe('Show method', function () {
        var $trigger = expandable1.$trigger,
            $container = expandable1.$container,
            show;

        it('Should add "ch-expandable-trigger-on" class name to trigger', function () {
            expect($trigger.hasClass('ch-expandable-trigger-on')).toBeFalsy();
            show = expandable1.show();
            expect($trigger.hasClass('ch-expandable-trigger-on')).toBeTruthy();
        });

        it('Should remove "ch-hide" class name from container.', function () {
            expect($container.hasClass('ch-hide')).toBeFalsy();
        });

        it('Should update the WAI-ARIA attribute "aria-expanded" to "true" on container', function () {
            expect($container.attr('aria-expanded')).toEqual('true');
        });

        it('Should emit the "show" event', function () {
            expect(showEvent).toHaveBeenCalled();
        });

        describe('Public instance', function () {
            it('Should return the same instance than initialized widget', function () {
                expect(show).toEqual(expandable1);
            });
        });
    });

    describe('Hide method', function () {
        var $trigger = expandable1.$trigger,
            $container = expandable1.$container,
            hide;

        it('Should remove "ch-expandable-trigger-on" class name to trigger', function () {
            hide = expandable1.hide();
            expect($trigger.hasClass('ch-expandable-trigger-on')).toBeFalsy();
        });

        it('Should add "ch-hide" class name to container', function () {
            expect($container.hasClass('ch-hide')).toBeTruthy();
        });

        it('Should update the WAI-ARIA attribute "aria-expanded" to "false" on container', function () {
            expect($container.attr('aria-expanded')).toEqual('false');
        });

        it('Should emit the "hide" event', function () {
            expect(showEvent).toHaveBeenCalled();
        });

        describe('Public instance', function () {
            it('Should return the same instance than initialized widget', function () {
                expect(hide).toEqual(expandable1);
            });
        });
    });

    describe('isShown method', function () {
        var isShown;

        it('Should return "true" when the widget is shown', function () {
            expandable1.show();
            isShown = expandable1.isShown();

            expect(typeof isShown).toEqual('boolean');
            expect(isShown).toBeTruthy();
        });

        it('Should return "false" when the widget is hidden', function () {
            expandable1.hide();
            isShown = expandable1.isShown();

            expect(typeof isShown).toEqual('boolean');
            expect(isShown).toBeFalsy();
        });

        expandable1.hide();
    });

    describe('An instance configured', function () {

        it('with custom container', function () {
            var $container = expandable2.$container;
            expect($container).not.toEqual(undefined);
            expect($container[0].nodeType).toEqual(1);
            expect($container instanceof $).toBeTruthy();
            expect($container).toEqual($('#container-2'));
        });

        it('shown by default', function () {
            expect(expandable3.$trigger.hasClass('ch-expandable-trigger-on')).toBeTruthy();
        });

        it('without toggle', function () {
            expandable3.show();
            expect(expandable3.$trigger.hasClass('ch-expandable-trigger-on')).toBeTruthy();

            expandable3.hide();
            expect(expandable3.$trigger.hasClass('ch-expandable-trigger-on')).toBeFalsy();
        });

    });
});<|endoftext|>


<commit_before>// LICENSE : MIT
"use strict";
// https://gist.github.com/domenic/ec8b0fc8ab45f39403dd
var shell = require('shelljs');
var tmp = require('tmp');
var ghParse = require('parse-github-url');
var Acho = require('acho');
var path = require("path");
var gitConfig = require("./git-config");
var Command = require("command-promise");
var acho = new Acho();
function remoteURLWithToken(token) {
    if (token == null) {
        return "https://github.com/" + getSlug() + ".git"
    }
    return "https://" + token + "@github.com/" + getSlug() + ".git"
}
function getSlug() {
    // Travis CI
    // http://docs.travis-ci.com/user/environment-variables/
    if (process.env.TRAVIS_REPO_SLUG) {
        return process.env.TRAVIS_REPO_SLUG;
    }
    try {
        var pkg = require(path.join(process.cwd(), "package.json"));
        var gh = ghParse(pkg.repository.url);
        if (gh.repopath) {
            return gh.repopath;
        }
    } catch (error) {
        console.error(error);
    }
    throw new Error("Not found git repository.url");
}
function isTRAVIS() {
    return process.env.CI === "true" || process.env.TRAVIS === "true";
}
function isNotDeploy() {
    // when pull-request
    if (process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== 'false') {
        return true;
    }

    return false;
}
function deploy(directory) {
    if (!isTRAVIS()) {
        throw new Error("gh-pages-deploy-sh is for Travis CI.");
    }
    if (isNotDeploy()) {
        console.log("Don't deploy if it is pull-request");
        return Promise.resolve();
    }
    var deployDir = directory || path.join(process.cwd(), ".");
    acho.info("deploy directory " + deployDir);
    var tmpObj = tmp.dirSync();
    var tmpDir = tmpObj.name;
    return Command("cp -rf " + deployDir + " " + tmpDir)
        .then(function () {
            var workDir = path.join(tmpDir, path.basename(deployDir));
            acho.info("tmp directory " + workDir);
            return Command("cd " + workDir);
        }).then(function () {
            return Command("rm -f .gitignore");
        }).then(function () {
            return gitConfig.resolveGitName().then(function () {
                return gitConfig.resolveGitEmail()
            })
        }).then(function () {
            acho.info("git checkout -B gh-pages");
            return Command("git checkout -B gh-pages");
        }).then(function () {
            acho.info("git add && git commit");
            return Command("git add .").then(function () {
                return Command("git diff --quiet --exit-code --cached || git commit -m 'Update " + new Date().toISOString() + "'");
            });
        }).then(function () {
            acho.info("git push to gh-pages");
            var repositoryURL = remoteURLWithToken(process.env.GH_TOKEN);
            return Command("git push --force --quiet '" + repositoryURL + "' master:gh-pages > /dev/null 2>&1")
        }).then(function () {
            return Command("git checkout -");
        }).then(function () {
            acho.success("Finish deploy");
        });
}

module.exports = deploy;
<commit_msg>fix(sh): extend maxBuffer<commit_after>// LICENSE : MIT
"use strict";
// https://gist.github.com/domenic/ec8b0fc8ab45f39403dd
var shell = require('shelljs');
var tmp = require('tmp');
var ghParse = require('parse-github-url');
var Acho = require('acho');
var path = require("path");
var gitConfig = require("./git-config");
var Command = require("command-promise");
var Run = function (command) {
    return Run(command, {maxBuffer: 1024 * 1000});
};
var acho = new Acho();
function remoteURLWithToken(token) {
    if (token == null) {
        return "https://github.com/" + getSlug() + ".git"
    }
    return "https://" + token + "@github.com/" + getSlug() + ".git"
}
function getSlug() {
    // Travis CI
    // http://docs.travis-ci.com/user/environment-variables/
    if (process.env.TRAVIS_REPO_SLUG) {
        return process.env.TRAVIS_REPO_SLUG;
    }
    try {
        var pkg = require(path.join(process.cwd(), "package.json"));
        var gh = ghParse(pkg.repository.url);
        if (gh.repopath) {
            return gh.repopath;
        }
    } catch (error) {
        console.error(error);
    }
    throw new Error("Not found git repository.url");
}
function isTRAVIS() {
    return process.env.CI === "true" || process.env.TRAVIS === "true";
}
function isNotDeploy() {
    // when pull-request
    if (process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== 'false') {
        return true;
    }

    return false;
}
function deploy(directory) {
    if (!isTRAVIS()) {
        throw new Error("gh-pages-deploy-sh is for Travis CI.");
    }
    if (isNotDeploy()) {
        console.log("Don't deploy if it is pull-request");
        return Promise.resolve();
    }
    var deployDir = directory || path.join(process.cwd(), ".");
    acho.info("deploy directory " + deployDir);
    var tmpObj = tmp.dirSync();
    var tmpDir = tmpObj.name;
    return Run("cp -rf " + deployDir + " " + tmpDir)
        .then(function () {
            var workDir = path.join(tmpDir, path.basename(deployDir));
            acho.info("tmp directory " + workDir);
            return Run("cd " + workDir);
        }).then(function () {
            return Run("rm -f .gitignore");
        }).then(function () {
            return gitConfig.resolveGitName().then(function () {
                return gitConfig.resolveGitEmail()
            })
        }).then(function () {
            acho.info("git checkout -B gh-pages");
            return Run("git checkout -B gh-pages");
        }).then(function () {
            acho.info("git add && git commit");
            return Run("git add .").then(function () {
                return Run("git diff --quiet --exit-code --cached || git commit -m 'Update " + new Date().toISOString() + "'");
            });
        }).then(function () {
            acho.info("git push to gh-pages");
            var repositoryURL = remoteURLWithToken(process.env.GH_TOKEN);
            return Run("git push --force --quiet '" + repositoryURL + "' master:gh-pages > /dev/null 2>&1")
        }).then(function () {
            return Run("git checkout -");
        }).then(function () {
            acho.success("Finish deploy");
        });
}

module.exports = deploy;
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview An object that owns a block's rendering SVG elements.
 * @author samelh@google.com (Sam El-Husseini)
 */

'use strict';

goog.provide('Blockly.zelos.PathObject');

goog.require('Blockly.blockRendering.PathObject');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.object');
goog.require('Blockly.utils.Svg');
goog.require('Blockly.zelos.ConstantProvider');

goog.requireType('Blockly.Theme');

/**
 * An object that handles creating and setting each of the SVG elements
 * used by the renderer.
 * @param {!SVGElement} root The root SVG element.
 * @param {!Blockly.Theme.BlockStyle} style The style object to use for
 *     colouring.
 * @param {!Blockly.zelos.ConstantProvider} constants The renderer's constants.
 * @constructor
 * @extends {Blockly.blockRendering.PathObject}
 * @package
 */
Blockly.zelos.PathObject = function(root, style, constants) {
  Blockly.zelos.PathObject.superClass_.constructor.call(this, root, style,
      constants);

  /**
   * The renderer's constant provider.
   * @type {!Blockly.zelos.ConstantProvider}
   */
  this.constants = constants;

  /**
   * The selected path of the block.
   * @type {?SVGElement}
   * @private
   */
  this.svgPathSelected_ = null;

  /**
   * The outline paths on the block.
   * @type {!Object<string, !SVGElement>}
   * @private
   */
  this.outlines_ = Object.create(null);

  /**
   * A set used to determine which outlines were used during a draw pass.  The
   * set is initialized with a reference to all the outlines in
   * `this.outlines_`. Every time we use an outline during the draw pass, the
   * reference is removed from this set.
   * @type {Object<string, number>}
   * @private
   */
  this.remainingOutlines_ = null;

  /**
   * The type of block's output connection shape.  This is set when a block with
   * an output connection is drawn.
   * @package
   */
  this.outputShapeType = null;
};
Blockly.utils.object.inherits(Blockly.zelos.PathObject,
    Blockly.blockRendering.PathObject);

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.setPath = function(pathString) {
  Blockly.zelos.PathObject.superClass_.setPath.call(this, pathString);
  if (this.svgPathSelected_) {
    this.svgPathSelected_.setAttribute('d', pathString);
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.applyColour = function(block) {
  Blockly.zelos.PathObject.superClass_.applyColour.call(this, block);
  // Set shadow stroke colour.
  if (block.isShadow() && block.getParent()) {
    this.svgPath.setAttribute('stroke', block.getParent().style.colourTertiary);
  }

  // Apply colour to outlines.
  for (var key in this.outlines_) {
    this.outlines_[key].setAttribute('fill', this.style.colourTertiary);
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.flipRTL = function() {
  Blockly.zelos.PathObject.superClass_.flipRTL.call(this);
  // Mirror each input outline path.
  for (var key in this.outlines_) {
    this.outlines_[key].setAttribute('transform', 'scale(-1 1)');
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.updateSelected = function(enable) {
  this.setClass_('blocklySelected', enable);
  if (enable) {
    if (!this.svgPathSelected_) {
      this.svgPathSelected_ =
        /** @type {!SVGElement} */ (this.svgPath.cloneNode(true));
      this.svgPathSelected_.setAttribute('fill', 'none');
      this.svgPathSelected_.setAttribute('filter',
          'url(#' + this.constants.selectedGlowFilterId + ')');
      this.svgRoot.appendChild(this.svgPathSelected_);
    }
  } else {
    if (this.svgPathSelected_) {
      this.svgRoot.removeChild(this.svgPathSelected_);
      this.svgPathSelected_ = null;
    }
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.updateReplacementFade = function(
    enable) {
  this.setClass_('blocklyReplaceable', enable);
  if (enable) {
    this.svgPath.setAttribute('filter',
        'url(#' + this.constants.replacementGlowFilterId + ')');
  } else {
    this.svgPath.removeAttribute('filter');
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.updateShapeForInputHighlight = function(
    conn, enable) {
  var name = conn.getParentInput().name;
  var outlinePath = this.getOutlinePath_(name);
  if (!outlinePath) {
    return;
  }
  if (enable) {
    outlinePath.setAttribute('filter',
        'url(#' + this.constants.replacementGlowFilterId + ')');
  } else {
    outlinePath.removeAttribute('filter');
  }
};

/**
 * Method that's called when the drawer is about to draw the block.
 * @package
 */
Blockly.zelos.PathObject.prototype.beginDrawing = function() {
  this.remainingOutlines_ = Object.create(null);
  for (var key in this.outlines_) {
    // The value set here isn't used anywhere, we are just using the
    // object as a Set data structure.
    this.remainingOutlines_[key] = 1;
  }
};

/**
 * Method that's called when the drawer is done drawing.
 * @package
 */
Blockly.zelos.PathObject.prototype.endDrawing = function() {
  // Go through all remaining outlines that were not used this draw pass, and
  // remove them.
  if (this.remainingOutlines_) {
    for (var key in this.remainingOutlines_) {
      this.removeOutlinePath_(key);
    }
  }
  this.remainingOutlines_ = null;
};

/**
 * Set the path generated by the renderer for an outline path on the respective
 * outline path SVG element.
 * @param {string} name The input name.
 * @param {string} pathString The path.
 * @package
 */
Blockly.zelos.PathObject.prototype.setOutlinePath = function(name, pathString) {
  var outline = this.getOutlinePath_(name);
  outline.setAttribute('d', pathString);
  outline.setAttribute('fill', this.style.colourTertiary);
};

/**
 * Create's an outline path for the specified input.
 * @param {string} name The input name.
 * @return {!SVGElement} The SVG outline path.
 * @private
 */
Blockly.zelos.PathObject.prototype.getOutlinePath_ = function(name) {
  if (!this.outlines_[name]) {
    this.outlines_[name] = Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.PATH, {
          'class': 'blocklyOutlinePath',
          // IE doesn't like paths without the data definition, set empty default
          'd': ''
        },
        this.svgRoot);
  }
  if (this.remainingOutlines_) {
    delete this.remainingOutlines_[name];
  }
  return this.outlines_[name];
};

/**
 * Remove an outline path that is associated with the specified input.
 * @param {string} name The input name.
 * @private
 */
Blockly.zelos.PathObject.prototype.removeOutlinePath_ = function(name) {
  this.outlines_[name].parentNode.removeChild(this.outlines_[name]);
  delete this.outlines_[name];
};
<commit_msg>Migrate core/renderers/zelos/path_object.js to ES6 const/let<commit_after>/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview An object that owns a block's rendering SVG elements.
 * @author samelh@google.com (Sam El-Husseini)
 */

'use strict';

goog.provide('Blockly.zelos.PathObject');

goog.require('Blockly.blockRendering.PathObject');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.object');
goog.require('Blockly.utils.Svg');
goog.require('Blockly.zelos.ConstantProvider');

goog.requireType('Blockly.Theme');

/**
 * An object that handles creating and setting each of the SVG elements
 * used by the renderer.
 * @param {!SVGElement} root The root SVG element.
 * @param {!Blockly.Theme.BlockStyle} style The style object to use for
 *     colouring.
 * @param {!Blockly.zelos.ConstantProvider} constants The renderer's constants.
 * @constructor
 * @extends {Blockly.blockRendering.PathObject}
 * @package
 */
Blockly.zelos.PathObject = function(root, style, constants) {
  Blockly.zelos.PathObject.superClass_.constructor.call(this, root, style,
      constants);

  /**
   * The renderer's constant provider.
   * @type {!Blockly.zelos.ConstantProvider}
   */
  this.constants = constants;

  /**
   * The selected path of the block.
   * @type {?SVGElement}
   * @private
   */
  this.svgPathSelected_ = null;

  /**
   * The outline paths on the block.
   * @type {!Object<string, !SVGElement>}
   * @private
   */
  this.outlines_ = Object.create(null);

  /**
   * A set used to determine which outlines were used during a draw pass.  The
   * set is initialized with a reference to all the outlines in
   * `this.outlines_`. Every time we use an outline during the draw pass, the
   * reference is removed from this set.
   * @type {Object<string, number>}
   * @private
   */
  this.remainingOutlines_ = null;

  /**
   * The type of block's output connection shape.  This is set when a block with
   * an output connection is drawn.
   * @package
   */
  this.outputShapeType = null;
};
Blockly.utils.object.inherits(Blockly.zelos.PathObject,
    Blockly.blockRendering.PathObject);

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.setPath = function(pathString) {
  Blockly.zelos.PathObject.superClass_.setPath.call(this, pathString);
  if (this.svgPathSelected_) {
    this.svgPathSelected_.setAttribute('d', pathString);
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.applyColour = function(block) {
  Blockly.zelos.PathObject.superClass_.applyColour.call(this, block);
  // Set shadow stroke colour.
  if (block.isShadow() && block.getParent()) {
    this.svgPath.setAttribute('stroke', block.getParent().style.colourTertiary);
  }

  // Apply colour to outlines.
  for (const key in this.outlines_) {
    this.outlines_[key].setAttribute('fill', this.style.colourTertiary);
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.flipRTL = function() {
  Blockly.zelos.PathObject.superClass_.flipRTL.call(this);
  // Mirror each input outline path.
  for (const key in this.outlines_) {
    this.outlines_[key].setAttribute('transform', 'scale(-1 1)');
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.updateSelected = function(enable) {
  this.setClass_('blocklySelected', enable);
  if (enable) {
    if (!this.svgPathSelected_) {
      this.svgPathSelected_ =
        /** @type {!SVGElement} */ (this.svgPath.cloneNode(true));
      this.svgPathSelected_.setAttribute('fill', 'none');
      this.svgPathSelected_.setAttribute('filter',
          'url(#' + this.constants.selectedGlowFilterId + ')');
      this.svgRoot.appendChild(this.svgPathSelected_);
    }
  } else {
    if (this.svgPathSelected_) {
      this.svgRoot.removeChild(this.svgPathSelected_);
      this.svgPathSelected_ = null;
    }
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.updateReplacementFade = function(
    enable) {
  this.setClass_('blocklyReplaceable', enable);
  if (enable) {
    this.svgPath.setAttribute('filter',
        'url(#' + this.constants.replacementGlowFilterId + ')');
  } else {
    this.svgPath.removeAttribute('filter');
  }
};

/**
 * @override
 */
Blockly.zelos.PathObject.prototype.updateShapeForInputHighlight = function(
    conn, enable) {
  const name = conn.getParentInput().name;
  const outlinePath = this.getOutlinePath_(name);
  if (!outlinePath) {
    return;
  }
  if (enable) {
    outlinePath.setAttribute('filter',
        'url(#' + this.constants.replacementGlowFilterId + ')');
  } else {
    outlinePath.removeAttribute('filter');
  }
};

/**
 * Method that's called when the drawer is about to draw the block.
 * @package
 */
Blockly.zelos.PathObject.prototype.beginDrawing = function() {
  this.remainingOutlines_ = Object.create(null);
  for (const key in this.outlines_) {
    // The value set here isn't used anywhere, we are just using the
    // object as a Set data structure.
    this.remainingOutlines_[key] = 1;
  }
};

/**
 * Method that's called when the drawer is done drawing.
 * @package
 */
Blockly.zelos.PathObject.prototype.endDrawing = function() {
  // Go through all remaining outlines that were not used this draw pass, and
  // remove them.
  if (this.remainingOutlines_) {
    for (const key in this.remainingOutlines_) {
      this.removeOutlinePath_(key);
    }
  }
  this.remainingOutlines_ = null;
};

/**
 * Set the path generated by the renderer for an outline path on the respective
 * outline path SVG element.
 * @param {string} name The input name.
 * @param {string} pathString The path.
 * @package
 */
Blockly.zelos.PathObject.prototype.setOutlinePath = function(name, pathString) {
  const outline = this.getOutlinePath_(name);
  outline.setAttribute('d', pathString);
  outline.setAttribute('fill', this.style.colourTertiary);
};

/**
 * Create's an outline path for the specified input.
 * @param {string} name The input name.
 * @return {!SVGElement} The SVG outline path.
 * @private
 */
Blockly.zelos.PathObject.prototype.getOutlinePath_ = function(name) {
  if (!this.outlines_[name]) {
    this.outlines_[name] = Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.PATH, {
          'class': 'blocklyOutlinePath',
          // IE doesn't like paths without the data definition, set empty default
          'd': ''
        },
        this.svgRoot);
  }
  if (this.remainingOutlines_) {
    delete this.remainingOutlines_[name];
  }
  return this.outlines_[name];
};

/**
 * Remove an outline path that is associated with the specified input.
 * @param {string} name The input name.
 * @private
 */
Blockly.zelos.PathObject.prototype.removeOutlinePath_ = function(name) {
  this.outlines_[name].parentNode.removeChild(this.outlines_[name]);
  delete this.outlines_[name];
};
<|endoftext|>


<commit_before>const models = require('../../models');
const i18n = require('../../../shared/i18n');
const errors = require('@tryghost/errors');
const mega = require('../../services/mega');

const emailPreview = new mega.EmailPreview({
    apiVersion: 'v3'
});

module.exports = {
    docName: 'email_preview',

    read: {
        options: [
            'fields'
        ],
        validation: {
            options: {
                fields: ['html', 'plaintext', 'subject']
            }
        },
        data: [
            'id',
            'status'
        ],
        permissions: true,
        async query(frame) {
            const options = Object.assign(frame.options, {formats: 'html,plaintext', withRelated: ['authors', 'posts_meta']});
            const data = Object.assign(frame.data, {status: 'all'});

            const model = await models.Post.findOne(data, options);

            if (!model) {
                throw new errors.NotFoundError({
                    message: i18n.t('errors.api.posts.postNotFound')
                });
            }

            return emailPreview.generateEmailContent(model, frame.options.memberSegment);
        }
    },
    sendTestEmail: {
        statusCode: 200,
        headers: {},
        options: [
            'id'
        ],
        validation: {
            options: {
                id: {
                    required: true
                }
            }
        },
        permissions: true,
        async query(frame) {
            const options = Object.assign(frame.options, {status: 'all'});
            let model = await models.Post.findOne(options, {withRelated: ['authors']});

            if (!model) {
                throw new errors.NotFoundError({
                    message: i18n.t('errors.api.posts.postNotFound')
                });
            }

            const {emails = []} = frame.data;
            return await mega.mega.sendTestEmail(model, emails, 'v3');
        }
    }
};
<commit_msg>Replace i18n with tpl in email-preview.js (#13475)<commit_after>const models = require('../../models');
const tpl = require('@tryghost/tpl');
const errors = require('@tryghost/errors');
const mega = require('../../services/mega');

const messages = {
    postNotFound: 'Post not found.'
};

const emailPreview = new mega.EmailPreview({
    apiVersion: 'v3'
});

module.exports = {
    docName: 'email_preview',

    read: {
        options: [
            'fields'
        ],
        validation: {
            options: {
                fields: ['html', 'plaintext', 'subject']
            }
        },
        data: [
            'id',
            'status'
        ],
        permissions: true,
        async query(frame) {
            const options = Object.assign(frame.options, {formats: 'html,plaintext', withRelated: ['authors', 'posts_meta']});
            const data = Object.assign(frame.data, {status: 'all'});

            const model = await models.Post.findOne(data, options);

            if (!model) {
                throw new errors.NotFoundError({
                    message: tpl(messages.postNotFound)
                });
            }

            return emailPreview.generateEmailContent(model, frame.options.memberSegment);
        }
    },
    sendTestEmail: {
        statusCode: 200,
        headers: {},
        options: [
            'id'
        ],
        validation: {
            options: {
                id: {
                    required: true
                }
            }
        },
        permissions: true,
        async query(frame) {
            const options = Object.assign(frame.options, {status: 'all'});
            let model = await models.Post.findOne(options, {withRelated: ['authors']});

            if (!model) {
                throw new errors.NotFoundError({
                    message: tpl(messages.postNotFound)
                });
            }

            const {emails = []} = frame.data;
            return await mega.mega.sendTestEmail(model, emails, 'v3');
        }
    }
};
<|endoftext|>


<commit_before>(function($) {
    var menu,shadow,trigger,content,hash,currentTarget;
    var defaults= {
        menuStyle: {
            listStyle:'none',
            padding:'1px',
            margin:'0px',
            backgroundColor:'#fff',
            border:'1px solid #999',
            width:'100px'
        },
        itemStyle: {
            margin:'0px',
            color:'#000',
            display:'block',
            cursor:'default',
            padding:'3px',
            border:'1px solid #fff',
            backgroundColor:'transparent'
        },
        itemHoverStyle: {
            border:'1px solid #0a246a',
            backgroundColor:'#b6bdd2'
        },
        eventPosX:'pageX',
        eventPosY:'pageY',
        shadow:true,
        onContextMenu:null,
        onShowMenu:null
    };
    $.fn.contextMenu= function(id,options) {
        if(!menu) {
            menu=$('

').hide().css({
                position:'absolute',
                zIndex:'500'
            }).appendTo('body').bind('click', function(e) {
                e.stopPropagation()
            })
        }
        if(!shadow) {
            shadow=$('

').css({
                backgroundColor:'#000',
                position:'absolute',
                opacity:0.2,
                zIndex:499
            }).appendTo('body').hide()
        }
        hash=hash||[];
        hash.push({
            id:id,
            menuStyle:$.extend({},defaults.menuStyle,options.menuStyle|| {}),
            itemStyle:$.extend({},defaults.itemStyle,options.itemStyle|| {}),
            itemHoverStyle:$.extend({},defaults.itemHoverStyle,options.itemHoverStyle|| {}),
            bindings:options.bindings|| {},
            shadow:options.shadow||options.shadow===false?options.shadow:defaults.shadow,
            onContextMenu:options.onContextMenu||defaults.onContextMenu,
            onShowMenu:options.onShowMenu||defaults.onShowMenu,
            eventPosX:options.eventPosX||defaults.eventPosX,
            eventPosY:options.eventPosY||defaults.eventPosY
        });
        var index=hash.length-1;
        var callback = function(e) {
            var bShowContext=(!!hash[index].onContextMenu)?hash[index].onContextMenu(e):true;
            if(bShowContext)
                display(index,this,e,options);
            return false;
        };
        $(this).bind('contextmenu', callback);
        if(options.leftClickToo) {
            $(this).click(callback);
        }
        return this
    };
    function display(index,trigger,e,options) {
        var cur=hash[index];
        content=$('#'+cur.id).find('ul:first').clone(true);
        content.css(cur.menuStyle).find('li').css(cur.itemStyle).hover( function() {
            $(this).css(cur.itemHoverStyle)
        }, function() {
            $(this).css(cur.itemStyle)
        }).find('img').css({
            verticalAlign:'middle',
            paddingRight:'2px'
        });
        menu.html(content);
        if(!!cur.onShowMenu)
            menu=cur.onShowMenu(e,menu);
        $.each(cur.bindings, function(id,func) {
            $('#'+id,menu).bind('click', function(e) {
                hide();
                func(trigger,currentTarget)
            })
        });
        menu.css({
            'left':e[cur.eventPosX],
            'top':e[cur.eventPosY]
        }).show();
        if(cur.shadow)
            shadow.css({
                width:menu.width(),
                height:menu.height(),
                left:e.pageX+2,
                top:e.pageY+2
            }).show();
        $(document).one('click',hide)
    }

    function hide() {
        menu.hide();
        shadow.hide()
    }

    $.contextMenu= {
        defaults: function(userDefaults) {
            $.each(userDefaults, function(i,val) {
                if(typeof val=='object'&&defaults[i]) {
                    $.extend(defaults[i],val)
                } else
                    defaults[i]=val
            })
        }
    }
})(jQuery);
$( function() {
    $('div.contextMenu').hide()
});<commit_msg>[fix] problem with context menu being displayed under the popups<commit_after>(function($) {
    var menu,shadow,trigger,content,hash,currentTarget;
    var defaults= {
        menuStyle: {
            listStyle:'none',
            padding:'1px',
            margin:'0px',
            backgroundColor:'#fff',
            border:'1px solid #999',
            width:'100px'
        },
        itemStyle: {
            margin:'0px',
            color:'#000',
            display:'block',
            cursor:'default',
            padding:'3px',
            border:'1px solid #fff',
            backgroundColor:'transparent'
        },
        itemHoverStyle: {
            border:'1px solid #0a246a',
            backgroundColor:'#b6bdd2'
        },
        eventPosX:'pageX',
        eventPosY:'pageY',
        shadow:true,
        onContextMenu:null,
        onShowMenu:null
    };
    $.fn.contextMenu= function(id,options) {
        if(!menu) {
            menu=$('

').hide().css({
                position:'absolute',
                zIndex:'2000'
            }).appendTo('body').bind('click', function(e) {
                e.stopPropagation()
            })
        }
        if(!shadow) {
            shadow=$('

').css({
                backgroundColor:'#000',
                position:'absolute',
                opacity:0.2,
                zIndex:499
            }).appendTo('body').hide()
        }
        hash=hash||[];
        hash.push({
            id:id,
            menuStyle:$.extend({},defaults.menuStyle,options.menuStyle|| {}),
            itemStyle:$.extend({},defaults.itemStyle,options.itemStyle|| {}),
            itemHoverStyle:$.extend({},defaults.itemHoverStyle,options.itemHoverStyle|| {}),
            bindings:options.bindings|| {},
            shadow:options.shadow||options.shadow===false?options.shadow:defaults.shadow,
            onContextMenu:options.onContextMenu||defaults.onContextMenu,
            onShowMenu:options.onShowMenu||defaults.onShowMenu,
            eventPosX:options.eventPosX||defaults.eventPosX,
            eventPosY:options.eventPosY||defaults.eventPosY
        });
        var index=hash.length-1;
        var callback = function(e) {
            var bShowContext=(!!hash[index].onContextMenu)?hash[index].onContextMenu(e):true;
            if(bShowContext)
                display(index,this,e,options);
            return false;
        };
        $(this).bind('contextmenu', callback);
        if(options.leftClickToo) {
            $(this).click(callback);
        }
        return this
    };
    function display(index,trigger,e,options) {
        var cur=hash[index];
        content=$('#'+cur.id).find('ul:first').clone(true);
        content.css(cur.menuStyle).find('li').css(cur.itemStyle).hover( function() {
            $(this).css(cur.itemHoverStyle)
        }, function() {
            $(this).css(cur.itemStyle)
        }).find('img').css({
            verticalAlign:'middle',
            paddingRight:'2px'
        });
        menu.html(content);
        if(!!cur.onShowMenu)
            menu=cur.onShowMenu(e,menu);
        $.each(cur.bindings, function(id,func) {
            $('#'+id,menu).bind('click', function(e) {
                hide();
                func(trigger,currentTarget)
            })
        });
        menu.css({
            'left':e[cur.eventPosX],
            'top':e[cur.eventPosY]
        }).show();
        if(cur.shadow)
            shadow.css({
                width:menu.width(),
                height:menu.height(),
                left:e.pageX+2,
                top:e.pageY+2
            }).show();
        $(document).one('click',hide)
    }

    function hide() {
        menu.hide();
        shadow.hide()
    }

    $.contextMenu= {
        defaults: function(userDefaults) {
            $.each(userDefaults, function(i,val) {
                if(typeof val=='object'&&defaults[i]) {
                    $.extend(defaults[i],val)
                } else
                    defaults[i]=val
            })
        }
    }
})(jQuery);
$( function() {
    $('div.contextMenu').hide()
});<|endoftext|>


<commit_before>// Global variables
var currentLayer = 0;
var layerList = new Array();
var stage = undefined;
var connection = new WebSocket('ws://localhost:8080');
var open = false;

// Event handlers
function parseMessage(event) {
    console.log("received raw data:");
    console.log(event.data);
    layerList[currentLayer].destroyChildren();
    placeFigure(parseFigureMessage(jQuery.parseJSON(event.data)));
    layerList[currentLayer].batchDraw();
}
function connectionError(error) {
    console.log('WebSocket Error ');
    console.log(error);
}
function parseFigureMessage(message) {
    var figure = makeFigure(message);
    console.log(message);
    parseEventData(figure, message);
    return figure;
}
function newDefaultLayer() {
    currentLayer++;
    layerList[currentLayer] = new Kinetic.Layer();
    stage.add(layerList[currentLayer]);
}
function parseEventData(figure, message) {
    if(message.eventData != undefined && message.eventData != null) {
        if(message.eventData.listen.indexOf("mouseclick") != -1) {
            figure.on('click', clickEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mousedown") != -1) {
            figure.on('mousedown', mouseDownEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mouseup") != -1) {
            figure.on('mouseup', mouseUpEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mouseover") != -1) {
            figure.on('mouseover', mouseOverEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mousemove") != -1) {
            figure.on('mousemove', mouseMoveEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mouseout") != -1) {
            figure.on('mouseout', mouseOutEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mousedrag") != -1) {
            figure.on('mousedrag', mouseDragEventHandler.bind(undefined, message.eventData.eventId));
        }
    }
}
function placeFigure(figure) {
    layerList[currentLayer].add(figure);
    debugMessage("Drawing "+figure.className);
}
function makeFigure(message) {
    var figure;
    switch (message.type) {
        case "line":
            figure = drawLine(message.data);
            break;
        case "polygon":
            figure = drawPolygon(message.data);
            break;
        case "circle":
            figure = drawCircle(message.data);
            break;
        case "rect":
            figure = drawRect(message.data);
            break;
        case "text":
            figure = drawText(message.data);
            break;
        case "container":
            figure = drawGroup(message.data);
            message.children.forEach(function(child) {
                figure.add(parseFigureMessage(child));
            });
            break;
        default:
            window.alert("Unrecognized JSON message received from server.");
            figure = null;
    }
    return figure;
}
function drawLine(data) {
    return new Kinetic.Line(data);
}
function drawPolygon(data) {
    return new Kinetic.Polygon(data);
}
function drawCircle(data) {
    return new Kinetic.Circle(data);
}
function drawRect(data) {
    return new Kinetic.Rect(data);
}
function drawText(data) {
    return new Kinetic.Text(data);
}
function drawGroup(data) {
    return new Kinetic.Group(data);
}
function clickEventHandler(id, event) { mouseEvent("mouseclick", id, event); }
function mouseDownEventHandler(id, event) { mouseEvent("mousedown", id, event); }
function mouseUpEventHandler(id, event) { mouseEvent("mouseup", id, event); }
function mouseOverEventHandler(id, event) { mouseEvent("mouseover", id, event); }
function mouseOutEventHandler(id, event) { mouseEvent("mouseout", id, event); }
function mouseMoveEventHandler(id, event) { mouseEvent("mousemove", id, event); }
function mouseDragEventHandler(id, event) { mouseEvent("mousedrag", id, event); }
function mouseEvent(eventName, id, event) {
    // Compensate for the position of the canvas
    var canvasPos = $("#canvas").position();
    console.log(event);
    connection.send(JSON.stringify({
        "event":eventName,
        "data":{
            "id": id,
            "x": event.pageX-canvasPos.left+575,
            "y": event.pageY-canvasPos.top+300
        }
    }));
}
function debugMessage(message) {

    var now = new Date(),
        now = now.getHours()+':'+now.getMinutes()+':'+now.getSeconds();
    $("#debug").prepend("
["+now+"] "+message+"
")
}

$(document).ready(function() {

    var width = 900; // defined here because the container also needs these proportions
    var height = 600;

    $( "#wrapper" ).css( "min-width", width+"px" );
    $( "#wrapper" ).css( "height", $( window ).height()+"px" );

    $( window ).resize(function() {
        $( "#wrapper" ).css( "height", $( window ).height()+"px" );
    });

    $( "#canvas" ).css( "width", width+"px" );
    $( "#canvas" ).css( "height", height+"px" );
    $( "#canvas" ).css( "margin-top", "-"+height/2+"px" );
    $( "#canvas" ).css( "margin-left", "-"+(width + $( "#debug" ).width())/2+"px" );

    stage = new Kinetic.Stage({
        container: 'canvas',
        width: 900,
        height: 600
    });
    var rect = drawRect({width: 900,
        height: 600})
    rect.on('click', clickEventHandler.bind(undefined, ""));
    layer = new Kinetic.Layer();
    layer.add(rect);
    stage.add(layer);

    // When the connection is open, send some data to the server
    connection.onopen = function () {
    };

    // Log errors
    connection.onerror = connectionError;

    // Log messages from the server
    connection.onmessage = parseMessage;

    // Create new layer to draw on
    newDefaultLayer();

});

<commit_msg>Keydown and keyup events added<commit_after>// Global variables
var currentLayer = 0;
var layerList = new Array();
var stage = undefined;
var connection = new WebSocket('ws://localhost:8080');
var open = false;

// Event handlers
function parseMessage(event) {
    console.log("received raw data:");
    console.log(event.data);
    layerList[currentLayer].destroyChildren();
    placeFigure(parseFigureMessage(jQuery.parseJSON(event.data)));
    layerList[currentLayer].batchDraw();
}
function connectionError(error) {
    console.log('WebSocket Error ');
    console.log(error);
}
function parseFigureMessage(message) {
    var figure = makeFigure(message);
    console.log(message);
    parseEventData(figure, message);
    return figure;
}
function newDefaultLayer() {
    currentLayer++;
    layerList[currentLayer] = new Kinetic.Layer();
    stage.add(layerList[currentLayer]);
}
function parseEventData(figure, message) {
    if(message.eventData != undefined && message.eventData != null) {
        if(message.eventData.listen.indexOf("mouseclick") != -1) {
            figure.on('click', clickEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mousedown") != -1) {
            figure.on('mousedown', mouseDownEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mouseup") != -1) {
            figure.on('mouseup', mouseUpEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mouseover") != -1) {
            figure.on('mouseover', mouseOverEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mousemove") != -1) {
            figure.on('mousemove', mouseMoveEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mouseout") != -1) {
            figure.on('mouseout', mouseOutEventHandler.bind(undefined, message.eventData.eventId));
        }
        if(message.eventData.listen.indexOf("mousedrag") != -1) {
            figure.on('mousedrag', mouseDragEventHandler.bind(undefined, message.eventData.eventId));
        }
    }
}
function placeFigure(figure) {
    layerList[currentLayer].add(figure);
    debugMessage("Drawing "+figure.className);
}
function makeFigure(message) {
    var figure;
    switch (message.type) {
        case "line":
            figure = drawLine(message.data);
            break;
        case "polygon":
            figure = drawPolygon(message.data);
            break;
        case "circle":
            figure = drawCircle(message.data);
            break;
        case "rect":
            figure = drawRect(message.data);
            break;
        case "text":
            figure = drawText(message.data);
            break;
        case "container":
            figure = drawGroup(message.data);
            message.children.forEach(function(child) {
                figure.add(parseFigureMessage(child));
            });
            break;
        default:
            window.alert("Unrecognized JSON message received from server.");
            figure = null;
    }
    return figure;
}
function drawLine(data) {
    return new Kinetic.Line(data);
}
function drawPolygon(data) {
    return new Kinetic.Polygon(data);
}
function drawCircle(data) {
    return new Kinetic.Circle(data);
}
function drawRect(data) {
    return new Kinetic.Rect(data);
}
function drawText(data) {
    return new Kinetic.Text(data);
}
function drawGroup(data) {
    return new Kinetic.Group(data);
}
function clickEventHandler(id, event) { mouseEvent("mouseclick", id, event); }
function mouseDownEventHandler(id, event) { mouseEvent("mousedown", id, event); }
function mouseUpEventHandler(id, event) { mouseEvent("mouseup", id, event); }
function mouseOverEventHandler(id, event) { mouseEvent("mouseover", id, event); }
function mouseOutEventHandler(id, event) { mouseEvent("mouseout", id, event); }
function mouseMoveEventHandler(id, event) { mouseEvent("mousemove", id, event); }
function mouseDragEventHandler(id, event) { mouseEvent("mousedrag", id, event); }
function mouseEvent(eventName, id, event) {
    // Compensate for the position of the canvas
    var canvasPos = $("#canvas").position();
    console.log(event);
    connection.send(JSON.stringify({
        "event":eventName,
        "data":{
            "id": id,
            "x": event.pageX-canvasPos.left+575,
            "y": event.pageY-canvasPos.top+300
        }
    }));
}

function debugMessage(message) {
    var now = new Date(),
        now = now.getHours()+':'+now.getMinutes()+':'+now.getSeconds();
    $("#debug").prepend("
["+now+"] "+message+"
")
}

var control = false;
var shift = false;
var alt = false;
var superKey = false;

function keyEvent(event,key) {
        connection.send(JSON.stringify({
            "event":event,
            "data":{
                "key": key,
                "control": control,
                "alt": alt,
                "shift": shift,
                "super": superKey
            }
        }));
}

$(document).ready(function() {

    var width = 900; // defined here because the container also needs these proportions
    var height = 600;

    $( "#wrapper" ).css( "min-width", width+"px" );
    $( "#wrapper" ).css( "height", $( window ).height()+"px" );

    $( window ).resize(function() {
        $( "#wrapper" ).css( "height", $( window ).height()+"px" );
    });

    $( "#canvas" ).css( "width", width+"px" );
    $( "#canvas" ).css( "height", height+"px" );
    $( "#canvas" ).css( "margin-top", "-"+height/2+"px" );
    $( "#canvas" ).css( "margin-left", "-"+(width + $( "#debug" ).width())/2+"px" );

    stage = new Kinetic.Stage({
        container: 'canvas',
        width: 900,
        height: 600
    });
    var rect = drawRect({width: 900, height: 600});
    rect.on('click', clickEventHandler.bind(undefined, ""));
    layer = new Kinetic.Layer();
    layer.add(rect);
    stage.add(layer);

    // When the connection is open, send some data to the server
    connection.onopen = function () {
    };

    // Log errors
    connection.onerror = connectionError;

    // Log messages from the server
    connection.onmessage = parseMessage;

    // Create new layer to draw on
    newDefaultLayer();

    window.addEventListener('keydown', function(e) {
        e.preventDefault();
        if (e.keyCode === 16) {
            shift = true;
        } else if (e.keyCode === 17) {
            control = true;
        } else if (e.keyCode === 18) {
            alt = true;
        } else if (e.keyCode === 91) {
            superKey = true;
        } else {
            var key = String.fromCharCode(e.keyCode);
            keyEvent("keydown", key);
//            console.log("Keydown: " + key + "\r\n shift: " + shift
//                    + "\r\n control: " + control + "\r\n alt: " + alt + "\r\n super: " + superKey);
        }
    });

    window.addEventListener('keyup', function(e) {
        e.preventDefault();
        if (e.keyCode === 16) {
            shift = false;
        } else if (e.keyCode === 17) {
            control = false;
        } else if (e.keyCode === 18) {
            alt = false;
        } else if (e.keyCode === 91) {
            superKey = false;
        } else {
            var key = String.fromCharCode(e.keyCode);
            keyEvent("keyup", key);
            console.log("Keyup: " + key);
        }
    });

});

<|endoftext|>


<commit_before>var async = require('async');
var url = require('url');
var httpreq = require('httpreq');
var ntlm = require('./ntlm');

exports.method = function(method, options, callback){
	if(!options.workstation) options.workstation = '';
	if(!options.domain) options.domain = '';

	// is https?
	var isHttps = false;
	var reqUrl = url.parse(options.url);
	if(reqUrl.protocol == 'https:') isHttps = true;

	// set keepaliveAgent (http or https):
	var keepaliveAgent;

	if(isHttps){
		var HttpsAgent = require('agentkeepalive').HttpsAgent;
		keepaliveAgent = new HttpsAgent();
	}else{
		var Agent = require('agentkeepalive');
		keepaliveAgent = new Agent();
	}

	async.waterfall([
		function ($){
			var type1msg = ntlm.createType1Message(options);

			httpreq.get(options.url, {
				headers:{
					'Connection' : 'keep-alive',
					'Authorization': type1msg
				},
				agent: keepaliveAgent
			}, $);
		},

		function (res, $){
			if(!res.headers['www-authenticate'])
				return $(new Error('www-authenticate not found on response of second request'));

			var type2msg = ntlm.parseType2Message(res.headers['www-authenticate']);
			var type3msg = ntlm.createType3Message(type2msg, options);

			httpreq[method](options.url, {
				headers:{
					'Connection' : 'Close',
					'Authorization': type3msg
				},
				allowRedirects: false,
				agent: keepaliveAgent
			}, $);
		}
	], callback);
};

['get', 'put', 'post', 'delete', 'head'].forEach(function(method){
  exports[method] = exports.method.bind(exports, method);
});

exports.ntlm = ntlm; //if you want to use the NTML functions yourself

<commit_msg>Adding custome headers + body to the final request<commit_after>var async = require('async');
var url = require('url');
var httpreq = require('httpreq');
var ntlm = require('./ntlm');

exports.method = function(method, options, callback){
	if(!options.workstation) options.workstation = '';
	if(!options.domain) options.domain = '';

	// is https?
	var isHttps = false;
	var reqUrl = url.parse(options.url);
	if(reqUrl.protocol == 'https:') isHttps = true;

	// set keepaliveAgent (http or https):
	var keepaliveAgent;

	if(isHttps){
		var HttpsAgent = require('agentkeepalive').HttpsAgent;
		keepaliveAgent = new HttpsAgent();
	}else{
		var Agent = require('agentkeepalive');
		keepaliveAgent = new Agent();
	}

	async.waterfall([
		function ($){
			var type1msg = ntlm.createType1Message(options);

			httpreq.get(options.url, {
				headers:{
					'Connection' : 'keep-alive',
					'Authorization': type1msg
				},
				agent: keepaliveAgent
			}, $);
		},

		function (res, $){
			if(!res.headers['www-authenticate'])
				return $(new Error('www-authenticate not found on response of second request'));

			var type2msg = ntlm.parseType2Message(res.headers['www-authenticate']);
			var type3msg = ntlm.createType3Message(type2msg, options);
			var headers = options.headers || {};
			var body = options.body || '';

			headers['Connection'] = 'Close';
			headers['Authorization'] = type3msg;

			httpreq[method](options.url, {
				headers: headers,
				allowRedirects: false,
				agent: keepaliveAgent,
				body: body
			}, $);
		}
	], callback);
};

['get', 'put', 'post', 'delete', 'head'].forEach(function(method){
  exports[method] = exports.method.bind(exports, method);
});

exports.ntlm = ntlm; //if you want to use the NTML functions yourself

<|endoftext|>