<commit_before>
/**
 * Optiscroll, use this to create instances
 * ```
 * var scrolltime = new Optiscroll(element);
 * ```
 */
var Optiscroll = function Optiscroll(element, options) {
  return new Optiscroll.Instance(element, options || {});
};

var GS = Optiscroll.globalSettings = {
  scrollMinUpdateInterval: 1000 / 40, // 40 FPS
  checkFrequency: 1000,
  pauseCheck: false,
};

Optiscroll.defaults = {
  preventParentScroll: false,
  forceScrollbars: false,
  scrollStopDelay: 300,
  maxTrackSize: 95,
  minTrackSize: 5,
  draggableTracks: true,
  autoUpdate: true,
  classPrefix: 'optiscroll-',
  wrapContent: true,
  rtl: false,
};

Optiscroll.Instance = function (element, options) {
  // instance variables
  this.element = element;
  this.settings = _extend(_extend({}, Optiscroll.defaults), options || {});
  if (typeof options.rtl !== 'boolean') {
    this.settings.rtl = window.getComputedStyle(element).direction === 'rtl';
  }
  this.cache = {};

  this.init();
};

Optiscroll.Instance.prototype = {

  init: function () {
    var element = this.element,
        settings = this.settings,
        shouldCreateScrollbars = false;

    var scrollEl = this.scrollEl = settings.wrapContent
      ? Utils.createWrapper(element)
      : element.firstElementChild;

    toggleClass(scrollEl, settings.classPrefix + 'content', true);
    toggleClass(element, 'is-enabled' + (settings.rtl ? ' is-rtl' : ''), true);

    // initialize scrollbars
    this.scrollbars = {
      v: Scrollbar('v', this),
      h: Scrollbar('h', this),
    };

    // create DOM scrollbars only if they have size or if it's forced
    if(G.scrollbarSpec.width || settings.forceScrollbars) {
      shouldCreateScrollbars = Utils.hideNativeScrollbars(scrollEl, settings.rtl);
    }

    if(shouldCreateScrollbars) {
      _invoke(this.scrollbars, 'create');
    }

    if(G.isTouch && settings.preventParentScroll) {
      toggleClass(element, settings.classPrefix + 'prevent', true);
    }

    // calculate scrollbars
    this.update();

    // bind container events
    this.bind();

    // add instance to global array for timed check
    if(settings.autoUpdate) {
      G.instances.push(this);
    }

    // start the timed check if it is not already running
    if(settings.autoUpdate && !G.checkTimer) {
      Utils.checkLoop();
    }

  },

  bind: function () {
    var listeners = this.listeners = {},
        scrollEl = this.scrollEl;

    // scroll event binding
    listeners.scroll = _throttle(Events.scroll.bind(this), GS.scrollMinUpdateInterval);

    if(G.isTouch) {
      listeners.touchstart = Events.touchstart.bind(this);
      listeners.touchend = Events.touchend.bind(this);
    }

    // Safari does not support wheel event
    listeners.mousewheel = listeners.wheel = Events.wheel.bind(this);

    for (var ev in listeners) {
      scrollEl.addEventListener(ev, listeners[ev], G.passiveEvent);
    }

  },

  update: function () {
    var scrollEl = this.scrollEl,
        cache = this.cache,
        oldcH = cache.clientH,
        sH = scrollEl.scrollHeight,
        cH = scrollEl.clientHeight,
        sW = scrollEl.scrollWidth,
        cW = scrollEl.clientWidth;

    if(sH !== cache.scrollH || cH !== cache.clientH ||
      sW !== cache.scrollW || cW !== cache.clientW) {

      cache.scrollH = sH;
      cache.clientH = cH;
      cache.scrollW = sW;
      cache.clientW = cW;

      // only fire if cache was defined
      if(oldcH !== undefined) {

        // if the element is no more in the DOM
        if(sH === 0 && cH === 0 && !document.body.contains(this.element)) {
          this.destroy();
          return false;
        }

        this.fireCustomEvent('sizechange');
      }

      // this will update the scrollbar
      // and check if bottom is reached
      _invoke(this.scrollbars, 'update');
    }
  },

  /**
   * Animate scrollTo
   */
  scrollTo: function (destX, destY, duration) {
    var cache = this.cache,
        startX, startY, endX, endY;

    G.pauseCheck = true;
    // force update
    this.update();

    startX = this.scrollEl.scrollLeft;
    startY = this.scrollEl.scrollTop;

    endX = +destX;
    if(destX === 'left') { endX = 0; }
    if(destX === 'right') { endX = cache.scrollW - cache.clientW; }
    if(destX === false) { endX = startX; }

    endY = +destY;
    if(destY === 'top') { endY = 0; }
    if(destY === 'bottom') { endY = cache.scrollH - cache.clientH; }
    if(destY === false) { endY = startY; }

    // animate
    this.animateScroll(startX, endX, startY, endY, +duration);

  },

  scrollIntoView: function (elem, duration, delta) {
    var scrollEl = this.scrollEl,
        eDim, sDim,
        leftEdge, topEdge, rightEdge, bottomEdge,
        offsetX, offsetY,
        startX, startY, endX, endY;

    G.pauseCheck = true;
    // force update
    this.update();

    if(typeof elem === 'string') { // selector
      elem = scrollEl.querySelector(elem);
    } else if(elem.length && elem.jquery) { // jquery element
      elem = elem[0];
    }

    if(typeof delta === 'number') { // same delta for all
      delta = { top: delta, right: delta, bottom: delta, left: delta };
    }

    delta = delta || {};
    eDim = elem.getBoundingClientRect();
    sDim = scrollEl.getBoundingClientRect();

    startX = endX = scrollEl.scrollLeft;
    startY = endY = scrollEl.scrollTop;
    offsetX = startX + eDim.left - sDim.left;
    offsetY = startY + eDim.top - sDim.top;

    leftEdge = offsetX - (delta.left || 0);
    topEdge = offsetY - (delta.top || 0);
    rightEdge = offsetX + eDim.width - this.cache.clientW + (delta.right || 0);
    bottomEdge = offsetY + eDim.height - this.cache.clientH + (delta.bottom || 0);

    if(leftEdge < startX) { endX = leftEdge; }
    if(rightEdge > startX) { endX = rightEdge; }

    if(topEdge < startY) { endY = topEdge; }
    if(bottomEdge > startY) { endY = bottomEdge; }

    // animate
    this.animateScroll(startX, endX, startY, endY, +duration);
  },

  animateScroll: function (startX, endX, startY, endY, duration) {
    var self = this,
        scrollEl = this.scrollEl,
        startTime = Date.now();

    if(endX === startX && endY === startY) {
      return;
    }

    if(duration === 0) {
      scrollEl.scrollLeft = endX;
      scrollEl.scrollTop = endY;
      return;
    }

    if(isNaN(duration)) { // undefined or auto
      // 500px in 430ms, 1000px in 625ms, 2000px in 910ms
      duration = Math.pow(Math.max(Math.abs(endX - startX), Math.abs(endY - startY)), 0.54) * 15;
    }

    (function animate () {
      var time = Math.min(1, ((Date.now() - startTime) / duration)),
          easedTime = Utils.easingFunction(time);

      if(endY !== startY) {
        scrollEl.scrollTop = ~~(easedTime * (endY - startY)) + startY;
      }
      if(endX !== startX) {
        scrollEl.scrollLeft = ~~(easedTime * (endX - startX)) + startX;
      }

      self.scrollAnimation = time < 1 ? window.requestAnimationFrame(animate) : null;
    }());
  },

  destroy: function () {
    var self = this,
        element = this.element,
        scrollEl = this.scrollEl,
        listeners = this.listeners,
        child;

    if(!this.scrollEl) { return; }

    // unbind events
    for (var ev in listeners) {
      scrollEl.removeEventListener(ev, listeners[ev]);
    }

    // remove scrollbars elements
    _invoke(this.scrollbars, 'remove');

    // unwrap content
    if (!this.settings.contentElement) {
      while(child = scrollEl.childNodes[0]) {
        element.insertBefore(child, scrollEl);
      }
      element.removeChild(scrollEl);
      this.scrollEl = null;
    }

    // remove classes
    toggleClass(element, this.settings.classPrefix + 'prevent', false);
    toggleClass(element, 'is-enabled', false);

    // defer instance removal from global array
    // to not affect checkLoop _invoke
    window.requestAnimationFrame(function () {
      var index = G.instances.indexOf(self);
      if (index > -1) {
        G.instances.splice(index, 1);
      }
    });
  },

  fireCustomEvent: function (eventName) {
    var cache = this.cache,
        sH = cache.scrollH, sW = cache.scrollW,
        eventData;

    eventData = {
      // scrollbars data
      scrollbarV: _extend({}, cache.v),
      scrollbarH: _extend({}, cache.h),

      // scroll position
      scrollTop: cache.v.position * sH,
      scrollLeft: cache.h.position * sW,
      scrollBottom: (1 - cache.v.position - cache.v.size) * sH,
      scrollRight: (1 - cache.h.position - cache.h.size) * sW,

      // element size
      scrollWidth: sW,
      scrollHeight: sH,
      clientWidth: cache.clientW,
      clientHeight: cache.clientH,
    };

    var event;
    if (typeof CustomEvent === 'function') {
      event = new CustomEvent(eventName, { detail: eventData });
    } else { // IE does not support CustomEvent
      event = document.createEvent('CustomEvent');
      event.initCustomEvent(eventName, false, false, eventData);
    }
    this.element.dispatchEvent(event);
  },

};

<commit_msg>Fix incorrect setting check<commit_after>
/**
 * Optiscroll, use this to create instances
 * ```
 * var scrolltime = new Optiscroll(element);
 * ```
 */
var Optiscroll = function Optiscroll(element, options) {
  return new Optiscroll.Instance(element, options || {});
};

var GS = Optiscroll.globalSettings = {
  scrollMinUpdateInterval: 1000 / 40, // 40 FPS
  checkFrequency: 1000,
  pauseCheck: false,
};

Optiscroll.defaults = {
  preventParentScroll: false,
  forceScrollbars: false,
  scrollStopDelay: 300,
  maxTrackSize: 95,
  minTrackSize: 5,
  draggableTracks: true,
  autoUpdate: true,
  classPrefix: 'optiscroll-',
  wrapContent: true,
  rtl: false,
};

Optiscroll.Instance = function (element, options) {
  // instance variables
  this.element = element;
  this.settings = _extend(_extend({}, Optiscroll.defaults), options || {});
  if (typeof options.rtl !== 'boolean') {
    this.settings.rtl = window.getComputedStyle(element).direction === 'rtl';
  }
  this.cache = {};

  this.init();
};

Optiscroll.Instance.prototype = {

  init: function () {
    var element = this.element,
        settings = this.settings,
        shouldCreateScrollbars = false;

    var scrollEl = this.scrollEl = settings.wrapContent
      ? Utils.createWrapper(element)
      : element.firstElementChild;

    toggleClass(scrollEl, settings.classPrefix + 'content', true);
    toggleClass(element, 'is-enabled' + (settings.rtl ? ' is-rtl' : ''), true);

    // initialize scrollbars
    this.scrollbars = {
      v: Scrollbar('v', this),
      h: Scrollbar('h', this),
    };

    // create DOM scrollbars only if they have size or if it's forced
    if(G.scrollbarSpec.width || settings.forceScrollbars) {
      shouldCreateScrollbars = Utils.hideNativeScrollbars(scrollEl, settings.rtl);
    }

    if(shouldCreateScrollbars) {
      _invoke(this.scrollbars, 'create');
    }

    if(G.isTouch && settings.preventParentScroll) {
      toggleClass(element, settings.classPrefix + 'prevent', true);
    }

    // calculate scrollbars
    this.update();

    // bind container events
    this.bind();

    // add instance to global array for timed check
    if(settings.autoUpdate) {
      G.instances.push(this);
    }

    // start the timed check if it is not already running
    if(settings.autoUpdate && !G.checkTimer) {
      Utils.checkLoop();
    }

  },

  bind: function () {
    var listeners = this.listeners = {},
        scrollEl = this.scrollEl;

    // scroll event binding
    listeners.scroll = _throttle(Events.scroll.bind(this), GS.scrollMinUpdateInterval);

    if(G.isTouch) {
      listeners.touchstart = Events.touchstart.bind(this);
      listeners.touchend = Events.touchend.bind(this);
    }

    // Safari does not support wheel event
    listeners.mousewheel = listeners.wheel = Events.wheel.bind(this);

    for (var ev in listeners) {
      scrollEl.addEventListener(ev, listeners[ev], G.passiveEvent);
    }

  },

  update: function () {
    var scrollEl = this.scrollEl,
        cache = this.cache,
        oldcH = cache.clientH,
        sH = scrollEl.scrollHeight,
        cH = scrollEl.clientHeight,
        sW = scrollEl.scrollWidth,
        cW = scrollEl.clientWidth;

    if(sH !== cache.scrollH || cH !== cache.clientH ||
      sW !== cache.scrollW || cW !== cache.clientW) {

      cache.scrollH = sH;
      cache.clientH = cH;
      cache.scrollW = sW;
      cache.clientW = cW;

      // only fire if cache was defined
      if(oldcH !== undefined) {

        // if the element is no more in the DOM
        if(sH === 0 && cH === 0 && !document.body.contains(this.element)) {
          this.destroy();
          return false;
        }

        this.fireCustomEvent('sizechange');
      }

      // this will update the scrollbar
      // and check if bottom is reached
      _invoke(this.scrollbars, 'update');
    }
  },

  /**
   * Animate scrollTo
   */
  scrollTo: function (destX, destY, duration) {
    var cache = this.cache,
        startX, startY, endX, endY;

    G.pauseCheck = true;
    // force update
    this.update();

    startX = this.scrollEl.scrollLeft;
    startY = this.scrollEl.scrollTop;

    endX = +destX;
    if(destX === 'left') { endX = 0; }
    if(destX === 'right') { endX = cache.scrollW - cache.clientW; }
    if(destX === false) { endX = startX; }

    endY = +destY;
    if(destY === 'top') { endY = 0; }
    if(destY === 'bottom') { endY = cache.scrollH - cache.clientH; }
    if(destY === false) { endY = startY; }

    // animate
    this.animateScroll(startX, endX, startY, endY, +duration);

  },

  scrollIntoView: function (elem, duration, delta) {
    var scrollEl = this.scrollEl,
        eDim, sDim,
        leftEdge, topEdge, rightEdge, bottomEdge,
        offsetX, offsetY,
        startX, startY, endX, endY;

    G.pauseCheck = true;
    // force update
    this.update();

    if(typeof elem === 'string') { // selector
      elem = scrollEl.querySelector(elem);
    } else if(elem.length && elem.jquery) { // jquery element
      elem = elem[0];
    }

    if(typeof delta === 'number') { // same delta for all
      delta = { top: delta, right: delta, bottom: delta, left: delta };
    }

    delta = delta || {};
    eDim = elem.getBoundingClientRect();
    sDim = scrollEl.getBoundingClientRect();

    startX = endX = scrollEl.scrollLeft;
    startY = endY = scrollEl.scrollTop;
    offsetX = startX + eDim.left - sDim.left;
    offsetY = startY + eDim.top - sDim.top;

    leftEdge = offsetX - (delta.left || 0);
    topEdge = offsetY - (delta.top || 0);
    rightEdge = offsetX + eDim.width - this.cache.clientW + (delta.right || 0);
    bottomEdge = offsetY + eDim.height - this.cache.clientH + (delta.bottom || 0);

    if(leftEdge < startX) { endX = leftEdge; }
    if(rightEdge > startX) { endX = rightEdge; }

    if(topEdge < startY) { endY = topEdge; }
    if(bottomEdge > startY) { endY = bottomEdge; }

    // animate
    this.animateScroll(startX, endX, startY, endY, +duration);
  },

  animateScroll: function (startX, endX, startY, endY, duration) {
    var self = this,
        scrollEl = this.scrollEl,
        startTime = Date.now();

    if(endX === startX && endY === startY) {
      return;
    }

    if(duration === 0) {
      scrollEl.scrollLeft = endX;
      scrollEl.scrollTop = endY;
      return;
    }

    if(isNaN(duration)) { // undefined or auto
      // 500px in 430ms, 1000px in 625ms, 2000px in 910ms
      duration = Math.pow(Math.max(Math.abs(endX - startX), Math.abs(endY - startY)), 0.54) * 15;
    }

    (function animate () {
      var time = Math.min(1, ((Date.now() - startTime) / duration)),
          easedTime = Utils.easingFunction(time);

      if(endY !== startY) {
        scrollEl.scrollTop = ~~(easedTime * (endY - startY)) + startY;
      }
      if(endX !== startX) {
        scrollEl.scrollLeft = ~~(easedTime * (endX - startX)) + startX;
      }

      self.scrollAnimation = time < 1 ? window.requestAnimationFrame(animate) : null;
    }());
  },

  destroy: function () {
    var self = this,
        element = this.element,
        scrollEl = this.scrollEl,
        listeners = this.listeners,
        child;

    if(!this.scrollEl) { return; }

    // unbind events
    for (var ev in listeners) {
      scrollEl.removeEventListener(ev, listeners[ev]);
    }

    // remove scrollbars elements
    _invoke(this.scrollbars, 'remove');

    // unwrap content
    if (this.settings.wrapContent) {
      while(child = scrollEl.childNodes[0]) {
        element.insertBefore(child, scrollEl);
      }
      element.removeChild(scrollEl);
      this.scrollEl = null;
    }

    // remove classes
    toggleClass(element, this.settings.classPrefix + 'prevent', false);
    toggleClass(element, 'is-enabled', false);

    // defer instance removal from global array
    // to not affect checkLoop _invoke
    window.requestAnimationFrame(function () {
      var index = G.instances.indexOf(self);
      if (index > -1) {
        G.instances.splice(index, 1);
      }
    });
  },

  fireCustomEvent: function (eventName) {
    var cache = this.cache,
        sH = cache.scrollH, sW = cache.scrollW,
        eventData;

    eventData = {
      // scrollbars data
      scrollbarV: _extend({}, cache.v),
      scrollbarH: _extend({}, cache.h),

      // scroll position
      scrollTop: cache.v.position * sH,
      scrollLeft: cache.h.position * sW,
      scrollBottom: (1 - cache.v.position - cache.v.size) * sH,
      scrollRight: (1 - cache.h.position - cache.h.size) * sW,

      // element size
      scrollWidth: sW,
      scrollHeight: sH,
      clientWidth: cache.clientW,
      clientHeight: cache.clientH,
    };

    var event;
    if (typeof CustomEvent === 'function') {
      event = new CustomEvent(eventName, { detail: eventData });
    } else { // IE does not support CustomEvent
      event = document.createEvent('CustomEvent');
      event.initCustomEvent(eventName, false, false, eventData);
    }
    this.element.dispatchEvent(event);
  },

};

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 peeracle contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// @exclude
var Peeracle = {
  DataStream: require('./dataStream'),
  Hash: require('./hash')
};
// @endexclude

/* eslint-disable */
Peeracle.MetadataStream = (function () {
  /* eslint-enable */
  /**
   * @class MetadataStream
   * @memberof {Peeracle}
   * @param {String} checksumAlgorithmName
   * @param {Media} media
   * @param {Uint8Array} bytes
   *
   * @property {String} checksumAlgorithmName
   * @property {Hash} checksumAlgorithm
   * @property {Media} media
   * @property {Number} type
   * @property {String} mimeType
   * @property {Number} bandwidth
   * @property {Number} width
   * @property {Number} height
   * @property {Number} numChannels
   * @property {Number} samplingFrequency
   * @property {Uint8Array} initSegment
   * @property {Number} chunkSize
   * @property {Array.<MetadataMediaSegment>} mediaSegments
   * @property {Number} averageSize
   * @constructor
   */
  function MetadataStream(checksumAlgorithmName, media, bytes) {
    var index;
    var count;
    var track;

    this.checksumAlgorithmName = checksumAlgorithmName;
    this.checksumAlgorithm = Peeracle.Hash.create(this.checksumAlgorithmName);
    if (!this.checksumAlgorithm) {
      throw new Error('Invalid checksum algorithm');
    }
    this.media = media;
    this.mimeType = media.mimeType;
    this.bandwidth = 0;
    this.initSegment = bytes;
    this.chunkSize = 0;
    this.mediaSegments = [];
    this.streamSize = 0;

    for (index = 0, count = media.tracks.length; index < count; ++index) {
      track = media.tracks[index];

      if ((track.type === 1 || track.type === 2) &&
        (this.type === 1 || this.type === 2) && this.type !== track.type) {
        this.type = 4;
      } else {
        this.type = track.type;
      }
      this.width = track.width !== -1 ? track.width : this.width;
      this.height = track.height !== -1 ? track.height : this.height;
      this.numChannels = track.channels !== -1 ?
        track.channels : this.numChannels;
      this.samplingFrequency = track.samplingFrequency !== -1 ?
        track.samplingFrequency : this.samplingFrequency;
    }
  }

  MetadataStream.HEADER_FIELDS = [
    {name: 'type', type: 'Byte'},
    {name: 'mimeType', type: 'String'},
    {name: 'bandwidth', type: 'UInteger'},
    {name: 'width', type: 'Integer'},
    {name: 'height', type: 'Integer'},
    {name: 'numChannels', type: 'Integer'},
    {name: 'samplingFrequency', type: 'Integer'},
    {name: 'chunkSize', type: 'Integer'}
    // {name: 'initSegmentLength', type: 'UInteger'},
    // {name: 'initSegment', type: 'Bytes'},
    // {name: 'mediaSegmentsCount', type: 'UInteger'},
    // {name: 'mediaSegments', type: 'MediaSegment'},
  ];

  MetadataStream.MEDIASEGMENT_FIELDS = [
    {name: 'timecode', type: 'UInteger'},
    {name: 'length', type: 'UInteger'}
    // {name: 'chunkCount', type: 'UInteger'},
    // {name: 'chunks', type: 'chunks'},
  ];

  /**
   * @function MetadataStream#addMediaSegments
   */
  MetadataStream.prototype.addMediaSegments = function addMediaSegments(cb) {
    var _this = this;
    var index = 0;
    var cues = this.media.cues['' + this.media.tracks[0].id];
    var timecodes = Object.keys(cues);
    var count = timecodes.length;
    var timecode = parseInt(timecodes[index], 10);

    this.calculateStreamSize_(cues);
    this.media.getMediaSegment(timecode,
      function getMediaSegmentCb(error, bytes) {
        /** @type {MetadataMediaSegment} */
        var mediaSegment = {};

        if (error) {
          cb(error);
          return;
        }

        mediaSegment.timecode = timecode;
        mediaSegment.length = bytes.length;
        mediaSegment.chunks = _this.chunkBytes_(bytes);

        _this.mediaSegments.push(mediaSegment);

        if (++index < count) {
          timecode = parseInt(timecodes[index], 10);
          _this.media.getMediaSegment(timecode,
            getMediaSegmentCb);
        } else {
          cb(null);
        }
      });
  };

  /**
   * @function MetadataStream#calculateStreamSize_
   * @param {Object.<String, Number>} cues
   */
  MetadataStream.prototype.calculateStreamSize_ =
    function calculateStreamSize_(cues) {
      var index;
      var currentOffset;
      var previousOffset = 0;
      var timecodes = Object.keys(cues);
      var count = timecodes.length;

      for (index = 0; index < count; ++index) {
        currentOffset = cues[timecodes[index]];
        this.streamSize += currentOffset - previousOffset;
        previousOffset = currentOffset;
      }

      for (index = 15; index < 20; ++index) {
        this.chunkSize = Math.pow(2, index);
        count = Math.ceil((this.streamSize + this.chunkSize - 1) /
          this.chunkSize);
        if (count < 255) {
          break;
        }
      }
    };

  /**
   * @function MetadataStream#chunkBytes_
   * @param {Uint8Array} bytes
   * @return {Array.<String>}
   * @private
   */
  MetadataStream.prototype.chunkBytes_ = function chunkBytes(bytes) {
    var index = 0;
    var length = bytes.length;
    var chunks = [];
    var chunk;
    var checksum;

    while (index < length) {
      chunk = bytes.subarray(index, index + this.chunkSize);
      checksum = this.checksumAlgorithm.checksum(chunk);
      chunks.push(checksum);
      index += chunk.length;
    }

    return chunks;
  };

  /**
   * @function MetadataStream#serializeChunks_
   * @param {Array.<Uint8Array>} chunks
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serializeChunks_ =
    function serializeChunks_(chunks, dataStream, cb) {
      var _this = this;
      var index = 0;
      var count = chunks.length;

      dataStream.writeUInteger(count, function writeChunksCount(error) {
        var chunk;

        if (error) {
          cb(error);
          return;
        }

        chunk = chunks[index];
        _this.checksumAlgorithm.constructor.serialize(chunk, dataStream,
          function writeChunkCb(err) {
            if (err) {
              cb(err);
              return;
            }

            if (++index < count) {
              chunk = chunks[index];
              _this.checksumAlgorithm.constructor.serialize(chunk, dataStream,
                writeChunkCb);
            } else {
              cb(null);
            }
          });
      });
    };

  /**
   * @function MetadataStream#serializeMediaSegments_
   * @param {MetadataMediaSegment} mediaSegment
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serializeMediaSegment_ =
    function serializeMediaSegment_(mediaSegment, dataStream, cb) {
      var field;
      var index = 0;
      var length = MetadataStream.MEDIASEGMENT_FIELDS.length;
      var _this = this;

      field = MetadataStream.MEDIASEGMENT_FIELDS[index];
      dataStream['write' + field.type](mediaSegment[field.name],
        function writeCb(error) {
          if (error) {
            cb(error);
            return;
          }

          if (++index < length) {
            field = MetadataStream.MEDIASEGMENT_FIELDS[index];
            dataStream['write' + field.type](mediaSegment[field.name], writeCb);
          } else {
            _this.serializeChunks_(mediaSegment.chunks, dataStream, cb);
          }
        });
    };

  /**
   * @function MetadataStream#serializeMediaSegments_
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serializeMediaSegments_ =
    function serializeMediaSegments_(dataStream, cb) {
      var _this = this;
      var count = this.mediaSegments.length;
      dataStream.writeUInteger(count,
        function writeMediaSegmentsCountCb(error) {
          var index = 0;
          var mediaSegment;

          if (error) {
            cb(error);
            return;
          }

          mediaSegment = _this.mediaSegments[index];
          _this.serializeMediaSegment_(mediaSegment, dataStream,
            function serializeMediaSegmentCb(err) {
              if (err) {
                cb(err);
                return;
              }

              if (++index < count) {
                mediaSegment = _this.mediaSegments[index];
                _this.serializeMediaSegment_(mediaSegment, dataStream,
                  serializeMediaSegmentCb);
              } else {
                cb(null);
              }
            });
        });
    };

  /**
   * @function MetadataStream#serializeInitSegment_
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serializeInitSegment_ =
    function serializeInitSegment_(dataStream, cb) {
      var _this = this;
      dataStream.writeUInteger(this.initSegment.length,
        function writeInitSegmentLengthCb(error) {
          if (error) {
            cb(error);
            return;
          }

          dataStream.write(_this.initSegment,
            function writeInitSegmentCb(err) {
              if (err) {
                cb(err);
                return;
              }

              _this.serializeMediaSegments_(dataStream, cb);
            });
        });
    };

  /**
   * @function MetadataStream#serialize
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serialize = function serialize(dataStream, cb) {
    var field;
    var index = 0;
    var length = MetadataStream.HEADER_FIELDS.length;
    var _this = this;

    if (!(dataStream instanceof Peeracle.DataStream)) {
      cb(new TypeError('argument must be a DataStream'));
      return;
    }

    field = MetadataStream.HEADER_FIELDS[index];
    dataStream['write' + field.type](this[field.name],
      function writeCb(error) {
        if (error) {
          cb(error);
          return;
        }

        if (++index < length) {
          field = MetadataStream.HEADER_FIELDS[index];
          dataStream['write' + field.type](_this[field.name], writeCb);
        } else {
          _this.serializeInitSegment_(dataStream, cb);
        }
      });
  };

  /**
   * @function MetadataStream#unserialize
   * @param {DataStream} dataStream
   * @return {Number}
   * @throws {TypeError}
   */
  MetadataStream.prototype.unserialize = function unserialize(dataStream) {
    if (!(dataStream instanceof Peeracle.DataStream)) {
      throw new TypeError('argument must be a DataStream');
    }

    return 0;
  };

  /**
   * @typedef {Object} MetadataMediaSegment
   * @property {Number} timecode
   * @property {Number} length
   * @property {Array.<Uint8Array>} chunks
   */

  return MetadataStream;
})();

// @exclude
module.exports = Peeracle.MetadataStream;
// @endexclude
<commit_msg>MetadataStream: Make the media and bytes arguments optional<commit_after>/*
 * Copyright (c) 2015 peeracle contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// @exclude
var Peeracle = {
  DataStream: require('./dataStream'),
  Hash: require('./hash')
};
// @endexclude

/* eslint-disable */
Peeracle.MetadataStream = (function () {
  /* eslint-enable */
  /**
   * @class MetadataStream
   * @memberof {Peeracle}
   * @param {String} checksumAlgorithmName
   * @param {Media=} media
   * @param {Uint8Array=} bytes
   *
   * @property {String} checksumAlgorithmName
   * @property {Hash} checksumAlgorithm
   * @property {Media} media
   * @property {Number} type
   * @property {String} mimeType
   * @property {Number} bandwidth
   * @property {Number} width
   * @property {Number} height
   * @property {Number} numChannels
   * @property {Number} samplingFrequency
   * @property {Uint8Array} initSegment
   * @property {Number} chunkSize
   * @property {Array.<MetadataMediaSegment>} mediaSegments
   * @property {Number} averageSize
   * @constructor
   */
  function MetadataStream(checksumAlgorithmName, media, bytes) {
    var index;
    var count;
    var track;

    this.checksumAlgorithmName = checksumAlgorithmName;
    this.checksumAlgorithm = Peeracle.Hash.create(this.checksumAlgorithmName);
    if (!this.checksumAlgorithm) {
      throw new Error('Invalid checksum algorithm');
    }
    this.media = media ? media : null;
    this.bandwidth = 0;
    this.initSegment = bytes ? bytes : null;
    this.chunkSize = 0;
    this.mediaSegments = [];
    this.streamSize = 0;

    this.type = -1;
    this.mimeType = null;
    this.width = -1;
    this.height = -1;
    this.numChannels = -1;
    this.samplingFrequency = -1;

    if (!media) {
      return;
    }

    this.mimeType = media.mimeType;
    for (index = 0, count = media.tracks.length; index < count; ++index) {
      track = media.tracks[index];

      if ((track.type === 1 || track.type === 2) &&
        (this.type === 1 || this.type === 2) && this.type !== track.type) {
        this.type = 4;
      } else {
        this.type = track.type;
      }
      this.width = track.width !== -1 ? track.width : this.width;
      this.height = track.height !== -1 ? track.height : this.height;
      this.numChannels = track.channels !== -1 ?
        track.channels : this.numChannels;
      this.samplingFrequency = track.samplingFrequency !== -1 ?
        track.samplingFrequency : this.samplingFrequency;
    }
  }

  MetadataStream.HEADER_FIELDS = [
    {name: 'type', type: 'Byte'},
    {name: 'mimeType', type: 'String'},
    {name: 'bandwidth', type: 'UInteger'},
    {name: 'width', type: 'Integer'},
    {name: 'height', type: 'Integer'},
    {name: 'numChannels', type: 'Integer'},
    {name: 'samplingFrequency', type: 'Integer'},
    {name: 'chunkSize', type: 'Integer'}
    // {name: 'initSegmentLength', type: 'UInteger'},
    // {name: 'initSegment', type: 'Bytes'},
    // {name: 'mediaSegmentsCount', type: 'UInteger'},
    // {name: 'mediaSegments', type: 'MediaSegment'},
  ];

  MetadataStream.MEDIASEGMENT_FIELDS = [
    {name: 'timecode', type: 'UInteger'},
    {name: 'length', type: 'UInteger'}
    // {name: 'chunkCount', type: 'UInteger'},
    // {name: 'chunks', type: 'chunks'},
  ];

  /**
   * @function MetadataStream#addMediaSegments
   */
  MetadataStream.prototype.addMediaSegments = function addMediaSegments(cb) {
    var _this = this;
    var index = 0;
    var cues = this.media.cues['' + this.media.tracks[0].id];
    var timecodes = Object.keys(cues);
    var count = timecodes.length;
    var timecode = parseInt(timecodes[index], 10);

    this.calculateStreamSize_(cues);
    this.media.getMediaSegment(timecode,
      function getMediaSegmentCb(error, bytes) {
        /** @type {MetadataMediaSegment} */
        var mediaSegment = {};

        if (error) {
          cb(error);
          return;
        }

        mediaSegment.timecode = timecode;
        mediaSegment.length = bytes.length;
        mediaSegment.chunks = _this.chunkBytes_(bytes);

        _this.mediaSegments.push(mediaSegment);

        if (++index < count) {
          timecode = parseInt(timecodes[index], 10);
          _this.media.getMediaSegment(timecode,
            getMediaSegmentCb);
        } else {
          cb(null);
        }
      });
  };

  /**
   * @function MetadataStream#calculateStreamSize_
   * @param {Object.<String, Number>} cues
   */
  MetadataStream.prototype.calculateStreamSize_ =
    function calculateStreamSize_(cues) {
      var index;
      var currentOffset;
      var previousOffset = 0;
      var timecodes = Object.keys(cues);
      var count = timecodes.length;

      for (index = 0; index < count; ++index) {
        currentOffset = cues[timecodes[index]];
        this.streamSize += currentOffset - previousOffset;
        previousOffset = currentOffset;
      }

      for (index = 15; index < 20; ++index) {
        this.chunkSize = Math.pow(2, index);
        count = Math.ceil((this.streamSize + this.chunkSize - 1) /
          this.chunkSize);
        if (count < 255) {
          break;
        }
      }
    };

  /**
   * @function MetadataStream#chunkBytes_
   * @param {Uint8Array} bytes
   * @return {Array.<String>}
   * @private
   */
  MetadataStream.prototype.chunkBytes_ = function chunkBytes(bytes) {
    var index = 0;
    var length = bytes.length;
    var chunks = [];
    var chunk;
    var checksum;

    while (index < length) {
      chunk = bytes.subarray(index, index + this.chunkSize);
      checksum = this.checksumAlgorithm.checksum(chunk);
      chunks.push(checksum);
      index += chunk.length;
    }

    return chunks;
  };

  /**
   * @function MetadataStream#serializeChunks_
   * @param {Array.<Uint8Array>} chunks
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serializeChunks_ =
    function serializeChunks_(chunks, dataStream, cb) {
      var _this = this;
      var index = 0;
      var count = chunks.length;

      dataStream.writeUInteger(count, function writeChunksCount(error) {
        var chunk;

        if (error) {
          cb(error);
          return;
        }

        chunk = chunks[index];
        _this.checksumAlgorithm.constructor.serialize(chunk, dataStream,
          function writeChunkCb(err) {
            if (err) {
              cb(err);
              return;
            }

            if (++index < count) {
              chunk = chunks[index];
              _this.checksumAlgorithm.constructor.serialize(chunk, dataStream,
                writeChunkCb);
            } else {
              cb(null);
            }
          });
      });
    };

  /**
   * @function MetadataStream#serializeMediaSegments_
   * @param {MetadataMediaSegment} mediaSegment
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serializeMediaSegment_ =
    function serializeMediaSegment_(mediaSegment, dataStream, cb) {
      var field;
      var index = 0;
      var length = MetadataStream.MEDIASEGMENT_FIELDS.length;
      var _this = this;

      field = MetadataStream.MEDIASEGMENT_FIELDS[index];
      dataStream['write' + field.type](mediaSegment[field.name],
        function writeCb(error) {
          if (error) {
            cb(error);
            return;
          }

          if (++index < length) {
            field = MetadataStream.MEDIASEGMENT_FIELDS[index];
            dataStream['write' + field.type](mediaSegment[field.name], writeCb);
          } else {
            _this.serializeChunks_(mediaSegment.chunks, dataStream, cb);
          }
        });
    };

  /**
   * @function MetadataStream#serializeMediaSegments_
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serializeMediaSegments_ =
    function serializeMediaSegments_(dataStream, cb) {
      var _this = this;
      var count = this.mediaSegments.length;
      dataStream.writeUInteger(count,
        function writeMediaSegmentsCountCb(error) {
          var index = 0;
          var mediaSegment;

          if (error) {
            cb(error);
            return;
          }

          mediaSegment = _this.mediaSegments[index];
          _this.serializeMediaSegment_(mediaSegment, dataStream,
            function serializeMediaSegmentCb(err) {
              if (err) {
                cb(err);
                return;
              }

              if (++index < count) {
                mediaSegment = _this.mediaSegments[index];
                _this.serializeMediaSegment_(mediaSegment, dataStream,
                  serializeMediaSegmentCb);
              } else {
                cb(null);
              }
            });
        });
    };

  /**
   * @function MetadataStream#serializeInitSegment_
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serializeInitSegment_ =
    function serializeInitSegment_(dataStream, cb) {
      var _this = this;
      dataStream.writeUInteger(this.initSegment.length,
        function writeInitSegmentLengthCb(error) {
          if (error) {
            cb(error);
            return;
          }

          dataStream.write(_this.initSegment,
            function writeInitSegmentCb(err) {
              if (err) {
                cb(err);
                return;
              }

              _this.serializeMediaSegments_(dataStream, cb);
            });
        });
    };

  /**
   * @function MetadataStream#serialize
   * @param {Peeracle.DataStream} dataStream
   * @param {Metadata~genericCallback} cb
   */
  MetadataStream.prototype.serialize = function serialize(dataStream, cb) {
    var field;
    var index = 0;
    var length = MetadataStream.HEADER_FIELDS.length;
    var _this = this;

    if (!(dataStream instanceof Peeracle.DataStream)) {
      cb(new TypeError('argument must be a DataStream'));
      return;
    }

    field = MetadataStream.HEADER_FIELDS[index];
    dataStream['write' + field.type](this[field.name],
      function writeCb(error) {
        if (error) {
          cb(error);
          return;
        }

        if (++index < length) {
          field = MetadataStream.HEADER_FIELDS[index];
          dataStream['write' + field.type](_this[field.name], writeCb);
        } else {
          _this.serializeInitSegment_(dataStream, cb);
        }
      });
  };

  /**
   * @function MetadataStream#unserialize
   * @param {DataStream} dataStream
   * @return {Number}
   * @throws {TypeError}
   */
  MetadataStream.prototype.unserialize = function unserialize(dataStream) {
    if (!(dataStream instanceof Peeracle.DataStream)) {
      throw new TypeError('argument must be a DataStream');
    }

    return 0;
  };

  /**
   * @typedef {Object} MetadataMediaSegment
   * @property {Number} timecode
   * @property {Number} length
   * @property {Array.<Uint8Array>} chunks
   */

  return MetadataStream;
})();

// @exclude
module.exports = Peeracle.MetadataStream;
// @endexclude
<|endoftext|>


<commit_before>// @flow
import getValueAndUnit from '../helpers/getValueAndUnit'

/**
 * Returns a CSS calc formula for linear interpolation of a property between two values. Accepts optional minScreen (defaults to '320px') and maxScreen (defaults to '1200px').
 *
 * @example
 * // Styles as object usage
 * const styles = {
 *   fontSize: between('20px', '100px', '400px', '1000px'),
 *   fontSize: between('20px', '100px')
 * }
 *
 * // styled-components usage
 * const div = styled.div`
 *   fontSize: ${fontSize: between('20px', '100px', '400px', '1000px')};
 *   fontSize: ${fontSize: between('20px', '100px')}
 * `
 *
 * // CSS as JS Output
 *
 * h1: {
 *   'fontSize': 'calc(-33.33333333333334px + 13.333333333333334vw)',
 *   'fontSize': 'calc(-9.090909090909093px + 9.090909090909092vw)'
 * }
 */
function between(
  fromSize: string,
  toSize: string,
  minScreen?: string = '320px',
  maxScreen?: string = '1200px',
): string {
  const [unitlessFromSize, fromSizeUnit] = getValueAndUnit(fromSize)
  const [unitlessToSize, toSizeUnit] = getValueAndUnit(toSize)
  const [unitlessMinScreen, minScreenUnit] = getValueAndUnit(minScreen)
  const [unitlessMaxScreen, maxScreenUnit] = getValueAndUnit(maxScreen)

  if (
    typeof unitlessMinScreen !== 'number'
    || typeof unitlessMaxScreen !== 'number'
    || !minScreenUnit
    || !maxScreenUnit
    || minScreenUnit !== maxScreenUnit
  ) {
    throw new Error(
      'minScreen and maxScreen must be provided as stringified numbers with the same units.',
    )
  }

  if (
    typeof unitlessFromSize !== 'number'
    || typeof unitlessToSize !== 'number'
    || !fromSizeUnit
    || !toSizeUnit
    || fromSizeUnit !== toSizeUnit
  ) {
    throw new Error(
      'fromSize and toSize must be provided as stringified numbers with the same units.',
    )
  }

  const slope = (unitlessFromSize - unitlessToSize)
    / (unitlessMinScreen - unitlessMaxScreen)
  const base = unitlessToSize - slope * unitlessMaxScreen
  return `calc(${base.toFixed(2)}${fromSizeUnit} + ${(100 * slope).toFixed(
    2,
  )}vw)`
}

export default between
<commit_msg>Fix syntax error<commit_after>// @flow
import getValueAndUnit from '../helpers/getValueAndUnit'

/**
 * Returns a CSS calc formula for linear interpolation of a property between two values. Accepts optional minScreen (defaults to '320px') and maxScreen (defaults to '1200px').
 *
 * @example
 * // Styles as object usage
 * const styles = {
 *   fontSize: between('20px', '100px', '400px', '1000px'),
 *   fontSize: between('20px', '100px')
 * }
 *
 * // styled-components usage
 * const div = styled.div`
 *   fontSize: ${between('20px', '100px', '400px', '1000px')};
 *   fontSize: ${between('20px', '100px')}
 * `
 *
 * // CSS as JS Output
 *
 * h1: {
 *   'fontSize': 'calc(-33.33333333333334px + 13.333333333333334vw)',
 *   'fontSize': 'calc(-9.090909090909093px + 9.090909090909092vw)'
 * }
 */
function between(
  fromSize: string,
  toSize: string,
  minScreen?: string = '320px',
  maxScreen?: string = '1200px',
): string {
  const [unitlessFromSize, fromSizeUnit] = getValueAndUnit(fromSize)
  const [unitlessToSize, toSizeUnit] = getValueAndUnit(toSize)
  const [unitlessMinScreen, minScreenUnit] = getValueAndUnit(minScreen)
  const [unitlessMaxScreen, maxScreenUnit] = getValueAndUnit(maxScreen)

  if (
    typeof unitlessMinScreen !== 'number'
    || typeof unitlessMaxScreen !== 'number'
    || !minScreenUnit
    || !maxScreenUnit
    || minScreenUnit !== maxScreenUnit
  ) {
    throw new Error(
      'minScreen and maxScreen must be provided as stringified numbers with the same units.',
    )
  }

  if (
    typeof unitlessFromSize !== 'number'
    || typeof unitlessToSize !== 'number'
    || !fromSizeUnit
    || !toSizeUnit
    || fromSizeUnit !== toSizeUnit
  ) {
    throw new Error(
      'fromSize and toSize must be provided as stringified numbers with the same units.',
    )
  }

  const slope = (unitlessFromSize - unitlessToSize)
    / (unitlessMinScreen - unitlessMaxScreen)
  const base = unitlessToSize - slope * unitlessMaxScreen
  return `calc(${base.toFixed(2)}${fromSizeUnit} + ${(100 * slope).toFixed(
    2,
  )}vw)`
}

export default between
<|endoftext|>


<commit_before>'use strict';
var EVENT = require('./model').socketEvents;

// Every new tool will have these defaults settings
// Can be changed by user for her preferences later
var Tools = {
  // Currently selected tool from the ToolBar
  selected: '',
  importer: {
    imageUrl: '',
    maxSize: 5
  },
  fill: {
    fillColor: 0xFF0000
  },
  pencil: {
    fillColor: 0x000000,
    strokeWidth: 1,
    lineColor: 0x000000,
    lineWidth: 2,
    lineAlpha: 1

  },
  select: {
    clickedObject: false,
    selectedObject: null
  },
  line: {
    lineColor: 0x000000,
    lineWidth: 1,
    lineAlpha: 1
  },
  rectangle: {
    lineColor: 0x000000,
    lineWidth: 1,
    lineAlpha: 1,
    fillColor: 0x913ce6,
    fillAlpha: 1
  },
  ellipse: {
    fillColor: 0xFFFFFF,
    strokeColor: 0x000000,
    strokeWidth: 1
  },
  text: {
    // Text Properties
    fontSize: 12,
    fontFamily: 'Arial',
    stroke: 0xff1010,
    align: 'left',
    strokeThickness: 1,
    wordWrap: true,
    wordWrapWidth: 500,

    // Rectangle class properties
    // lineColor: 0x000000,
    // lineWidth: 1,
    // lineAlpha: 1,
    // fillColor: 0xFFFFFF,
    // fillAlpha: 1
    // {font : '24px Arial',
    // fill : 0xff1010,
    // align : 'center'}
  },
  templates: {
    lineColor: 0x000000,
    lineWidth: 1,
    lineAlpha: 1,
    fillColor: 0xFFFFFF,
    fillAlpha: 1
  },
  table: {
    lineColor: 0x000000,
    lineWidth: 1,
    lineAlpha: 1,
    fillColor: 0xFFFFFF,
    fillAlpha: 1
  },
  uml: {}
};

/**
 * Shapes holds all the Drawn objects on Canvas and stage, but it organizes
 * it by hashkeys (ObjectIds), this will ensure each Shape created can be uniquely
 * identified and quick to access
 */
var Shapes = {
  addNew: addNew,
  removeShape: removeShape,
  removeShapeByID: removeShapeByID,
  _shapeTypes: {
    'pencil': 0,
    'line': 0,
    'rectangle': 0,
    'ellipse': 0
  },
  _shapes: {},
  _order: [],
  hashKeys: ['#', '@', '&', '*', '%'] // These are scrambler characters to make Key more unique
};

Object.defineProperty(Shapes, 'originalUser', {
  get: function() {
    return AppState.Users.currentUser._id || 'unknown';
  }
})
// Methods for User Layer
// function insertAt(shape, index) {
//   var oldIndex = 0;
//   // Check if shape exists already
//   if(this._shapes[shape._id]) {
//     oldIndex = this._shapes.layerLevel;
//   }
// }

// function removeAt() {}
// function reorder(start, end) {
//   var orderedArray = this._order;
//   var i = start;
// }

// Use test case to ensure userId, canvasID and Object Type are set
// layerLevel is optional parameter
function addNew(shapeObject, layerLevel) {
  // increment the number of Shapes of this type
  var shapeCount = this._shapeTypes[shapeObject.shapeType];

  // Used for scrambling the hash,
  // ie. hashKeys[keyIndex]
  var keyIndex = 0;

  shapeObject.originalUserId = shapeObject.originalUserId || this.originalUser;
  shapeObject.currentUserId = shapeObject.originalUserId;

  // Increment the count of Shapes of this type that have been drawn
  if(!isNaN(shapeCount)) {
    shapeCount++;
  }
  else {
    shapeCount = 0;
  }

  // Create Unique key
  shapeObject._id = '#_' + shapeObject.shapeType +
                    shapeCount +
                    shapeObject.originalUserId.substr(0,3);

  // Loop and attempt to create a unqiue key for this shape
  while(this[shapeObject._id]) {
    shapeCount = shapeCount%2 === 0 ? shapeCount + 1
                                    : shapeCount;
    shapeObject._id = shapeObject._id + this.hashKeys[keyIndex] + shapeCount;
    keyIndex = ++keyIndex%5;
  }

  // Set the layer level of this Shape, ie. this is its stage level on Pixi stage
  shapeObject.layerLevel = layerLevel || this.stage.children.length;

  // Set object in Shape Map
  this[shapeObject._id] = shapeObject;

  // Add stage/layer level the shape will be inserted at
  this.stage.addChildAt(shapeObject.getGraphics(), shapeObject.layerLevel);

  // Set the number of Shapes of this type that have been drawn so far
  this._shapeTypes[shapeObject.shapeType] = shapeCount;

  return shapeObject;
}

// Removes shape based on id
function removeShapeByID(id) {
  var shape = this[id];
  if(shape) {
    this._shapeTypes[shape.shapeType]--;

    this.stage.removeChildAt(shape.layerLevel);

    this[id] = null;
  }
}

// Removes entire shape by reference
function removeShape(shapeObject) {
  this.removeShapeByID(shapeObject._id);
}

// AppState Main Object
var AppState = {
  Canvas: {
    _stage: null, // private property, accessed through getter AppState.Canvas.stage, set value by AppState.Canvas.stage = new PIXI.Stage(color)
    renderer: null,
    settings: {
      maxUsers: 0,
      canDraw: true,
      canChat: true
    },
    Shapes: Shapes
  },
  Tools: Object.preventExtensions(Tools),
  Users: {
    currentUser: {},
    users: [], // index 0 is always for Head
    getUserById: function(id) {
      var matchedUser;
      this.users.some(function(user) {
        if(id === user._id) {
          matchedUser = user;
          return true;
        }
        return false;
      })

      return matchedUser;
    }
  },
  Settings: {}, // General settings, ie. styles or themes
  Messages: [],
  Socket: null // Will be added later, in toolbar js or AppState.init method
};

// Defines a more specific setter and getter for Canvas stage
Object.defineProperty(AppState.Canvas, "stage", {

  get: function () {
    return this._stage;
  },

  set: function (stage) {
    this._stage = stage;
    this.Shapes.stage = stage;
  }
});

// Preferred way of initiatializing the AppState, should be done early and seperate
// Currently initialization is done in toolbar.js
Object.defineProperty(AppState, 'init', {
  // Pixi library instance, Socket instance, HTML div container
  value: function(PIXI, Socket, Container) {
    var _this = this;
    var stage = new PIXI.Stage(0xFFFFFF, true);
    var renderer = new PIXI.CanvasRenderer(document.body.offsetWidth * 0.75,
                                           document.body.offsetHeight  - 60,
                                           { antialias: true });

    PIXI.dontSayHello = true;

    this.Canvas.stage = stage;
    this.Canvas.renderer = renderer;
    this.Socket = Socket;
    this.Canvas.Shapes.stage = stage;
    this.Canvas.Shapes.socket = Socket;

    Container.appendChild(renderer.view);

    // Start the render loop
    animate();

    function animate() {
      requestAnimationFrame(animate);
      renderer.render(stage);
    }
  }
});

module.exports = AppState;

<commit_msg>changed Rect's fill color to white<commit_after>'use strict';
var EVENT = require('./model').socketEvents;

// Every new tool will have these defaults settings
// Can be changed by user for her preferences later
var Tools = {
  // Currently selected tool from the ToolBar
  selected: '',
  importer: {
    imageUrl: '',
    maxSize: 5
  },
  fill: {
    fillColor: 0xFF0000
  },
  pencil: {
    fillColor: 0x000000,
    strokeWidth: 1,
    lineColor: 0x000000,
    lineWidth: 2,
    lineAlpha: 1

  },
  select: {
    clickedObject: false,
    selectedObject: null
  },
  line: {
    lineColor: 0x000000,
    lineWidth: 1,
    lineAlpha: 1
  },
  rectangle: {
    lineColor: 0x000000,
    lineWidth: 1,
    lineAlpha: 1,
    fillColor: 0xFFFFFF,
    fillAlpha: 1
  },
  ellipse: {
    fillColor: 0xFFFFFF,
    strokeColor: 0x000000,
    strokeWidth: 1
  },
  text: {
    // Text Properties
    fontSize: 12,
    fontFamily: 'Arial',
    stroke: 0xff1010,
    align: 'left',
    strokeThickness: 1,
    wordWrap: true,
    wordWrapWidth: 500,

    // Rectangle class properties
    // lineColor: 0x000000,
    // lineWidth: 1,
    // lineAlpha: 1,
    // fillColor: 0xFFFFFF,
    // fillAlpha: 1
    // {font : '24px Arial',
    // fill : 0xff1010,
    // align : 'center'}
  },
  templates: {
    lineColor: 0x000000,
    lineWidth: 1,
    lineAlpha: 1,
    fillColor: 0xFFFFFF,
    fillAlpha: 1
  },
  table: {
    lineColor: 0x000000,
    lineWidth: 1,
    lineAlpha: 1,
    fillColor: 0xFFFFFF,
    fillAlpha: 1
  },
  uml: {}
};

/**
 * Shapes holds all the Drawn objects on Canvas and stage, but it organizes
 * it by hashkeys (ObjectIds), this will ensure each Shape created can be uniquely
 * identified and quick to access
 */
var Shapes = {
  addNew: addNew,
  removeShape: removeShape,
  removeShapeByID: removeShapeByID,
  _shapeTypes: {
    'pencil': 0,
    'line': 0,
    'rectangle': 0,
    'ellipse': 0
  },
  _shapes: {},
  _order: [],
  hashKeys: ['#', '@', '&', '*', '%'] // These are scrambler characters to make Key more unique
};

Object.defineProperty(Shapes, 'originalUser', {
  get: function() {
    return AppState.Users.currentUser._id || 'unknown';
  }
})
// Methods for User Layer
// function insertAt(shape, index) {
//   var oldIndex = 0;
//   // Check if shape exists already
//   if(this._shapes[shape._id]) {
//     oldIndex = this._shapes.layerLevel;
//   }
// }

// function removeAt() {}
// function reorder(start, end) {
//   var orderedArray = this._order;
//   var i = start;
// }

// Use test case to ensure userId, canvasID and Object Type are set
// layerLevel is optional parameter
function addNew(shapeObject, layerLevel) {
  // increment the number of Shapes of this type
  var shapeCount = this._shapeTypes[shapeObject.shapeType];

  // Used for scrambling the hash,
  // ie. hashKeys[keyIndex]
  var keyIndex = 0;

  shapeObject.originalUserId = shapeObject.originalUserId || this.originalUser;
  shapeObject.currentUserId = shapeObject.originalUserId;

  // Increment the count of Shapes of this type that have been drawn
  if(!isNaN(shapeCount)) {
    shapeCount++;
  }
  else {
    shapeCount = 0;
  }

  // Create Unique key
  shapeObject._id = '#_' + shapeObject.shapeType +
                    shapeCount +
                    shapeObject.originalUserId.substr(0,3);

  // Loop and attempt to create a unqiue key for this shape
  while(this[shapeObject._id]) {
    shapeCount = shapeCount%2 === 0 ? shapeCount + 1
                                    : shapeCount;
    shapeObject._id = shapeObject._id + this.hashKeys[keyIndex] + shapeCount;
    keyIndex = ++keyIndex%5;
  }

  // Set the layer level of this Shape, ie. this is its stage level on Pixi stage
  shapeObject.layerLevel = layerLevel || this.stage.children.length;

  // Set object in Shape Map
  this[shapeObject._id] = shapeObject;

  // Add stage/layer level the shape will be inserted at
  this.stage.addChildAt(shapeObject.getGraphics(), shapeObject.layerLevel);

  // Set the number of Shapes of this type that have been drawn so far
  this._shapeTypes[shapeObject.shapeType] = shapeCount;

  return shapeObject;
}

// Removes shape based on id
function removeShapeByID(id) {
  var shape = this[id];
  if(shape) {
    this._shapeTypes[shape.shapeType]--;

    this.stage.removeChildAt(shape.layerLevel);

    this[id] = null;
  }
}

// Removes entire shape by reference
function removeShape(shapeObject) {
  this.removeShapeByID(shapeObject._id);
}

// AppState Main Object
var AppState = {
  Canvas: {
    _stage: null, // private property, accessed through getter AppState.Canvas.stage, set value by AppState.Canvas.stage = new PIXI.Stage(color)
    renderer: null,
    settings: {
      maxUsers: 0,
      canDraw: true,
      canChat: true
    },
    Shapes: Shapes
  },
  Tools: Object.preventExtensions(Tools),
  Users: {
    currentUser: {},
    users: [], // index 0 is always for Head
    getUserById: function(id) {
      var matchedUser;
      this.users.some(function(user) {
        if(id === user._id) {
          matchedUser = user;
          return true;
        }
        return false;
      })

      return matchedUser;
    }
  },
  Settings: {}, // General settings, ie. styles or themes
  Messages: [],
  Socket: null // Will be added later, in toolbar js or AppState.init method
};

// Defines a more specific setter and getter for Canvas stage
Object.defineProperty(AppState.Canvas, "stage", {

  get: function () {
    return this._stage;
  },

  set: function (stage) {
    this._stage = stage;
    this.Shapes.stage = stage;
  }
});

// Preferred way of initiatializing the AppState, should be done early and seperate
// Currently initialization is done in toolbar.js
Object.defineProperty(AppState, 'init', {
  // Pixi library instance, Socket instance, HTML div container
  value: function(PIXI, Socket, Container) {
    var _this = this;
    var stage = new PIXI.Stage(0xFFFFFF, true);
    var renderer = new PIXI.CanvasRenderer(document.body.offsetWidth * 0.75,
                                           document.body.offsetHeight  - 60,
                                           { antialias: true });

    PIXI.dontSayHello = true;

    this.Canvas.stage = stage;
    this.Canvas.renderer = renderer;
    this.Socket = Socket;
    this.Canvas.Shapes.stage = stage;
    this.Canvas.Shapes.socket = Socket;

    Container.appendChild(renderer.view);

    // Start the render loop
    animate();

    function animate() {
      requestAnimationFrame(animate);
      renderer.render(stage);
    }
  }
});

module.exports = AppState;

<|endoftext|>


<commit_before>'use strict';

let webpack = require('webpack');

let Config = require('./Config.js'),
    ExtractTextPlugin = require("extract-text-webpack-plugin");

class Project {
    constructor(cwd) {
        this.cwd = cwd;
        this.config = new Config(cwd);
        this.extraCommands = [];
        this.middlewares = [];
    }
    readConfig(options) {
        this.options = options = options || {};
        this.configFile = globby.sync('ykit.*.js', {
            cwd: this.cwd
        })[0];
        if (!this.configFile) {
            if (!options.noCheck) {
                error('没有找到 ykit 配置文件！');
            }
            return this;
        }
        this.extendConfig = this.configFile.match(/ykit\.([\w\.]+)\.js/)[1].replace(/\./g, '-');
        if (this.extendConfig != 'config') {
            let modulePath = sysPath.join(this.cwd, 'node_modules', 'ykit-config-' + this.extendConfig),
                extended = false;
            if (fs.existsSync(modulePath)) {
                let module = require(modulePath);
                if (module.config) {
                    extended = true;
                    module.config(this.config, options, this.cwd);
                    this.extraCommands = this.extraCommands.concat(module.commands || []);
                    if (module.middlewares) {
                        this.middlewares = module.middlewares;
                    }
                }
            } else {
                try {
                    let module = require('ykit-config-' + this.extendConfig);
                    if (module.config) {
                        extended = true;
                        module.config(this.config, options, this.cwd);
                        this.extraCommands = this.extraCommands.concat(module.commands || []);
                        if (module.middlewares) {
                            this.middlewares = module.middlewares;
                        }
                    }
                } catch (e) {}
            }
            if (!extended) {
                error('没有找到 ykit-config-' + this.extendConfig + ' 配置模块！');
                return this;
            }
        }

        let configMethod = require(sysPath.join(this.cwd, this.configFile));

        if (!_.isFunction(configMethod.config)) {
            error(this.configFile + ' 没有 exports 正确的方法！');
            return this;
        }

        configMethod.config(this.config, options, this.cwd);
        this.extraCommands = this.extraCommands.concat(configMethod.commands || []);
        if (configMethod.middlewares) {
            this.middlewares = configMethod.middlewares;
        }

        if (this.config._config.output.path[0] != '/') {
            this.config.setOutput({
                path: sysPath.join(this.cwd, this.config._config.output.path)
            });
        }

        return this;
    }
    check() {
        return !!this.configFile;
    }
    fixCss() {
        let config = this.config.getConfig(),
            entry = config.entry,
            fps = [];

        for (let key in entry) {
            let extName = sysPath.extname(entry[key]);
            if (this.config._cssExtNames.indexOf(extName) > -1) {
                let name = sysPath.basename(entry[key], extName),
                    np = entry[key] = entry[key] + '.js',
                    fp = sysPath.join(config.context, np);
                fs.writeFileSync(fp, 'require("./' + name + extName + '");', 'utf-8');
                fps.push(fp);
            }
        }

        config.plugins.push(new ExtractTextPlugin(config.output.filename.replace('[ext]', '.css')));

        return fps;
    }
    pack(callback) {
        let config = this.config.getConfig(),
            fps = this.fixCss();

        if (this.options.min) {
            config.plugins.push(new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false
                }
            }));
        }

        console.log(config.module.loaders);
        webpack(config, function() {
            globby.sync('**/*.cache', {
                cwd: config.output.path
            })
            .map((p) => sysPath.join(config.output.path, p))
            .concat(fps)
            .forEach((fp) => fs.unlinkSync(fp));
            callback();
        });

        return this;
    }
    getCompiler() {
        this.fixCss();
        return webpack(this.config.getConfig());
    }
}

module.exports = Project;
<commit_msg>update<commit_after>'use strict';

let webpack = require('webpack');

let Config = require('./Config.js'),
    ExtractTextPlugin = require("extract-text-webpack-plugin");

class Project {
    constructor(cwd) {
        this.cwd = cwd;
        this.config = new Config(cwd);
        this.extraCommands = [];
        this.middlewares = [];
    }
    readConfig(options) {
        this.options = options = options || {};
        this.configFile = globby.sync('ykit.*.js', {
            cwd: this.cwd
        })[0];
        if (!this.configFile) {
            if (!options.noCheck) {
                error('没有找到 ykit 配置文件！');
            }
            return this;
        }
        this.extendConfig = this.configFile.match(/ykit\.([\w\.]+)\.js/)[1].replace(/\./g, '-');
        if (this.extendConfig != 'config') {
            let modulePath = sysPath.join(this.cwd, 'node_modules', 'ykit-config-' + this.extendConfig),
                extended = false;
            if (fs.existsSync(modulePath)) {
                let module = require(modulePath);
                if (module.config) {
                    extended = true;
                    module.config(this.config, options, this.cwd);
                    this.extraCommands = this.extraCommands.concat(module.commands || []);
                    if (module.middlewares) {
                        this.middlewares = module.middlewares;
                    }
                }
            } else {
                try {
                    let module = require('ykit-config-' + this.extendConfig);
                    if (module.config) {
                        extended = true;
                        module.config(this.config, options, this.cwd);
                        this.extraCommands = this.extraCommands.concat(module.commands || []);
                        if (module.middlewares) {
                            this.middlewares = module.middlewares;
                        }
                    }
                } catch (e) {}
            }
            if (!extended) {
                error('没有找到 ykit-config-' + this.extendConfig + ' 配置模块！');
                return this;
            }
        }

        let configMethod = require(sysPath.join(this.cwd, this.configFile));

        if (!_.isFunction(configMethod.config)) {
            error(this.configFile + ' 没有 exports 正确的方法！');
            return this;
        }

        configMethod.config(this.config, options, this.cwd);
        this.extraCommands = this.extraCommands.concat(configMethod.commands || []);
        if (configMethod.middlewares) {
            this.middlewares = configMethod.middlewares;
        }

        if (this.config._config.output.path[0] != '/') {
            this.config.setOutput({
                path: sysPath.join(this.cwd, this.config._config.output.path)
            });
        }

        return this;
    }
    check() {
        return !!this.configFile;
    }
    fixCss() {
        let config = this.config.getConfig(),
            entry = config.entry,
            fps = [];

        for (let key in entry) {
            let extName = sysPath.extname(entry[key]);
            if (this.config._cssExtNames.indexOf(extName) > -1) {
                let name = sysPath.basename(entry[key], extName),
                    np = entry[key] = entry[key] + '.js',
                    fp = sysPath.join(config.context, np);
                fs.writeFileSync(fp, 'require("./' + name + extName + '");', 'utf-8');
                fps.push(fp);
            }
        }

        config.plugins.push(new ExtractTextPlugin(config.output.filename.replace('[ext]', '.css')));

        return fps;
    }
    pack(callback) {
        let config = this.config.getConfig(),
            fps = this.fixCss();

        if (this.options.min) {
            config.plugins.push(new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false
                }
            }));
        }

        webpack(config, function() {
            globby.sync('**/*.cache', {
                cwd: config.output.path
            })
            .map((p) => sysPath.join(config.output.path, p))
            .concat(fps)
            .forEach((fp) => fs.unlinkSync(fp));
            callback();
        });

        return this;
    }
    getCompiler() {
        this.fixCss();
        return webpack(this.config.getConfig());
    }
}

module.exports = Project;
<|endoftext|>


<commit_before>export default function(mongoose) {
  const Schema = mongoose.Schema;

  const historySchema = new Schema({
    'user': { 'type': Schema.Types.ObjectId, 'ref': 'User', 'required': true },
    'media': { 'type': Schema.Types.ObjectId, 'ref': 'Media', 'required': true },
    'playlist': { 'type': Schema.Types.ObjectId, 'ref': 'Playlist', 'required': true },
    'played': { 'type': Date, 'default': Date.now, 'required': true },
    'upvotes': [Number],
    'downvotes': [Number],
    'favorites': [Number]
  }, {
    'minimize': false
  });

  return mongoose.model('History', historySchema);
}
<commit_msg>remove require from played<commit_after>export default function(mongoose) {
  const Schema = mongoose.Schema;

  const historySchema = new Schema({
    'user': { 'type': Schema.Types.ObjectId, 'ref': 'User', 'required': true },
    'media': { 'type': Schema.Types.ObjectId, 'ref': 'Media', 'required': true },
    'playlist': { 'type': Schema.Types.ObjectId, 'ref': 'Playlist', 'required': true },
    'played': { 'type': Date, 'default': Date.now },
    'upvotes': [Number],
    'downvotes': [Number],
    'favorites': [Number]
  }, {
    'minimize': false
  });

  return mongoose.model('History', historySchema);
}
<|endoftext|>


<commit_before>"use strict";

let fs = require("fs");
let util = require("util");
let EventManager = require("./events").EventManager;
let cmsutil = require("./util");

class ModuleLoader {
  constructor(services) {
    this.services = services;
  }

  load(path, name) {
    let module = {
      name: name,
      path: util.format("%s/%s", path, name),
      controllers: new Map,
      config: new Map,
      factories: new Map,
      main: null,
    };
    fs.readdirSync(module.path).forEach(filename => {
      try {
        if (filename == "index.js") {
          let path = util.format("%s/index", module.path);
          module.main = require(path);
        } else if (filename.substr(-3) == ".js") {
          let path = util.format("%s/%s", module.path, filename);
          module.factories.set(filename.substring(0, filename.length - 3), require(path));
        } else if (filename.substr(-5) == ".json") {
          let path = util.format("%s/%s", module.path, filename);
          let config = require(path);
          module.config.set(filename.substring(0, filename.length - 5), config);
        }
      } catch (err) {
        console.error(filename + ":", err.toString());
      }
    });

    return Promise.resolve(module);
  }

  initialize(module) {
    console.log("configure", module.name);
    module.main.configure(this.services);
    module.factories.forEach((factory, name) => {
      console.log(util.format("configure %s.%s", module.name, name));
      if (typeof factory == "function") {
        module.controllers.set(name, factory(this.services));
      } else {
        if (factory.hasOwnProperty("configure")) {
          factory.configure(this.services);
        }
        module.controllers.set(name, factory);
      }
    });

    let router = this.services.get("router");
    let routes = module.config.get("routes") || [];

    routes.forEach(options => {
      let action = options.action.split(".");
      let controller = module.controllers.get(action[0]);
      let route_options = cmsutil.copy(options);
      route_options.name = util.format("%s.%s", module.name, options.name);
      router.route(options.path, route_options, event => cmsutil.promisify(controller[action[1]].call(controller, event)));
    });
  }
}

class ModuleManager {
  constructor(services, loader) {
    this.services = services;
    this.modules = new Map;
    this.events = new EventManager;
    this.loader = loader || new ModuleLoader(this.services);
  }

  get(name) {
    return this.modules.get(name);
  }

  discover(directory, modules) {
    modules.forEach(name => this.load(directory, name));
    return Promise.resolve();
  }

  load(path, name) {
    if (this.modules.has(name)) {
      return Promise.reject(new Error(util.format("Module '%s' is already loaded", name)));
    }
    return this.loader.load(path, name).then(module => {
      this.modules.set(name, module);
      this.loader.initialize(module);
      this.events.emit("load", module);
    })
  }
}

exports.ModuleManager = ModuleManager;
exports.ModuleLoader = ModuleLoader;
<commit_msg>Catch module init errors<commit_after>"use strict";

let fs = require("fs");
let util = require("util");
let EventManager = require("./events").EventManager;
let cmsutil = require("./util");

class ModuleLoader {
  constructor(services) {
    this.services = services;
  }

  load(path, name) {
    let module = {
      name: name,
      path: util.format("%s/%s", path, name),
      controllers: new Map,
      config: new Map,
      factories: new Map,
      main: null,
    };
    fs.readdirSync(module.path).forEach(filename => {
      try {
        if (filename == "index.js") {
          let path = util.format("%s/index", module.path);
          module.main = require(path);
        } else if (filename.substr(-3) == ".js") {
          let path = util.format("%s/%s", module.path, filename);
          module.factories.set(filename.substring(0, filename.length - 3), require(path));
        } else if (filename.substr(-5) == ".json") {
          let path = util.format("%s/%s", module.path, filename);
          let config = require(path);
          module.config.set(filename.substring(0, filename.length - 5), config);
        }
      } catch (err) {
        console.error(filename + ":", err.toString());
      }
    });

    return Promise.resolve(module);
  }

  initialize(module) {
    console.log("configure", module.name);
    try {
      module.main.configure(this.services);
      module.factories.forEach((factory, name) => {
        console.log(util.format("configure %s.%s", module.name, name));
        if (typeof factory == "function") {
          module.controllers.set(name, factory(this.services));
        } else {
          if (factory.hasOwnProperty("configure")) {
            factory.configure(this.services);
          }
          module.controllers.set(name, factory);
        }
      });

      let router = this.services.get("router");
      let routes = module.config.get("routes") || [];

      routes.forEach(options => {
        let action = options.action.split(".");
        let controller = module.controllers.get(action[0]);
        let route_options = cmsutil.copy(options);
        route_options.name = util.format("%s.%s", module.name, options.name);
        router.route(options.path, route_options, event => cmsutil.promisify(controller[action[1]].call(controller, event)));
      });
    } catch (error) {
      console.error(error.stack);
    }
  }
}

class ModuleManager {
  constructor(services, loader) {
    this.services = services;
    this.modules = new Map;
    this.events = new EventManager;
    this.loader = loader || new ModuleLoader(this.services);
  }

  get(name) {
    return this.modules.get(name);
  }

  discover(directory, modules) {
    modules.forEach(name => this.load(directory, name));
    return Promise.resolve();
  }

  load(path, name) {
    if (this.modules.has(name)) {
      return Promise.reject(new Error(util.format("Module '%s' is already loaded", name)));
    }
    return this.loader.load(path, name).then(module => {
      this.modules.set(name, module);
      this.loader.initialize(module);
      this.events.emit("load", module);
    })
  }
}

exports.ModuleManager = ModuleManager;
exports.ModuleLoader = ModuleLoader;
<|endoftext|>


<commit_before>import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {isFn} from '../types';
import {root} from '../root';
import {NONE} from '../const';

/**
 * Activity indicator
 *
 * @export
 * @class Loader
 * @extends {Feature}
 */
export class Loader extends Feature {

    /**
     * Creates an instance of Loader.
     *
     * @param {TableFilter} tf TableFilter instance
     */
    constructor(tf) {
        super(tf, 'loader');

        let f = this.config;

        /**
         * ID of custom container element
         * @type {String}
         */
        this.targetId = f.loader_target_id || null;

         /**
         * Loader container DOM element
         * @type {DOMElement}
         */
        this.cont = null;

        /**
         * Text displayed when indicator is visible
         * @type {String}
         */
        this.text = f.loader_text || 'Loading...';

        /**
         * Custom HTML injected in Loader's container element
         * @type {String}
         */
        this.html = f.loader_html || null;

        /**
         * Css class for Loader's container element
         * @type {String}
         */
        this.cssClass = f.loader_css_class || 'loader';

        /**
         * Close delay in milliseconds
         * @type {Number}
         */
        this.closeDelay = 250;

        /**
         * Callback fired when loader is displayed
         * @type {Function}
         */
        this.onShow = isFn(f.on_show_loader) ? f.on_show_loader : null;

        /**
         * Callback fired when loader is closed
         * @type {Function}
         */
        this.onHide = isFn(f.on_hide_loader) ? f.on_hide_loader : null;

        /**
         * Prefix for container ID
         * @type {String}
         * @private
         */
        this.prfx = 'load_';
    }

    /**
     * Initializes Loader instance
     */
    init() {
        if (this.initialized) {
            return;
        }

        let tf = this.tf;
        let emitter = this.emitter;

        let containerDiv = createElm('div', ['id', this.prfx + tf.id]);
        containerDiv.className = this.cssClass;

        let targetEl = !this.targetId ?
            tf.tbl.parentNode : elm(this.targetId);
        if (!this.targetId) {
            targetEl.insertBefore(containerDiv, tf.tbl);
        } else {
            targetEl.appendChild(containerDiv);
        }
        this.cont = containerDiv;
        if (!this.html) {
            this.cont.appendChild(createText(this.text));
        } else {
            this.cont.innerHTML = this.html;
        }

        this.show(NONE);

        // Subscribe to events
        emitter.on([
            'before-filtering',
            'before-populating-filter',
            'before-page-change',
            'before-clearing-filters',
            'before-page-length-change',
            'before-reset-page',
            'before-reset-page-length',
            'before-loading-extensions',
            'before-loading-themes'],
            () => this.show('')
        );
        emitter.on([
            'after-filtering',
            'after-populating-filter',
            'after-page-change',
            'after-clearing-filters',
            'after-page-length-change',
            'after-reset-page',
            'after-reset-page-length',
            'after-loading-extensions',
            'after-loading-themes'],
            () => this.show(NONE)
        );

        this.initialized = true;
    }

    /**
     * Shows or hides activity indicator
     * @param {String} Two possible values: '' or 'none'
     */
    show(p) {
        if (!this.isEnabled()) {
            return;
        }

        let displayLoader = () => {
            if (!this.cont) {
                return;
            }
            if (this.onShow && p !== NONE) {
                this.onShow.call(null, this);
            }
            this.cont.style.display = p;
            if (this.onHide && p === NONE) {
                this.onHide.call(null, this);
            }
        };

        let t = p === NONE ? this.closeDelay : 1;
        root.setTimeout(displayLoader, t);
    }

    /**
     * Removes feature
     */
    destroy() {
        if (!this.initialized) {
            return;
        }

        let emitter = this.emitter;

        removeElm(this.cont);
        this.cont = null;

        // Unsubscribe to events
        emitter.off([
            'before-filtering',
            'before-populating-filter',
            'before-page-change',
            'before-clearing-filters',
            'before-page-length-change',
            'before-reset-page',
            'before-reset-page-length',
            'before-loading-extensions',
            'before-loading-themes'],
            () => this.show('')
        );
        emitter.off([
            'after-filtering',
            'after-populating-filter',
            'after-page-change',
            'after-clearing-filters',
            'after-page-length-change',
            'after-reset-page',
            'after-reset-page-length',
            'after-loading-extensions',
            'after-loading-themes'],
            () => this.show(NONE)
        );

        this.initialized = false;
    }
}
<commit_msg>Aligned comment in Loader<commit_after>import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {isFn} from '../types';
import {root} from '../root';
import {NONE} from '../const';

/**
 * Activity indicator
 *
 * @export
 * @class Loader
 * @extends {Feature}
 */
export class Loader extends Feature {

    /**
     * Creates an instance of Loader.
     *
     * @param {TableFilter} tf TableFilter instance
     */
    constructor(tf) {
        super(tf, 'loader');

        let f = this.config;

        /**
         * ID of custom container element
         * @type {String}
         */
        this.targetId = f.loader_target_id || null;

        /**
         * Loader container DOM element
         * @type {DOMElement}
         */
        this.cont = null;

        /**
         * Text displayed when indicator is visible
         * @type {String}
         */
        this.text = f.loader_text || 'Loading...';

        /**
         * Custom HTML injected in Loader's container element
         * @type {String}
         */
        this.html = f.loader_html || null;

        /**
         * Css class for Loader's container element
         * @type {String}
         */
        this.cssClass = f.loader_css_class || 'loader';

        /**
         * Close delay in milliseconds
         * @type {Number}
         */
        this.closeDelay = 250;

        /**
         * Callback fired when loader is displayed
         * @type {Function}
         */
        this.onShow = isFn(f.on_show_loader) ? f.on_show_loader : null;

        /**
         * Callback fired when loader is closed
         * @type {Function}
         */
        this.onHide = isFn(f.on_hide_loader) ? f.on_hide_loader : null;

        /**
         * Prefix for container ID
         * @type {String}
         * @private
         */
        this.prfx = 'load_';
    }

    /**
     * Initializes Loader instance
     */
    init() {
        if (this.initialized) {
            return;
        }

        let tf = this.tf;
        let emitter = this.emitter;

        let containerDiv = createElm('div', ['id', this.prfx + tf.id]);
        containerDiv.className = this.cssClass;

        let targetEl = !this.targetId ?
            tf.tbl.parentNode : elm(this.targetId);
        if (!this.targetId) {
            targetEl.insertBefore(containerDiv, tf.tbl);
        } else {
            targetEl.appendChild(containerDiv);
        }
        this.cont = containerDiv;
        if (!this.html) {
            this.cont.appendChild(createText(this.text));
        } else {
            this.cont.innerHTML = this.html;
        }

        this.show(NONE);

        // Subscribe to events
        emitter.on([
            'before-filtering',
            'before-populating-filter',
            'before-page-change',
            'before-clearing-filters',
            'before-page-length-change',
            'before-reset-page',
            'before-reset-page-length',
            'before-loading-extensions',
            'before-loading-themes'],
            () => this.show('')
        );
        emitter.on([
            'after-filtering',
            'after-populating-filter',
            'after-page-change',
            'after-clearing-filters',
            'after-page-length-change',
            'after-reset-page',
            'after-reset-page-length',
            'after-loading-extensions',
            'after-loading-themes'],
            () => this.show(NONE)
        );

        this.initialized = true;
    }

    /**
     * Shows or hides activity indicator
     * @param {String} Two possible values: '' or 'none'
     */
    show(p) {
        if (!this.isEnabled()) {
            return;
        }

        let displayLoader = () => {
            if (!this.cont) {
                return;
            }
            if (this.onShow && p !== NONE) {
                this.onShow.call(null, this);
            }
            this.cont.style.display = p;
            if (this.onHide && p === NONE) {
                this.onHide.call(null, this);
            }
        };

        let t = p === NONE ? this.closeDelay : 1;
        root.setTimeout(displayLoader, t);
    }

    /**
     * Removes feature
     */
    destroy() {
        if (!this.initialized) {
            return;
        }

        let emitter = this.emitter;

        removeElm(this.cont);
        this.cont = null;

        // Unsubscribe to events
        emitter.off([
            'before-filtering',
            'before-populating-filter',
            'before-page-change',
            'before-clearing-filters',
            'before-page-length-change',
            'before-reset-page',
            'before-reset-page-length',
            'before-loading-extensions',
            'before-loading-themes'],
            () => this.show('')
        );
        emitter.off([
            'after-filtering',
            'after-populating-filter',
            'after-page-change',
            'after-clearing-filters',
            'after-page-length-change',
            'after-reset-page',
            'after-reset-page-length',
            'after-loading-extensions',
            'after-loading-themes'],
            () => this.show(NONE)
        );

        this.initialized = false;
    }
}
<|endoftext|>


<commit_before>var request = require('request');
var debug = require('debug')('botkit:rasa');

module.exports = function(config) {

    if (!config) {
        config = {};
    }

    if (!config.rasa_uri) {
        config.rasa_uri = 'http://localhost:5000';
    }

    var middleware = {
        receive: function(bot, message, next) {

            debug('Sending message to rasa API', message.text);
            request.post(config.rasa_uri + '/parse',{form: {q: message.text }}, function(err, res, body) {
                if (err) {
                    console.error('rasa middleware error:',err);
                } else {
                    var json = null;
                    try {
                        json = JSON.parse(body);
                    } catch(err) {
                        console.error('rasa middleware error parsing json:',err);
                    }

                    // copy the entire payload into the message
                    if (json) {
                        debug('rasa API payload', json);
                        message.intent = json.intent;
                        message.entities = json.entities;
                    }
                }

                next();

            });

        },
        hears: function(patterns, message) {
             for (var t = 0; t < patterns.length; t++) {
               if (message.intent == patterns[t]){
                   return true;
               }
             }
        }

    }

    return middleware;

}
<commit_msg>add debug<commit_after>var request = require('request');
var debug = require('debug')('botkit:rasa');

module.exports = function(config) {

    if (!config) {
        config = {};
    }

    if (!config.rasa_uri) {
        config.rasa_uri = 'http://localhost:5000';
    }

    var middleware = {
        receive: function(bot, message, next) {

            debug('Sending message to rasa API', message.text);
            request.post(config.rasa_uri + '/parse',{form: {q: message.text }}, function(err, res, body) {
                if (err) {
                    console.error('rasa middleware error:',err);
                } else {
                    var json = null;
                    try {
                        json = JSON.parse(body);
                    } catch(err) {
                        console.error('rasa middleware error parsing json:',err);
                    }

                    // copy the entire payload into the message
                    if (json) {
                        debug('rasa API payload', json);
                        message.intent = json.intent;
                        message.entities = json.entities;
                    }
                }

                next();

            });

        },
        hears: function(patterns, message) {
             for (var t = 0; t < patterns.length; t++) {
               if (message.intent == patterns[t]){
                   debug('rasa intent matched hear pattern', message.intent, patterns[t]);
                   return true;
               }
             }
        }

    }

    return middleware;

}
<|endoftext|>


<commit_before>import { ROUTER_ACTION } from './actions'

const routerMiddleware = history =>
  () => next => action => {
    if (action.type !== ROUTER_ACTION) return next(action)
    history[action.payload.method](...action.payload.args)
  }

export default routerMiddleware
<commit_msg>Rewrite middleware to ES6 style<commit_after>import { ROUTER_ACTION } from './actions'

const routerMiddleware = history =>
  () => next => action => {
    const { type, payload: { method, args } } = action
    if (type !== ROUTER_ACTION) return next(action)
    history[method](...args)
  }

export default routerMiddleware
<|endoftext|>


<commit_before>/** @jsx React.DOM */

var MindEditor = React.createClass( {
	dragBlobId: null,
	getInitialState: function() {
		window.editor = this;
		if ( typeof( Storage ) == "undefined" ) {
			console.log( "Browser does not support localstorage." );
		}
		if ( typeof( Storage ) !== "undefined" && localStorage.getItem( "mindEditor.blobs" ) ) {
			return {
				blobs: JSON.parse( localStorage.getItem( "mindEditor.blobs" ) ),
				nextBlobId: JSON.parse( localStorage.getItem( "mindEditor.nextBlobId" ) )
			};
		}
		else {
			var intro = "Welcome to MindEdit! Click anywhere to start writing.\n\n";
			if ( typeof( Storage ) !== "undefined" ) {
				intro += "Your browser supports localStorage. Great!\nYour text will be automatically saved on your browser.\n";
			}
			else {
				intro += "Your browser does not support localStorage.\nYour text will be lost after you reload or leave this page.\n";
			}
			return {
				blobs: {
					0: {
						x: 100,
						y: 100,
						text: intro
					}
				},
				nextBlobId: 1
			}
		}
	},
	componentWillUpdate: function() {
		if ( typeof( Storage ) !== "undefined" ) {
			localStorage.setItem( "mindEditor.blobs", JSON.stringify( this.state.blobs ) );
			localStorage.setItem( "mindEditor.nextBlobId", JSON.stringify( this.state.nextBlobId ) );
		}
	},
	handleClick: function( event ) {
		console.log( 'mindEditor: click', event.pageX, event.pageY );
		var id = this.state.nextBlobId;
		this.state.nextBlobId++;
		var blob = {
			x: event.pageX,
			y: event.pageY,
			text: '',
			id: id
		};
		this.state.blobs[ id ] = blob;
		this.setState( {
			nextBlobId: this.state.nextBlobId,
			blobs: this.state.blobs
		} );
	},
	handleBlobTextChange: function( blobId, event ) {
		console.log( 'mindEditor: text change', event.target.value );
		var blobs = this.state.blobs;
		var blob = blobs[ blobId ];
		blob.text = event.target.value;
		if ( !blob.text ) {
			delete this.state.blobs[ blobId ];
		}
		this.setState( {
			nextBlobId: this.state.nextBlobId,
			blobs: this.state.blobs
		} );
	},
	handleStopEditing: function( blobId, event ) {
		var blob = this.state.blobs[ blobId ];
		if ( !blob.text ) {
			delete this.state.blobs[ blobId ];
		}
		this.setState( {
			nextBlobId: this.state.nextBlobId,
			blobs: this.state.blobs
		} );
	},
	handleDragStart: function( blobId, event ) {
		console.log( 'mindEditor: drag start', blobId );
		this.dragBlobId = blobId;
		var blob = this.state.blobs[ blobId ];
		this.dragOffsetX = blob.x - event.pageX;
		this.dragOffsetY = blob.y - event.pageY;
	},
	handleMouseMove: function( event ) {
		if ( this.dragBlobId ) {
			var blobId = this.dragBlobId;
			var blob = this.state.blobs[ blobId ];
			blob.x = event.pageX + this.dragOffsetX;
			blob.y = event.pageY + this.dragOffsetY;
			this.setState( {
				nextBlobId: this.state.nextBlobId,
				blobs: this.state.blobs
			} );
		}
	},
	handleDragEnd: function( event ) {
		this.dragBlobId = null;
	},
	render: function() {
		var divStyle = {
			width: document.body.scrollWidth,
			height: document.body.scrollHeight
		};
		var blobs = {};
		for ( var i in this.state.blobs ) {
			var data = this.state.blobs[ i ];
			blobs[ 'blob-' + data.id ] = (
				<Blob id={data.id} pageX={data.x} pageY={data.y} text={data.text}
					onTextChange={this.handleBlobTextChange.bind( this, data.id )}
					onStopEditing={this.handleStopEditing.bind( this, data.id )}
					onDragStart={this.handleDragStart.bind( this, data.id )}
					onDragEnd={this.handleDragEnd}>
				</Blob>
			);
		}
		return (

{blobs}

		);
	}
} );
<commit_msg>fix: make intro blob movable<commit_after>/** @jsx React.DOM */

var MindEditor = React.createClass( {
	dragBlobId: null,
	getInitialState: function() {
		window.editor = this;
		if ( typeof( Storage ) == "undefined" ) {
			console.log( "Browser does not support localstorage." );
		}
		if ( typeof( Storage ) !== "undefined" && localStorage.getItem( "mindEditor.blobs" ) ) {
			return {
				blobs: JSON.parse( localStorage.getItem( "mindEditor.blobs" ) ),
				nextBlobId: JSON.parse( localStorage.getItem( "mindEditor.nextBlobId" ) )
			};
		}
		else {
			var intro = "Welcome to MindEdit! Click anywhere to start writing.\n\n";
			if ( typeof( Storage ) !== "undefined" ) {
				intro += "Your browser supports localStorage. Great!\nYour text will be automatically saved on your browser.\n";
			}
			else {
				intro += "Your browser does not support localStorage.\nYour text will be lost after you reload or leave this page.\n";
			}
			return {
				blobs: {
					0: {
						id: 0,
						x: 100,
						y: 100,
						text: intro
					}
				},
				nextBlobId: 1
			}
		}
	},
	componentWillUpdate: function() {
		if ( typeof( Storage ) !== "undefined" ) {
			localStorage.setItem( "mindEditor.blobs", JSON.stringify( this.state.blobs ) );
			localStorage.setItem( "mindEditor.nextBlobId", JSON.stringify( this.state.nextBlobId ) );
		}
	},
	handleClick: function( event ) {
		console.log( 'mindEditor: click', event.pageX, event.pageY );
		var id = this.state.nextBlobId;
		this.state.nextBlobId++;
		var blob = {
			x: event.pageX,
			y: event.pageY,
			text: '',
			id: id
		};
		this.state.blobs[ id ] = blob;
		this.setState( {
			nextBlobId: this.state.nextBlobId,
			blobs: this.state.blobs
		} );
	},
	handleBlobTextChange: function( blobId, event ) {
		console.log( 'mindEditor: text change', event.target.value );
		var blobs = this.state.blobs;
		var blob = blobs[ blobId ];
		blob.text = event.target.value;
		if ( !blob.text ) {
			delete this.state.blobs[ blobId ];
		}
		this.setState( {
			nextBlobId: this.state.nextBlobId,
			blobs: this.state.blobs
		} );
	},
	handleStopEditing: function( blobId, event ) {
		var blob = this.state.blobs[ blobId ];
		if ( !blob.text ) {
			delete this.state.blobs[ blobId ];
		}
		this.setState( {
			nextBlobId: this.state.nextBlobId,
			blobs: this.state.blobs
		} );
	},
	handleDragStart: function( blobId, event ) {
		console.log( 'mindEditor: drag start', blobId );
		this.dragBlobId = blobId;
		var blob = this.state.blobs[ blobId ];
		this.dragOffsetX = blob.x - event.pageX;
		this.dragOffsetY = blob.y - event.pageY;
	},
	handleMouseMove: function( event ) {
		if ( this.dragBlobId ) {
			var blobId = this.dragBlobId;
			var blob = this.state.blobs[ blobId ];
			blob.x = event.pageX + this.dragOffsetX;
			blob.y = event.pageY + this.dragOffsetY;
			this.setState( {
				nextBlobId: this.state.nextBlobId,
				blobs: this.state.blobs
			} );
		}
	},
	handleDragEnd: function( event ) {
		this.dragBlobId = null;
	},
	render: function() {
		var divStyle = {
			width: document.body.scrollWidth,
			height: document.body.scrollHeight
		};
		var blobs = {};
		for ( var i in this.state.blobs ) {
			var data = this.state.blobs[ i ];
			blobs[ 'blob-' + data.id ] = (
				<Blob id={data.id} pageX={data.x} pageY={data.y} text={data.text}
					onTextChange={this.handleBlobTextChange.bind( this, data.id )}
					onStopEditing={this.handleStopEditing.bind( this, data.id )}
					onDragStart={this.handleDragStart.bind( this, data.id )}
					onDragEnd={this.handleDragEnd}>
				</Blob>
			);
		}
		return (

{blobs}

		);
	}
} );
<|endoftext|>