<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2017, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

/* eslint-disable no-bitwise, no-mixed-operators, max-len */
import _ from 'lodash';

import { addDuration } from '../src/utils/datetime';
import { MGDL_UNITS, MS_IN_DAY, MMOLL_UNITS, MGDL_PER_MMOLL } from '../src/utils/constants';

const APPEND = '.000Z';

export const generateGUID = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
  const r = Math.random() * 16 | 0;
  const v = c === 'x' ? r : (r & 0x3 | 0x8);
  return v.toString(16);
});

class Common {
  constructor(opts = {}) {
    this.deviceId = 'Test Page Data - 123';
    this.source = opts.source || 'testpage';
    this.conversionOffset = 0;
    this.uploadId = opts.uploadId || 'uploadId123';

    this.assignGUID();
  }

  assignGUID() {
    const guid = generateGUID();

    this.id = guid;
  }

  asObject() {
    const clone = {};

    _.forIn(this, (value, key) => {
      if (typeof key !== 'function') {
        clone[key] = value;
      }
    });

    return clone;
  }

  makeDeviceTime() {
    return new Date().toISOString().slice(0, -5);
  }

  makeNormalTime() {
    return this.deviceTime + APPEND;
  }

  makeTime() {
    const d = new Date(this.deviceTime + APPEND);
    const offsetMinutes = d.getTimezoneOffset();
    d.setUTCMinutes(d.getUTCMinutes() + offsetMinutes);
    return d.toISOString();
  }

  makeTimezoneOffset() {
    const d = new Date(this.deviceTime + APPEND);
    const offsetMinutes = d.getTimezoneOffset();
    return -offsetMinutes;
  }
}

export class Basal extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deliveryType: 'scheduled',
      deviceTime: this.makeDeviceTime(),
      duration: MS_IN_DAY / 12,
      rate: 0.5,
    });

    this.type = 'basal';

    this.deliveryType = opts.deliveryType;
    this.deviceTime = opts.deviceTime;
    this.duration = opts.duration;
    this.rate = opts.rate;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (!opts.raw) this.normalTime = this.makeNormalTime();
    if (!opts.raw) this.normalEnd = addDuration(this.normalTime, this.duration);
  }
}

export class Bolus extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
      subType: 'normal',
      value: 5.0,
    });

    this.type = 'bolus';
    this.deviceTime = opts.deviceTime;
    this.subType = opts.subType;

    if (this.subType === 'normal') {
      this.normal = opts.value;
    }

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (!opts.raw) this.normalTime = this.makeNormalTime();
  }
}

export class CBG extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceId: 'DexG4Rec_XXXXXXXXX',
      deviceTime: this.makeDeviceTime(),
      units: MGDL_UNITS,
      value: 100,
    });

    this.type = 'cbg';

    this.deviceTime = opts.deviceTime;
    this.deviceId = opts.deviceId;
    this.units = opts.units;
    this.value = opts.value;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (opts.raw) {
      if (this.units === MGDL_UNITS) {
        this.units = MMOLL_UNITS;
        this.value = this.value / MGDL_PER_MMOLL;
      }
    } else {
      this.normalTime = this.makeNormalTime();
    }
  }
}

export class Message extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      messagetext: 'This is a note.',
      parentmessage: null,
      time: new Date().toISOString(),
    });

    this.type = 'message';

    this.time = opts.time;

    if (!opts.raw) {
      const dt = new Date(this.time);
      const offsetMinutes = dt.getTimezoneOffset();
      dt.setUTCMinutes(dt.getUTCMinutes() - offsetMinutes);

      this.normalTime = dt.toISOString();
      this.messageText = opts.messagetext;
      this.parentMessage = opts.parentmessage;
    } else {
      this.messagetext = opts.messagetext;
      this.parentmessage = opts.parentmessage;
    }
  }
}

export class Settings extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      activeSchedule: 'standard',
      basalSchedules: [{
        name: 'standard',
        value: [{
          start: 0,
          rate: 1.0,
        }],
      }],
      bgTarget: [{
        high: 100,
        low: 80,
        start: 0,
      }],
      carbRatio: [{
        amount: 15,
        start: 0,
      }],
      deviceTime: this.makeDeviceTime(),
      insulinSensitivity: [{
        amount: 50,
        start: 0,
      }],
      units: {
        carb: 'grams',
        bg: MGDL_UNITS,
      },
    });

    this.type = 'settings';

    this.activeSchedule = opts.activeSchedule;
    this.basalSchedules = opts.basalSchedules;
    this.bgTarget = opts.bgTarget;
    this.carbRatio = opts.carbRatio;
    this.deviceTime = opts.deviceTime;
    this.insulinSensitivity = opts.insulinSensitivity;
    this.units = opts.units;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (opts.raw) {
      this.units.bg = MMOLL_UNITS;
      if (this.insulinSensitivity) this.insulinSensitivity.amount = this.insulinSensitivity.amount / MGDL_PER_MMOLL;
      if (this.bgTarget.target) this.bgTarget.target = this.bgTarget.target / MGDL_PER_MMOLL;
      if (this.bgTarget.low) this.bgTarget.low = this.bgTarget.low / MGDL_PER_MMOLL;
      if (this.bgTarget.high) this.bgTarget.high = this.bgTarget.high / MGDL_PER_MMOLL;
    } else {
      this.normalTime = this.makeNormalTime();
    }
  }
}

export class SMBG extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
      displayOffset: 0,
      units: MGDL_UNITS,
      value: 100,
    });

    this.type = 'smbg';

    this.deviceTime = opts.deviceTime;
    this.units = opts.units;
    this.value = opts.value;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    this.displayOffset = opts.displayOffset;

    if (opts.raw) {
      this.units = MMOLL_UNITS;
      this.value = this.value / MGDL_PER_MMOLL;
    } else {
      this.normalTime = this.makeNormalTime();
    }
  }
}

export class DeviceEvent extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
      units: 'mg/dL',
      value: 100,
      primeTarget: 'cannula',
    });

    this.type = 'deviceEvent';
    this.subType = opts.subType;

    if (opts.subType === 'prime') {
      this.primeTarget = opts.primeTarget;
    }

    this.deviceTime = opts.deviceTime;

    this.time = this.makeTime();
    this.createdTime = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (!opts.raw) this.normalTime = this.makeNormalTime();
  }
}

export class Upload extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
      timezone: 'US/Eastern',
    });

    this.type = 'upload';
    this.deviceTags = opts.deviceTags;
    this.source = opts.source;
    this.deviceTime = opts.deviceTime;
    this.deviceModel = opts.deviceModel;

    this.time = this.makeTime();
    this.timezone = opts.timezone;
    if (!opts.raw) this.normalTime = this.makeNormalTime();
    this.createdTime = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
  }
}

export class Wizard extends Common {
  constructor(opts = {}) {
    super(opts);

    if (opts.bolus) {
      // eslint-disable-next-line no-param-reassign
      opts.deviceTime = opts.bolus.deviceTime;
    }
    _.defaults(opts, {
      bgTarget: {
        high: 120,
        target: 100,
      },
      deviceTime: this.makeDeviceTime(),
      insulinCarbRatio: 15,
      insulinSensitivity: 50,
      recommended: {},
      value: 5.0,
      units: MGDL_UNITS,
    });

    this.type = 'wizard';

    this.bgTarget = opts.bgTarget;
    this.bolus = opts.bolus ? opts.bolus : new Bolus({
      value: opts.value,
      deviceTime: this.deviceTime,
    });

    this.carbInput = opts.carbInput;
    this.deviceTime = opts.deviceTime;
    this.insulinCarbRatio = opts.insulinCarbRatio;
    this.insulinSensitivity = opts.insulinSensitivity;
    this.recommended = opts.recommended;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (opts.raw) {
      this.bolus = this.bolus.id;

      this.units = MMOLL_UNITS;
      if (this.insulinSensitivity) this.insulinSensitivity = this.insulinSensitivity / MGDL_PER_MMOLL;
      if (this.bgInput) this.bgInput = this.bgInput / MGDL_PER_MMOLL;
      if (this.bgTarget.target) this.bgTarget.target = this.bgTarget.target / MGDL_PER_MMOLL;
      if (this.bgTarget.range) this.bgTarget.range = this.bgTarget.range / MGDL_PER_MMOLL;
      if (this.bgTarget.low) this.bgTarget.low = this.bgTarget.low / MGDL_PER_MMOLL;
      if (this.bgTarget.high) this.bgTarget.high = this.bgTarget.high / MGDL_PER_MMOLL;
    } else {
      this.normalTime = this.makeNormalTime();
    }
  }
}

export class Food extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
    });

    this.type = 'food';
    this.deviceTime = opts.deviceTime;
    this.nutrition = opts.nutrition;

    this.time = this.makeTime();
    if (!opts.raw) this.normalTime = this.makeNormalTime();
    this.createdTime = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
  }
}

export const types = {
  Basal,
  Bolus,
  CBG,
  DeviceEvent,
  Food,
  Message,
  Settings,
  SMBG,
  Upload,
  Wizard,
};

export default types;
<commit_msg>Add scheduleName prop to Basal data stubs<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2017, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

/* eslint-disable no-bitwise, no-mixed-operators, max-len */
import _ from 'lodash';

import { addDuration } from '../src/utils/datetime';
import { MGDL_UNITS, MS_IN_DAY, MMOLL_UNITS, MGDL_PER_MMOLL } from '../src/utils/constants';

const APPEND = '.000Z';

export const generateGUID = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
  const r = Math.random() * 16 | 0;
  const v = c === 'x' ? r : (r & 0x3 | 0x8);
  return v.toString(16);
});

class Common {
  constructor(opts = {}) {
    this.deviceId = 'Test Page Data - 123';
    this.source = opts.source || 'testpage';
    this.conversionOffset = 0;
    this.uploadId = opts.uploadId || 'uploadId123';

    this.assignGUID();
  }

  assignGUID() {
    const guid = generateGUID();

    this.id = guid;
  }

  asObject() {
    const clone = {};

    _.forIn(this, (value, key) => {
      if (typeof key !== 'function') {
        clone[key] = value;
      }
    });

    return clone;
  }

  makeDeviceTime() {
    return new Date().toISOString().slice(0, -5);
  }

  makeNormalTime() {
    return this.deviceTime + APPEND;
  }

  makeTime() {
    const d = new Date(this.deviceTime + APPEND);
    const offsetMinutes = d.getTimezoneOffset();
    d.setUTCMinutes(d.getUTCMinutes() + offsetMinutes);
    return d.toISOString();
  }

  makeTimezoneOffset() {
    const d = new Date(this.deviceTime + APPEND);
    const offsetMinutes = d.getTimezoneOffset();
    return -offsetMinutes;
  }
}

export class Basal extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deliveryType: 'scheduled',
      deviceTime: this.makeDeviceTime(),
      duration: MS_IN_DAY / 12,
      rate: 0.5,
      scheduleName: 'standard',
    });

    this.type = 'basal';

    this.deliveryType = opts.deliveryType;
    this.deviceTime = opts.deviceTime;
    this.duration = opts.duration;
    this.rate = opts.rate;
    this.scheduleName = opts.scheduleName;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (!opts.raw) this.normalTime = this.makeNormalTime();
    if (!opts.raw) this.normalEnd = addDuration(this.normalTime, this.duration);
  }
}

export class Bolus extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
      subType: 'normal',
      value: 5.0,
    });

    this.type = 'bolus';
    this.deviceTime = opts.deviceTime;
    this.subType = opts.subType;

    if (this.subType === 'normal') {
      this.normal = opts.value;
    }

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (!opts.raw) this.normalTime = this.makeNormalTime();
  }
}

export class CBG extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceId: 'DexG4Rec_XXXXXXXXX',
      deviceTime: this.makeDeviceTime(),
      units: MGDL_UNITS,
      value: 100,
    });

    this.type = 'cbg';

    this.deviceTime = opts.deviceTime;
    this.deviceId = opts.deviceId;
    this.units = opts.units;
    this.value = opts.value;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (opts.raw) {
      if (this.units === MGDL_UNITS) {
        this.units = MMOLL_UNITS;
        this.value = this.value / MGDL_PER_MMOLL;
      }
    } else {
      this.normalTime = this.makeNormalTime();
    }
  }
}

export class Message extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      messagetext: 'This is a note.',
      parentmessage: null,
      time: new Date().toISOString(),
    });

    this.type = 'message';

    this.time = opts.time;

    if (!opts.raw) {
      const dt = new Date(this.time);
      const offsetMinutes = dt.getTimezoneOffset();
      dt.setUTCMinutes(dt.getUTCMinutes() - offsetMinutes);

      this.normalTime = dt.toISOString();
      this.messageText = opts.messagetext;
      this.parentMessage = opts.parentmessage;
    } else {
      this.messagetext = opts.messagetext;
      this.parentmessage = opts.parentmessage;
    }
  }
}

export class Settings extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      activeSchedule: 'standard',
      basalSchedules: [{
        name: 'standard',
        value: [{
          start: 0,
          rate: 1.0,
        }],
      }],
      bgTarget: [{
        high: 100,
        low: 80,
        start: 0,
      }],
      carbRatio: [{
        amount: 15,
        start: 0,
      }],
      deviceTime: this.makeDeviceTime(),
      insulinSensitivity: [{
        amount: 50,
        start: 0,
      }],
      units: {
        carb: 'grams',
        bg: MGDL_UNITS,
      },
    });

    this.type = 'settings';

    this.activeSchedule = opts.activeSchedule;
    this.basalSchedules = opts.basalSchedules;
    this.bgTarget = opts.bgTarget;
    this.carbRatio = opts.carbRatio;
    this.deviceTime = opts.deviceTime;
    this.insulinSensitivity = opts.insulinSensitivity;
    this.units = opts.units;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (opts.raw) {
      this.units.bg = MMOLL_UNITS;
      if (this.insulinSensitivity) this.insulinSensitivity.amount = this.insulinSensitivity.amount / MGDL_PER_MMOLL;
      if (this.bgTarget.target) this.bgTarget.target = this.bgTarget.target / MGDL_PER_MMOLL;
      if (this.bgTarget.low) this.bgTarget.low = this.bgTarget.low / MGDL_PER_MMOLL;
      if (this.bgTarget.high) this.bgTarget.high = this.bgTarget.high / MGDL_PER_MMOLL;
    } else {
      this.normalTime = this.makeNormalTime();
    }
  }
}

export class SMBG extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
      displayOffset: 0,
      units: MGDL_UNITS,
      value: 100,
    });

    this.type = 'smbg';

    this.deviceTime = opts.deviceTime;
    this.units = opts.units;
    this.value = opts.value;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    this.displayOffset = opts.displayOffset;

    if (opts.raw) {
      this.units = MMOLL_UNITS;
      this.value = this.value / MGDL_PER_MMOLL;
    } else {
      this.normalTime = this.makeNormalTime();
    }
  }
}

export class DeviceEvent extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
      units: 'mg/dL',
      value: 100,
      primeTarget: 'cannula',
    });

    this.type = 'deviceEvent';
    this.subType = opts.subType;

    if (opts.subType === 'prime') {
      this.primeTarget = opts.primeTarget;
    }

    this.deviceTime = opts.deviceTime;

    this.time = this.makeTime();
    this.createdTime = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (!opts.raw) this.normalTime = this.makeNormalTime();
  }
}

export class Upload extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
      timezone: 'US/Eastern',
    });

    this.type = 'upload';
    this.deviceTags = opts.deviceTags;
    this.source = opts.source;
    this.deviceTime = opts.deviceTime;
    this.deviceModel = opts.deviceModel;

    this.time = this.makeTime();
    this.timezone = opts.timezone;
    if (!opts.raw) this.normalTime = this.makeNormalTime();
    this.createdTime = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
  }
}

export class Wizard extends Common {
  constructor(opts = {}) {
    super(opts);

    if (opts.bolus) {
      // eslint-disable-next-line no-param-reassign
      opts.deviceTime = opts.bolus.deviceTime;
    }
    _.defaults(opts, {
      bgTarget: {
        high: 120,
        target: 100,
      },
      deviceTime: this.makeDeviceTime(),
      insulinCarbRatio: 15,
      insulinSensitivity: 50,
      recommended: {},
      value: 5.0,
      units: MGDL_UNITS,
    });

    this.type = 'wizard';

    this.bgTarget = opts.bgTarget;
    this.bolus = opts.bolus ? opts.bolus : new Bolus({
      value: opts.value,
      deviceTime: this.deviceTime,
    });

    this.carbInput = opts.carbInput;
    this.deviceTime = opts.deviceTime;
    this.insulinCarbRatio = opts.insulinCarbRatio;
    this.insulinSensitivity = opts.insulinSensitivity;
    this.recommended = opts.recommended;

    this.time = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
    if (opts.raw) {
      this.bolus = this.bolus.id;

      this.units = MMOLL_UNITS;
      if (this.insulinSensitivity) this.insulinSensitivity = this.insulinSensitivity / MGDL_PER_MMOLL;
      if (this.bgInput) this.bgInput = this.bgInput / MGDL_PER_MMOLL;
      if (this.bgTarget.target) this.bgTarget.target = this.bgTarget.target / MGDL_PER_MMOLL;
      if (this.bgTarget.range) this.bgTarget.range = this.bgTarget.range / MGDL_PER_MMOLL;
      if (this.bgTarget.low) this.bgTarget.low = this.bgTarget.low / MGDL_PER_MMOLL;
      if (this.bgTarget.high) this.bgTarget.high = this.bgTarget.high / MGDL_PER_MMOLL;
    } else {
      this.normalTime = this.makeNormalTime();
    }
  }
}

export class Food extends Common {
  constructor(opts = {}) {
    super(opts);

    _.defaults(opts, {
      deviceTime: this.makeDeviceTime(),
    });

    this.type = 'food';
    this.deviceTime = opts.deviceTime;
    this.nutrition = opts.nutrition;

    this.time = this.makeTime();
    if (!opts.raw) this.normalTime = this.makeNormalTime();
    this.createdTime = this.makeTime();
    this.timezoneOffset = this.makeTimezoneOffset();
  }
}

export const types = {
  Basal,
  Bolus,
  CBG,
  DeviceEvent,
  Food,
  Message,
  Settings,
  SMBG,
  Upload,
  Wizard,
};

export default types;
<|endoftext|>


<commit_before>/**
 * @fileoverview
 * Color class
 */

/**
* @constructor
*
*
* @class
* Represent a color. Allows for setting and getting color components based
* on RGV, HSV and HSL color spaces.
* See also http://en.wikipedia.org/wiki/Color_space
*/
var Colors = function()
{
  const
  RED = 0,
  GREEN = 1,
  BLUE = 2,
  HUE = 0,
  SAT = 1,
  LUM = 2;

  var rgb = [0, 0, 0];
  var hsl = [0, 50, 50];
  var hsv = [0, 50, 50];

  /**
   * return val bounded to upper or lower if it over/underflows
   * @private
   * @param val {number} value to bound
   * @param upper {number} upper bound
   * @param lower {number} lower bound
   * @returns {number}
   */
  var fixRange = function( val, upper, lower)
  {
    return val > upper ? upper : val < lower ? lower : val;
  }

  /**
   * rounds off val and bounds it to upper and lower
   * @see Colors#fixRange
   * @private
   * @returns {number}
   * @param val {number} value to bound
   * @param upper {number} upper bound
   * @param lower {number} lower bound
   */
  var roundVal = function( val, upper, lower)
  {
    val = Math.round(val);
    return val > upper ? upper : val < lower ? lower : val;
  }

  /**
   * turns val into a fixed number and bounds it to upper and lower
   * @see Colors#fixRange
   * @private
   * @returns {number}
   * @param val {number} value to bound
   * @param upper {number} upper bound
   * @param lower {number} lower bound
   */
  var toFixed = function( val, upper, lower)
  {
    val = val.toFixed(2);
    return val > upper ? upper : val < lower ? lower : val;
  }

  /**
   * Set the hue component of the color
   * @param h {int} desired value of hue
   * @returns {int} new value of hue
   */
  this.setHue = function(h)
  {
    h = fixRange(h, 360, 0);
    hsl[HUE] = parseInt(h);
    rgb = this.hsl_to_rgb( hsl[HUE], hsl[SAT], hsl[LUM] );
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return h;
  }

  /**
   * Set the saturation component of the color
   * @param s {int} desired value of saturation
   * @returns {int} new value of saturation
   */
  this.setSaturation = function(s)
  {
    s = fixRange(s, 100, 0);
    hsl[SAT] = parseFloat(s);
    rgb = this.hsl_to_rgb( hsl[HUE], hsl[SAT], hsl[LUM] );
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return s;
  }

  /**
   * Set the luminosity component of the color
   * @param l {int} desired value of luminosity
   * @returns {int} new value of luminosity
   */
  this.setLuminosity = function(l)
  {
    l = fixRange(l, 100, 0);
    hsl[LUM] = parseFloat(l);
    rgb = this.hsl_to_rgb( hsl[HUE], hsl[SAT], hsl[LUM] );
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return l;
  }

  /**
   * Set hue component of the color, using HSV
   * http://en.wikipedia.org/wiki/HSV_color_space
   * @param h {float} desired value of hue
   * @returns {int} new value of hue
   */
  this.setHueV = function(h)
  {
    h = fixRange(h, 360, 0);
    hsv[HUE] = parseInt(h);
    rgb = this.hsv_to_rgb( hsv[HUE], hsv[SAT], hsv[LUM] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return h;
  }

  /**
   * Set the saturation component of the color, using HSV
   * @param h {float} desired value of saturation
   * @returns {int} new value of saturation
   */
  this.setSaturationV = function(s)
  {
    s = fixRange(s, 100, 0);
    hsv[SAT] = parseFloat(s);
    rgb = this.hsv_to_rgb( hsv[HUE], hsv[SAT], hsv[LUM] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return s;
  }

  /**
   * Set the value component of the color, using HSV
   * @param h {float} desired value of value
   * @returns {int} new value of value
   */
  this.setValue = function(l)
  {
    l = fixRange(l, 100, 0);
    hsv[LUM] = parseFloat(l);
    rgb = this.hsv_to_rgb( hsv[HUE], hsv[SAT], hsv[LUM] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return l;
  }

  /**
   * Set the red component of the color
   * @param r {int} value of red component
   * @returns {int} value of red component
   */
  this.setRed = function(r)
  {
    r = fixRange(r, 255, 0);
    rgb[RED] = parseInt(r);
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return r;
  }

  /**
   * Set the green component of the color
   * @param g {int} value of green component
   * @returns {int} value of green component
   */
  this.setGreen = function(g)
  {
    g = fixRange(g, 255, 0);
    rgb[GREEN] = parseInt(g);
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return g;
  }

  /**
   * Set the red, green and blue components of the color
   * @param c_arr {array} array containing red,green,blue ints
   */
  this.setRGB = function(c_arr)
  {
    var i = 0;
    for( ; i < 3; i++)
    {
      rgb[i] = c_arr[i] > 255 ? 255 : c_arr[i];
    }
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
  }

  /**
   * Set the blue component of the color
   * @param b {int} value of blue component
   * @returns {int} value of blue component
   */
  this.setBlue = function(b)
  {
    b = fixRange(b, 255, 0);
    rgb[BLUE] = parseInt(b);
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return b;
  }

  /**
   * Set the color from a hex color code
   * @param hex {String} hex color
   * @returns {String} hex color
   */
  this.setHex = function(hex)
  {
    hex = /^[0-9a-f]*$/i.test(hex) ? hex : '';
    if(hex)
    {
      hex = hex.slice(0,6);
      var temp = parseInt(hex, 16);
      rgb = [ temp >> 16, ( temp >> 8 ) & 0xff, temp & 0xff ];
      hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
      hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    }
    return hex;
  }

  /**
   * Get hue component of color
   * @returns {int} hue
   */
  this.getHue = function()
  {
    return roundVal(hsl[HUE], 360, 0);
  }

  /**
   * Get saturation component of color
   * @returns {int} saturation
   */
  this.getSaturation = function()
  {
    return toFixed(hsl[SAT], 100, 0);
  }

  /**
   * Get luminosity component of color
   * @returns {int} luminosity
   */
  this.getLuminosity = function()
  {
    return toFixed(hsl[LUM], 100, 0);
  }

  /**
   * Get hue, saturation and luminosity of color as an array
   * @returns {array} [hue, sat, lum]
   */
  this.getHSL = function()
  {
    return [roundVal(hsl[0], 360, 0), toFixed(hsl[1], 100, 0), toFixed(hsl[2], 100, 0)];
  }

  /**
   * Get hue component of color (HSV)
   * @returns {int} hue
   */
  this.getHueV = function()
  {
    return roundVal(hsv[HUE], 360, 0);
  }

  /**
   * Get saturation component of color (HSV)
   * @returns {int} saturation
   */
  this.getSaturationV = function()
  {
    return toFixed(hsv[SAT], 100, 0);
  }

  /**
   * Get value component of color (HSV)
   * @returns {int} value
   */
  this.getValue = function()
  {
    return toFixed(hsv[LUM], 100, 0);
  }

  /**
   * Get red component of color
   * @returns {int} red value
   */
  this.getRed = function()
  {
    return roundVal(rgb[RED], 255, 0);
  }

  /**
   * Get green component of color
   * @returns {int} green value
   */
  this.getGreen = function()
  {
    return roundVal(rgb[GREEN], 255, 0);
  }

  /**
   * Get blue component of color
   * @returns {int} blue
   */
  this.getBlue = function()
  {
    return roundVal(rgb[BLUE], 255, 0);
  }

  /**
   * Get red, green and blue component of color as an array
   * @returns {array} [r, g, b]
   */
  this.getRGB = function()
  {
    return [roundVal(rgb[0], 255, 0), roundVal(rgb[1], 255, 0), roundVal(rgb[2], 255, 0)];
  }

  /**
   * Get hex value of color
   * @returns {String} hex value
   */
  this.getHex = function()
  {
    return this.rgb_to_hex_c(rgb);
  }

}

Colors.prototype = new function()
{
  var self = this;

  var roundVal = function( val, upper, lower)
  {
    val = Math.round(val);
    return val > upper ? upper : val < lower ? lower : val;
  }

  var hsl_or_hsv_to_rgb = function ( h, s, l, is_hsl )
  {
    var ret = self.hue_to_rgb(h), i = 0;
    if( is_hsl)
    {
      ret = self.mix_rgb(ret, [127.5, 127.5, 127.5], 1 - s / 100);
      if( l <= 50 )
      {
        ret = self.mix_rgb([0, 0, 0], ret, l/50);
      }
      else
      {
        ret = self.mix_rgb(ret, [0xff, 0xff, 0xff], ( l - 50 ) / 50);
      }
    }
    else
    {
      ret = self.mix_rgb(ret, [0xff, 0xff, 0xff], 1 - s / 100);
      ret = self.mix_rgb([0, 0, 0], ret, l/100);
    }
    return ret;
  }

  var rgb_to_hsl_or_hsv = function ( r, g, b, is_to_hsl )
  {
    r /= 255;
    g /= 255;
    b /= 255;

    var h = 0
    var s = 0;
    var l = 0;
    var maxcolor = Math.max(r, g, b);
    var mincolor = Math.min(r, g, b);
    var delta = maxcolor - mincolor;
    var sum = maxcolor + mincolor;

    if( is_to_hsl )
    {
      l = sum / 2;
    }
    else
    {
      l = maxcolor;
    }

    if( delta == 0 )
    {
      s = h = 0;
    }
    else
    {
      if( is_to_hsl )
      {
        if( l < 0.5 )
        {
          s = delta / sum;
        }
        else
        {
          s = delta / ( 2 - sum );
        }
      }
      else
      {
        s = delta / maxcolor;
      }

      if( r == maxcolor )
      {
        h = ( g - b ) / delta;
      }
      else if( g == maxcolor )
      {
        h = 2.0 + ( b - r ) / delta;
      }
      else
      {
        h = 4.0 + ( r - g ) / delta;
      }
    }

    h *= 60;
    if( h > 360 )
    {
      h = 360;
    }
    else if ( h < 0 )
    {
      h += 360;
    }
    s *= 100;
    if( s > 100 )
    {
      s = 100;
    }
    l *= 100;
    if( l > 100 )
    {
      l = 100;
    }

    return [ h, s, l ];
  }

  this.rgb_c_to_hex_c = function(c)
  {
    c = roundVal(c, 255, 0);
    return ( c < 16 ? '0' : '' ) + c.toString(16);
  }

  this.rgb_to_hex_c = function(c_arr)
  {
    var ret = '', i = 0, c = 0;
    for( ; i < 3; i++ )
    {
      c = roundVal(c_arr[i], 255, 0);
      if( c > 255 ) c = 255;
      ret +=  ( c < 16 ? '0' : '' ) + c.toString(16);
    }
    return ret;
  }

  this.mix_rgb = function(c_1, c_2, m)
  {
    var ret = [], i = 0;
    for( ; i < 3; i++ )
    {
      ret[i] = c_1[i] + m * ( c_2[i] - c_1[i] );
    }
    return ret;
  }

  this.hue_to_rgb = function(h)
  {
    h = h % 360;
    var delta = h % 60;
    h -= delta;
    delta = ( 255 / 60 * delta ) >> 0;
    if( h < 60 ) return [0xff, delta, 0];
    if( h < 120 ) return  [0xff - delta, 0xff, 0];
    if( h < 180 ) return  [0, 0xff, delta];
    if( h < 240 ) return  [0, 0xff - delta, 0xff];
    if( h < 300 ) return  [delta, 0, 0xff];
    if( h < 360 ) return  [0xff, 0, 0xff - delta];
  }

  this.hsl_to_rgb = function ( h, s, l )
  {
    return hsl_or_hsv_to_rgb( h, s, l, true);
  }

  this.hsv_to_rgb = function ( h, s, v )
  {
    return hsl_or_hsv_to_rgb( h, s, v, false);
  }

  this.rgb_to_hsv = function ( r, g, b )
  {
    return rgb_to_hsl_or_hsv ( r, g, b, false );
  }

  this.rgb_to_hsl = function ( r, g, b )
  {
    return rgb_to_hsl_or_hsv ( r, g, b, true );
  }

}<commit_msg>Removed BOM from the file. It was messing us up when concatenating<commit_after>/**
 * @fileoverview
 * Color class
 */

/**
* @constructor
*
*
* @class
* Represent a color. Allows for setting and getting color components based
* on RGV, HSV and HSL color spaces.
* See also http://en.wikipedia.org/wiki/Color_space
*/
var Colors = function()
{
  const
  RED = 0,
  GREEN = 1,
  BLUE = 2,
  HUE = 0,
  SAT = 1,
  LUM = 2;

  var rgb = [0, 0, 0];
  var hsl = [0, 50, 50];
  var hsv = [0, 50, 50];

  /**
   * return val bounded to upper or lower if it over/underflows
   * @private
   * @param val {number} value to bound
   * @param upper {number} upper bound
   * @param lower {number} lower bound
   * @returns {number}
   */
  var fixRange = function( val, upper, lower)
  {
    return val > upper ? upper : val < lower ? lower : val;
  }

  /**
   * rounds off val and bounds it to upper and lower
   * @see Colors#fixRange
   * @private
   * @returns {number}
   * @param val {number} value to bound
   * @param upper {number} upper bound
   * @param lower {number} lower bound
   */
  var roundVal = function( val, upper, lower)
  {
    val = Math.round(val);
    return val > upper ? upper : val < lower ? lower : val;
  }

  /**
   * turns val into a fixed number and bounds it to upper and lower
   * @see Colors#fixRange
   * @private
   * @returns {number}
   * @param val {number} value to bound
   * @param upper {number} upper bound
   * @param lower {number} lower bound
   */
  var toFixed = function( val, upper, lower)
  {
    val = val.toFixed(2);
    return val > upper ? upper : val < lower ? lower : val;
  }

  /**
   * Set the hue component of the color
   * @param h {int} desired value of hue
   * @returns {int} new value of hue
   */
  this.setHue = function(h)
  {
    h = fixRange(h, 360, 0);
    hsl[HUE] = parseInt(h);
    rgb = this.hsl_to_rgb( hsl[HUE], hsl[SAT], hsl[LUM] );
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return h;
  }

  /**
   * Set the saturation component of the color
   * @param s {int} desired value of saturation
   * @returns {int} new value of saturation
   */
  this.setSaturation = function(s)
  {
    s = fixRange(s, 100, 0);
    hsl[SAT] = parseFloat(s);
    rgb = this.hsl_to_rgb( hsl[HUE], hsl[SAT], hsl[LUM] );
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return s;
  }

  /**
   * Set the luminosity component of the color
   * @param l {int} desired value of luminosity
   * @returns {int} new value of luminosity
   */
  this.setLuminosity = function(l)
  {
    l = fixRange(l, 100, 0);
    hsl[LUM] = parseFloat(l);
    rgb = this.hsl_to_rgb( hsl[HUE], hsl[SAT], hsl[LUM] );
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return l;
  }

  /**
   * Set hue component of the color, using HSV
   * http://en.wikipedia.org/wiki/HSV_color_space
   * @param h {float} desired value of hue
   * @returns {int} new value of hue
   */
  this.setHueV = function(h)
  {
    h = fixRange(h, 360, 0);
    hsv[HUE] = parseInt(h);
    rgb = this.hsv_to_rgb( hsv[HUE], hsv[SAT], hsv[LUM] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return h;
  }

  /**
   * Set the saturation component of the color, using HSV
   * @param h {float} desired value of saturation
   * @returns {int} new value of saturation
   */
  this.setSaturationV = function(s)
  {
    s = fixRange(s, 100, 0);
    hsv[SAT] = parseFloat(s);
    rgb = this.hsv_to_rgb( hsv[HUE], hsv[SAT], hsv[LUM] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return s;
  }

  /**
   * Set the value component of the color, using HSV
   * @param h {float} desired value of value
   * @returns {int} new value of value
   */
  this.setValue = function(l)
  {
    l = fixRange(l, 100, 0);
    hsv[LUM] = parseFloat(l);
    rgb = this.hsv_to_rgb( hsv[HUE], hsv[SAT], hsv[LUM] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return l;
  }

  /**
   * Set the red component of the color
   * @param r {int} value of red component
   * @returns {int} value of red component
   */
  this.setRed = function(r)
  {
    r = fixRange(r, 255, 0);
    rgb[RED] = parseInt(r);
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return r;
  }

  /**
   * Set the green component of the color
   * @param g {int} value of green component
   * @returns {int} value of green component
   */
  this.setGreen = function(g)
  {
    g = fixRange(g, 255, 0);
    rgb[GREEN] = parseInt(g);
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return g;
  }

  /**
   * Set the red, green and blue components of the color
   * @param c_arr {array} array containing red,green,blue ints
   */
  this.setRGB = function(c_arr)
  {
    var i = 0;
    for( ; i < 3; i++)
    {
      rgb[i] = c_arr[i] > 255 ? 255 : c_arr[i];
    }
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
  }

  /**
   * Set the blue component of the color
   * @param b {int} value of blue component
   * @returns {int} value of blue component
   */
  this.setBlue = function(b)
  {
    b = fixRange(b, 255, 0);
    rgb[BLUE] = parseInt(b);
    hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
    hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    return b;
  }

  /**
   * Set the color from a hex color code
   * @param hex {String} hex color
   * @returns {String} hex color
   */
  this.setHex = function(hex)
  {
    hex = /^[0-9a-f]*$/i.test(hex) ? hex : '';
    if(hex)
    {
      hex = hex.slice(0,6);
      var temp = parseInt(hex, 16);
      rgb = [ temp >> 16, ( temp >> 8 ) & 0xff, temp & 0xff ];
      hsv = this.rgb_to_hsv( rgb[RED], rgb[GREEN], rgb[BLUE] );
      hsl = this.rgb_to_hsl( rgb[RED], rgb[GREEN], rgb[BLUE] );
    }
    return hex;
  }

  /**
   * Get hue component of color
   * @returns {int} hue
   */
  this.getHue = function()
  {
    return roundVal(hsl[HUE], 360, 0);
  }

  /**
   * Get saturation component of color
   * @returns {int} saturation
   */
  this.getSaturation = function()
  {
    return toFixed(hsl[SAT], 100, 0);
  }

  /**
   * Get luminosity component of color
   * @returns {int} luminosity
   */
  this.getLuminosity = function()
  {
    return toFixed(hsl[LUM], 100, 0);
  }

  /**
   * Get hue, saturation and luminosity of color as an array
   * @returns {array} [hue, sat, lum]
   */
  this.getHSL = function()
  {
    return [roundVal(hsl[0], 360, 0), toFixed(hsl[1], 100, 0), toFixed(hsl[2], 100, 0)];
  }

  /**
   * Get hue component of color (HSV)
   * @returns {int} hue
   */
  this.getHueV = function()
  {
    return roundVal(hsv[HUE], 360, 0);
  }

  /**
   * Get saturation component of color (HSV)
   * @returns {int} saturation
   */
  this.getSaturationV = function()
  {
    return toFixed(hsv[SAT], 100, 0);
  }

  /**
   * Get value component of color (HSV)
   * @returns {int} value
   */
  this.getValue = function()
  {
    return toFixed(hsv[LUM], 100, 0);
  }

  /**
   * Get red component of color
   * @returns {int} red value
   */
  this.getRed = function()
  {
    return roundVal(rgb[RED], 255, 0);
  }

  /**
   * Get green component of color
   * @returns {int} green value
   */
  this.getGreen = function()
  {
    return roundVal(rgb[GREEN], 255, 0);
  }

  /**
   * Get blue component of color
   * @returns {int} blue
   */
  this.getBlue = function()
  {
    return roundVal(rgb[BLUE], 255, 0);
  }

  /**
   * Get red, green and blue component of color as an array
   * @returns {array} [r, g, b]
   */
  this.getRGB = function()
  {
    return [roundVal(rgb[0], 255, 0), roundVal(rgb[1], 255, 0), roundVal(rgb[2], 255, 0)];
  }

  /**
   * Get hex value of color
   * @returns {String} hex value
   */
  this.getHex = function()
  {
    return this.rgb_to_hex_c(rgb);
  }

}

Colors.prototype = new function()
{
  var self = this;

  var roundVal = function( val, upper, lower)
  {
    val = Math.round(val);
    return val > upper ? upper : val < lower ? lower : val;
  }

  var hsl_or_hsv_to_rgb = function ( h, s, l, is_hsl )
  {
    var ret = self.hue_to_rgb(h), i = 0;
    if( is_hsl)
    {
      ret = self.mix_rgb(ret, [127.5, 127.5, 127.5], 1 - s / 100);
      if( l <= 50 )
      {
        ret = self.mix_rgb([0, 0, 0], ret, l/50);
      }
      else
      {
        ret = self.mix_rgb(ret, [0xff, 0xff, 0xff], ( l - 50 ) / 50);
      }
    }
    else
    {
      ret = self.mix_rgb(ret, [0xff, 0xff, 0xff], 1 - s / 100);
      ret = self.mix_rgb([0, 0, 0], ret, l/100);
    }
    return ret;
  }

  var rgb_to_hsl_or_hsv = function ( r, g, b, is_to_hsl )
  {
    r /= 255;
    g /= 255;
    b /= 255;

    var h = 0
    var s = 0;
    var l = 0;
    var maxcolor = Math.max(r, g, b);
    var mincolor = Math.min(r, g, b);
    var delta = maxcolor - mincolor;
    var sum = maxcolor + mincolor;

    if( is_to_hsl )
    {
      l = sum / 2;
    }
    else
    {
      l = maxcolor;
    }

    if( delta == 0 )
    {
      s = h = 0;
    }
    else
    {
      if( is_to_hsl )
      {
        if( l < 0.5 )
        {
          s = delta / sum;
        }
        else
        {
          s = delta / ( 2 - sum );
        }
      }
      else
      {
        s = delta / maxcolor;
      }

      if( r == maxcolor )
      {
        h = ( g - b ) / delta;
      }
      else if( g == maxcolor )
      {
        h = 2.0 + ( b - r ) / delta;
      }
      else
      {
        h = 4.0 + ( r - g ) / delta;
      }
    }

    h *= 60;
    if( h > 360 )
    {
      h = 360;
    }
    else if ( h < 0 )
    {
      h += 360;
    }
    s *= 100;
    if( s > 100 )
    {
      s = 100;
    }
    l *= 100;
    if( l > 100 )
    {
      l = 100;
    }

    return [ h, s, l ];
  }

  this.rgb_c_to_hex_c = function(c)
  {
    c = roundVal(c, 255, 0);
    return ( c < 16 ? '0' : '' ) + c.toString(16);
  }

  this.rgb_to_hex_c = function(c_arr)
  {
    var ret = '', i = 0, c = 0;
    for( ; i < 3; i++ )
    {
      c = roundVal(c_arr[i], 255, 0);
      if( c > 255 ) c = 255;
      ret +=  ( c < 16 ? '0' : '' ) + c.toString(16);
    }
    return ret;
  }

  this.mix_rgb = function(c_1, c_2, m)
  {
    var ret = [], i = 0;
    for( ; i < 3; i++ )
    {
      ret[i] = c_1[i] + m * ( c_2[i] - c_1[i] );
    }
    return ret;
  }

  this.hue_to_rgb = function(h)
  {
    h = h % 360;
    var delta = h % 60;
    h -= delta;
    delta = ( 255 / 60 * delta ) >> 0;
    if( h < 60 ) return [0xff, delta, 0];
    if( h < 120 ) return  [0xff - delta, 0xff, 0];
    if( h < 180 ) return  [0, 0xff, delta];
    if( h < 240 ) return  [0, 0xff - delta, 0xff];
    if( h < 300 ) return  [delta, 0, 0xff];
    if( h < 360 ) return  [0xff, 0, 0xff - delta];
  }

  this.hsl_to_rgb = function ( h, s, l )
  {
    return hsl_or_hsv_to_rgb( h, s, l, true);
  }

  this.hsv_to_rgb = function ( h, s, v )
  {
    return hsl_or_hsv_to_rgb( h, s, v, false);
  }

  this.rgb_to_hsv = function ( r, g, b )
  {
    return rgb_to_hsl_or_hsv ( r, g, b, false );
  }

  this.rgb_to_hsl = function ( r, g, b )
  {
    return rgb_to_hsl_or_hsv ( r, g, b, true );
  }

}<|endoftext|>


<commit_before>import { remote } from 'electron';
import servers from './servers';
import sidebar from './sidebar';
import webview from './webview';

const { app, getCurrentWindow, shell } = remote;
const { certificate, dock, menus, showAboutDialog, tray } = remote.require('./background');

export default () => {
	menus.on('quit', () => app.quit());
	menus.on('about', () => showAboutDialog());
	menus.on('open-url', (url) => shell.openExternal(url));

	menus.on('add-new-server', () => {
		getCurrentWindow().show();
		servers.clearActive();
		webview.showLanding();
	});

	menus.on('select-server', ({ url }) => {
		getCurrentWindow().show();
		servers.setActive(url);
	});

	menus.on('reload-server', ({ ignoringCache = false, clearCertificates = false } = {}) => {
		if (clearCertificates) {
			certificate.clear();
		}

		const activeWebview = webview.getActive();
		if (!activeWebview) {
			return;
		}

		if (ignoringCache) {
			activeWebview.reloadIgnoringCache();
			return;
		}

		activeWebview.reload();
	});

	menus.on('open-devtools-for-server', () => {
		const activeWebview = webview.getActive();
		if (activeWebview) {
			activeWebview.openDevTools();
		}
	});

	menus.on('go-back', () => webview.goBack());
	menus.on('go-forward', () => webview.goForward());

	menus.on('reload-app', () => {
		const mainWindow = getCurrentWindow();
		mainWindow.removeAllListeners();
		menus.removeAllListeners();
		tray.destroy();
		dock.destroy();
		mainWindow.reload();
	});

	menus.on('toggle-devtools', () => getCurrentWindow().toggleDevTools());

	menus.on('reset-app-data', () => servers.resetAppData());

	const updatePreferences = () => {
		const mainWindow = getCurrentWindow();

		menus.setState({
			showTrayIcon: localStorage.getItem('hideTray') ?
				localStorage.getItem('hideTray') !== 'true' : (process.platform !== 'linux'),
			showUserStatusInTray: (localStorage.getItem('showUserStatusInTray') || 'true') === 'true',
			showFullScreen: mainWindow.isFullScreen(),
			showWindowOnUnreadChanged: localStorage.getItem('showWindowOnUnreadChanged') === 'true',
			showMenuBar: localStorage.getItem('autohideMenu') !== 'true',
			showServerList: localStorage.getItem('sidebar-closed') !== 'true',
		});

		tray.setState({
			showIcon: localStorage.getItem('hideTray') ?
				localStorage.getItem('hideTray') !== 'true' : (process.platform !== 'linux'),
			showUserStatus: (localStorage.getItem('showUserStatusInTray') || 'true') === 'true',
		});
	};

	menus.on('toggle', (property) => {
		switch (property) {
			case 'showTrayIcon': {
				const previousValue = localStorage.getItem('hideTray') !== 'true';
				const newValue = !previousValue;
				localStorage.setItem('hideTray', JSON.stringify(!newValue));
				break;
			}

			case 'showUserStatusInTray': {
				const previousValue = (localStorage.getItem('showUserStatusInTray') || 'true') === 'true';
				const newValue = !previousValue;
				localStorage.setItem('showUserStatusInTray', JSON.stringify(newValue));
				break;
			}

			case 'showFullScreen': {
				const mainWindow = getCurrentWindow();
				mainWindow.setFullScreen(!mainWindow.isFullScreen());
				break;
			}

			case 'showWindowOnUnreadChanged': {
				const previousValue = localStorage.getItem('showWindowOnUnreadChanged') === 'true';
				const newValue = !previousValue;
				localStorage.setItem('showWindowOnUnreadChanged', JSON.stringify(newValue));
				break;
			}

			case 'showMenuBar': {
				const previousValue = localStorage.getItem('autohideMenu') !== 'true';
				const newValue = !previousValue;
				localStorage.setItem('autohideMenu', JSON.stringify(!newValue));
				break;
			}

			case 'showServerList': {
				sidebar.toggle();
				break;
			}
		}

		updatePreferences();
	});

	const updateServers = () => {
		menus.setState({
			servers: Object.values(servers.hosts)
				.sort((a, b) => (sidebar ? (sidebar.sortOrder.indexOf(a.url) - sidebar.sortOrder.indexOf(b.url)) : 0))
				.map(({ title, url }) => ({ title, url })),
			currentServerUrl: servers.active,
		});
	};

	servers.on('loaded', updateServers);
	servers.on('active-cleared', updateServers);
	servers.on('active-setted', updateServers);
	servers.on('host-added', updateServers);
	servers.on('host-removed', updateServers);
	servers.on('title-setted', updateServers);
	sidebar.on('hosts-sorted', updateServers);

	sidebar.on('badge-setted', () => {
		const badge = sidebar.getGlobalBadge();
		tray.setState({ badge });
		dock.setState({ badge });
	});

	const updateWindowState = () =>
		tray.setState({ isMainWindowVisible: getCurrentWindow().isVisible() });
	getCurrentWindow().on('hide', updateWindowState);
	getCurrentWindow().on('show', updateWindowState);

	tray.on('created', () => getCurrentWindow().emit('set-state', { hideOnClose: true }));
	tray.on('destroyed', () => getCurrentWindow().emit('set-state', { hideOnClose: false }));
	tray.on('set-main-window-visibility', (visible) =>
		(visible ? getCurrentWindow().show() : getCurrentWindow().hide()));
	tray.on('quit', () => app.quit());

	webview.on('ipc-message-unread-changed', (hostUrl, [count]) => {
		if (typeof count === 'number' && localStorage.getItem('showWindowOnUnreadChanged') === 'true') {
			const mainWindow = remote.getCurrentWindow();
			if (!mainWindow.isFocused()) {
				mainWindow.once('focus', () => mainWindow.flashFrame(false));
				mainWindow.showInactive();
				mainWindow.flashFrame(true);
			}
		}
	});

	webview.on('ipc-message-user-status-manually-set', (hostUrl, [status]) => {
		tray.setState({ status });
		dock.setState({ status });
	});

	servers.restoreActive();
	updatePreferences();
	updateServers();
	updateWindowState();

};
<commit_msg>[fix] Add additional condition for option "Show on unread" to show Rocket.Chat window<commit_after>import { remote } from 'electron';
import servers from './servers';
import sidebar from './sidebar';
import webview from './webview';

const { app, getCurrentWindow, shell } = remote;
const { certificate, dock, menus, showAboutDialog, tray } = remote.require('./background');

export default () => {
	menus.on('quit', () => app.quit());
	menus.on('about', () => showAboutDialog());
	menus.on('open-url', (url) => shell.openExternal(url));

	menus.on('add-new-server', () => {
		getCurrentWindow().show();
		servers.clearActive();
		webview.showLanding();
	});

	menus.on('select-server', ({ url }) => {
		getCurrentWindow().show();
		servers.setActive(url);
	});

	menus.on('reload-server', ({ ignoringCache = false, clearCertificates = false } = {}) => {
		if (clearCertificates) {
			certificate.clear();
		}

		const activeWebview = webview.getActive();
		if (!activeWebview) {
			return;
		}

		if (ignoringCache) {
			activeWebview.reloadIgnoringCache();
			return;
		}

		activeWebview.reload();
	});

	menus.on('open-devtools-for-server', () => {
		const activeWebview = webview.getActive();
		if (activeWebview) {
			activeWebview.openDevTools();
		}
	});

	menus.on('go-back', () => webview.goBack());
	menus.on('go-forward', () => webview.goForward());

	menus.on('reload-app', () => {
		const mainWindow = getCurrentWindow();
		mainWindow.removeAllListeners();
		menus.removeAllListeners();
		tray.destroy();
		dock.destroy();
		mainWindow.reload();
	});

	menus.on('toggle-devtools', () => getCurrentWindow().toggleDevTools());

	menus.on('reset-app-data', () => servers.resetAppData());

	const updatePreferences = () => {
		const mainWindow = getCurrentWindow();

		menus.setState({
			showTrayIcon: localStorage.getItem('hideTray') ?
				localStorage.getItem('hideTray') !== 'true' : (process.platform !== 'linux'),
			showUserStatusInTray: (localStorage.getItem('showUserStatusInTray') || 'true') === 'true',
			showFullScreen: mainWindow.isFullScreen(),
			showWindowOnUnreadChanged: localStorage.getItem('showWindowOnUnreadChanged') === 'true',
			showMenuBar: localStorage.getItem('autohideMenu') !== 'true',
			showServerList: localStorage.getItem('sidebar-closed') !== 'true',
		});

		tray.setState({
			showIcon: localStorage.getItem('hideTray') ?
				localStorage.getItem('hideTray') !== 'true' : (process.platform !== 'linux'),
			showUserStatus: (localStorage.getItem('showUserStatusInTray') || 'true') === 'true',
		});
	};

	menus.on('toggle', (property) => {
		switch (property) {
			case 'showTrayIcon': {
				const previousValue = localStorage.getItem('hideTray') !== 'true';
				const newValue = !previousValue;
				localStorage.setItem('hideTray', JSON.stringify(!newValue));
				break;
			}

			case 'showUserStatusInTray': {
				const previousValue = (localStorage.getItem('showUserStatusInTray') || 'true') === 'true';
				const newValue = !previousValue;
				localStorage.setItem('showUserStatusInTray', JSON.stringify(newValue));
				break;
			}

			case 'showFullScreen': {
				const mainWindow = getCurrentWindow();
				mainWindow.setFullScreen(!mainWindow.isFullScreen());
				break;
			}

			case 'showWindowOnUnreadChanged': {
				const previousValue = localStorage.getItem('showWindowOnUnreadChanged') === 'true';
				const newValue = !previousValue;
				localStorage.setItem('showWindowOnUnreadChanged', JSON.stringify(newValue));
				break;
			}

			case 'showMenuBar': {
				const previousValue = localStorage.getItem('autohideMenu') !== 'true';
				const newValue = !previousValue;
				localStorage.setItem('autohideMenu', JSON.stringify(!newValue));
				break;
			}

			case 'showServerList': {
				sidebar.toggle();
				break;
			}
		}

		updatePreferences();
	});

	const updateServers = () => {
		menus.setState({
			servers: Object.values(servers.hosts)
				.sort((a, b) => (sidebar ? (sidebar.sortOrder.indexOf(a.url) - sidebar.sortOrder.indexOf(b.url)) : 0))
				.map(({ title, url }) => ({ title, url })),
			currentServerUrl: servers.active,
		});
	};

	servers.on('loaded', updateServers);
	servers.on('active-cleared', updateServers);
	servers.on('active-setted', updateServers);
	servers.on('host-added', updateServers);
	servers.on('host-removed', updateServers);
	servers.on('title-setted', updateServers);
	sidebar.on('hosts-sorted', updateServers);

	sidebar.on('badge-setted', () => {
		const badge = sidebar.getGlobalBadge();
		tray.setState({ badge });
		dock.setState({ badge });
	});

	const updateWindowState = () =>
		tray.setState({ isMainWindowVisible: getCurrentWindow().isVisible() });
	getCurrentWindow().on('hide', updateWindowState);
	getCurrentWindow().on('show', updateWindowState);

	tray.on('created', () => getCurrentWindow().emit('set-state', { hideOnClose: true }));
	tray.on('destroyed', () => getCurrentWindow().emit('set-state', { hideOnClose: false }));
	tray.on('set-main-window-visibility', (visible) =>
		(visible ? getCurrentWindow().show() : getCurrentWindow().hide()));
	tray.on('quit', () => app.quit());

	webview.on('ipc-message-unread-changed', (hostUrl, [count]) => {
		if (typeof count === 'number' && localStorage.getItem('showWindowOnUnreadChanged') === 'true') {
			const mainWindow = remote.getCurrentWindow();
			const isNeededToShow = !mainWindow.isFocused() || (mainWindow.isFocused() && !mainWindow.isVisible());
			if (isNeededToShow) {
				mainWindow.once('focus', () => mainWindow.flashFrame(false));
				mainWindow.showInactive();
				mainWindow.flashFrame(true);
			}
		}
	});

	webview.on('ipc-message-user-status-manually-set', (hostUrl, [status]) => {
		tray.setState({ status });
		dock.setState({ status });
	});

	servers.restoreActive();
	updatePreferences();
	updateServers();
	updateWindowState();

};
<|endoftext|>


<commit_before>// Beautiful player using POO

// Work In Progress

class Player {
  constructor(params = {
    basePath,
    parent,
    id,
    className,
    link,
    width,
    height,
    controls,
    autoplay
  }) {

    this.parent = document.querySelector(params.parent)
    this.link = params.basePath + params.link
    this.width = params.width
    this.height = params.height
    this.autoplay = params.autoplay
    this.id = params.id
    this.className = params.className

    this.playerContainer = document.createElement('div')

    this.playerContainer.className = 'playerContainer'
    this.playerContainer.tabIndex = 0
    this.playerContainer.style.width = this.width + 'px'
    this.playerContainer.style.height = 'auto'
    this.parent.appendChild(this.playerContainer)

    this.player = document.createElement('video')

    this.player.src = this.link
    this.player.id = this.id
    this.player.className = this.className
    this.player.autoplay = this.autoplay
    this.player.controls = false

    this.playerContainer.appendChild(this.player)

    // Check ifcontrols are required
    if (params.controls) {
      this.createControllers()
    } else {
      console.log('To enable controllers turn controls to true')
    }
  }

  createControllers() {

    let player = this.player
    let playerContainer = this.playerContainer
    let parent = this.parent

    // Create control bar
    let controlBar = document.createElement('div')
    controlBar.className = 'controlBar'
    playerContainer.appendChild(controlBar)

    // Create play/pause button
    let playPauseButton = document.createElement('div')
    playPauseButton.className = 'playPauseButton'
    controlBar.appendChild(playPauseButton)

    // Create Mute Button
    let muteButton = document.createElement('div')
    muteButton.className = 'muteButton'
    controlBar.appendChild(muteButton)

    // Create Volume Slider
    let volumeController = document.createElement('div')
    volumeController.className = 'volumeController'
    controlBar.appendChild(volumeController)

    // Create Volume Bar inside Volume Slider
    let volumeBar = document.createElement('div')
    volumeBar.className = 'volumeBar'
    volumeController.appendChild(volumeBar)

    let activeVolume = false

    // Create currentTimer
    let currentTimer = document.createElement('div')
    currentTimer.className = 'currentTimer'
    currentTimer.innerHTML = '0:00'
    controlBar.appendChild(currentTimer)

    // Create Timeline
    let timeline = document.createElement('div')
    timeline.className = 'timeline'
    controlBar.appendChild(timeline)
    let activeTimeline = false

    // Create vars for lerp
    let position = 0
    let amount = 0.1

    // Create TimelineLoadingBar
    let timelineLoadingBar = document.createElement('div')
    timelineLoadingBar.className = 'timelineLoadingBar'
    timeline.appendChild(timelineLoadingBar)

    // Create Timeline Bar
    let timelineBar = document.createElement('div')
    timelineBar.className = 'timelineBar'
    timeline.appendChild(timelineBar)

    // Create durationTimer
    let durationTimer = document.createElement('div')
    durationTimer.className = 'durationTimer'
    durationTimer.innerHTML = '0:00'
    controlBar.appendChild(durationTimer)

    // Create fullscreenButton
    let fullscreenButton = document.createElement('div')
    fullscreenButton.className = 'fullscreenButton'
    controlBar.appendChild(fullscreenButton)

    let fullscreenMode = false

    // Check at start

    // Check Video Status to display the right button
    if (player.autoplay) {
      playPauseButton.classList.add('isPlaying')
    } else {
      playPauseButton.classList.remove('isPlaying')
    }

    // Set volume at start
    player.volume = 0
    volumeBar.style.transform = 'scaleX(' + player.volume + ')'

    // Events

    // PlayPause Events
    let playPauseEvents = [player, playPauseButton]
    playPauseEvents.forEach(function(e) {
      e.addEventListener('click', function() {
        if (player.paused) {
          player.play()
          playPauseButton.classList.add('isPlaying')
        } else {
          player.pause()
          playPauseButton.classList.remove('isPlaying')
        }
      })
    })

    parent.addEventListener('keydown', function(e) {
      if (e.keyCode === 32) {
        if (player.paused) {
          player.play()
          playPauseButton.classList.add('isPlaying')
        } else {
          player.pause()
          playPauseButton.classList.remove('isPlaying')
        }
      }
    })

    // Volume Events
    muteButton.addEventListener('click', function() {
      let volumeSaved = 0;
      if (!muteButton.classList.contains('isMuted')) {
        this.volumeSaved = player.volume
        player.volume = 0;
        muteButton.classList.toggle('isMuted')
      } else {
        player.volume = this.volumeSaved
        muteButton.classList.toggle('isMuted')
      }
    })

    volumeController.addEventListener('mousedown', function(event) {
      activeVolume = true
      muteButton.classList.remove('isMuted')
      if (0.1 <= event.offsetX / volumeController.offsetWidth && event.offsetX / volumeController.offsetWidth <= 0.9) {
        player.volume = event.offsetX / volumeController.offsetWidth
      } else if (event.offsetX / volumeController.offsetWidth < 0.1) {
        player.volume = 0
        muteButton.classList.add('isMuted')
      } else {
        player.volume = 1
      }
      volumeBar.style.transform = 'scaleX(' + player.volume + ')'
    })

    volumeController.addEventListener('mousemove', function(event) {
      if (activeVolume) {
        muteButton.classList.remove('isMuted')
        if (0.1 <= event.offsetX / volumeController.offsetWidth && event.offsetX / volumeController.offsetWidth <= 0.9) {
          player.volume = event.offsetX / volumeController.offsetWidth
        } else if (event.offsetX / volumeController.offsetWidth < 0.1) {
          player.volume = 0
          muteButton.classList.add('isMuted')
        } else {
          player.volume = 1
        }
        volumeBar.style.transform = 'scaleX(' + player.volume + ')'
      }
    })

    window.addEventListener('mouseup', function() {
      activeVolume = false
    })

    // Timeline Events
    setInterval(function barProgression() {
      // Display bar progression
      let timelineBarProgression = player.currentTime / player.duration

      if (position === 0) {
        timelineBar.style.transform = 'scaleX(' + timelineBarProgression + ')'
        position += player.currentTime
      } else {
        position += (player.currentTime - position) * amount
        timelineBarProgression = position / player.duration
        timelineBar.style.transform = 'scaleX(' + timelineBarProgression + ')'
      }

      // Display on timeline what is already loaded
      timelineLoadingBar.style.transform = 'scaleX(' + player.buffered.end(0) / player.duration + ')'

    }, 16);

    player.addEventListener('timeupdate', function() {

      // Display time formated
      let durationTimeFormated = new Date(null)
      durationTimeFormated.setSeconds(Math.floor(player.duration))
      let ds = durationTimeFormated.getSeconds()
      let dm = durationTimeFormated.getMinutes()
      let dh = durationTimeFormated.getUTCHours()

      let currentTimeFormated = new Date(null)
      currentTimeFormated.setSeconds(Math.floor(player.currentTime))

      let cs = currentTimeFormated.getSeconds()
      let cm = currentTimeFormated.getMinutes()
      let ch = currentTimeFormated.getUTCHours()

      // Checks for currentTime display
      if (cs >= 0 && cs < 10)  {
        cs = '0' + cs
      }
      if (ch > 0 && (cm === 0 && cm < 10)) {
        cm = '0' + cm
      }

      // Checks for durationTime display
      if (ds >= 0 && ds < 10) {
        ds = '0' + ds
      }
      if (dh > 0 && (dm === 0 && dm < 10)) {
        dm = '0' + cm
      }

      //
      if (dh === 0 || ch === 0) {
        currentTimer.innerHTML = cm + ':' + cs
        durationTimer.innerHTML = dm + ':' + ds
      } else {
        currentTimer.innerHTML = ch + ':' + cm + ':' + cs
        durationTimer.innerHTML = dh + ':' + dm + ':' + ds
      }
    })

    timeline.addEventListener('mousedown', function(event) {
      player.pause()
      timelineBar.classList.add('isTransiting')
      activeTimeline = true
      let requestedPosition = event.offsetX / timeline.offsetWidth
      player.currentTime = player.duration * requestedPosition
      timelineBar.style.transform = 'scaleX(' + requestedPosition + ')'
      position = player.currentTime
    })

    timeline.addEventListener('mousemove', function(event) {
      if (activeTimeline) {
        let requestedPosition = event.offsetX / timeline.offsetWidth
        player.currentTime = player.duration * requestedPosition
        timelineBar.style.transform = 'scaleX(' + requestedPosition + ')'
        position = player.currentTime
      }
    })

    window.addEventListener('mouseup', function() {
      if (activeTimeline) {
        timelineBar.classList.remove('isTransiting')
        player.play()
        playPauseButton.classList.add('isPlaying')
        activeTimeline = false
      }
    })

    // Fullscreen
    fullscreenButton.addEventListener('click', function(e) {
      if (!fullscreenMode) {
        if (playerContainer.requestFullscreen) {
          playerContainer.requestFullscreen();
        } else if (playerContainer.mozRequestFullScreen) {
          playerContainer.mozRequestFullScreen();
        } else if (playerContainer.webkitRequestFullscreen) {
          playerContainer.webkitRequestFullscreen();
        }
        fullscreenMode = true
      } else {
        if (document.cancelFullScreen) {
          document.cancelFullScreen();
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen();
        }
        fullscreenMode = false
      }
    })

    // Fullscreen on double click
    player.addEventListener('dblclick', function(e) {
      if (!fullscreenMode) {
        if (playerContainer.requestFullscreen) {
          playerContainer.requestFullscreen();
        } else if (playerContainer.mozRequestFullScreen) {
          playerContainer.mozRequestFullScreen();
        } else if (playerContainer.webkitRequestFullscreen) {
          playerContainer.webkitRequestFullscreen();
        }
        fullscreenMode = true
      } else {
        if (document.cancelFullScreen) {
          document.cancelFullScreen();
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen();
        }
        fullscreenMode = false
      }
    })

    let isFullscreen = false;

    const fullscreenEvents = ["fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "msfullscreenchange"]
    fullscreenEvents.forEach(function(event) {
      document.addEventListener(event, function() {
        isFullscreen = !isFullscreen
        if (!isFullscreen) {
          fullscreenMode = false
        }
      })
    })
  }
}

// Creating new Player
let customPlayer = new Player({
  basePath: './src/videos/',
  parent: '.container',
  id: '1',
  className: 'customPlayer',
  link: 'video.mp4',
  width: 800,
  height: 'auto',
  controls: true,
  autoplay: true
})<commit_msg>Beautify JS again<commit_after>// Beautiful player using POO

// Work In Progress

class Player {
  constructor(params = {
    basePath,
    parent,
    id,
    className,
    link,
    width,
    height,
    controls,
    autoplay
  }) {

    this.parent = document.querySelector(params.parent)
    this.link = params.basePath + params.link
    this.width = params.width
    this.height = params.height
    this.autoplay = params.autoplay
    this.id = params.id
    this.className = params.className

    this.playerContainer = document.createElement('div')

    this.playerContainer.className = 'playerContainer'
    this.playerContainer.tabIndex = 0
    this.playerContainer.style.width = this.width + 'px'
    this.playerContainer.style.height = 'auto'
    this.parent.appendChild(this.playerContainer)

    this.player = document.createElement('video')

    this.player.src = this.link
    this.player.id = this.id
    this.player.className = this.className
    this.player.autoplay = this.autoplay
    this.player.controls = false

    this.playerContainer.appendChild(this.player)

    // Check ifcontrols are required
    if (params.controls) {
      this.createControllers()
    } else {
      console.log('To enable controllers turn controls to true')
    }
  }

  createControllers() {

    let player = this.player
    let playerContainer = this.playerContainer
    let parent = this.parent

    // Create control bar
    let controlBar = document.createElement('div')
    controlBar.className = 'controlBar'
    playerContainer.appendChild(controlBar)

    // Create play/pause button
    let playPauseButton = document.createElement('div')
    playPauseButton.className = 'playPauseButton'
    controlBar.appendChild(playPauseButton)

    // Create Mute Button
    let muteButton = document.createElement('div')
    muteButton.className = 'muteButton'
    controlBar.appendChild(muteButton)

    // Create Volume Slider
    let volumeController = document.createElement('div')
    volumeController.className = 'volumeController'
    controlBar.appendChild(volumeController)

    // Create Volume Bar inside Volume Slider
    let volumeBar = document.createElement('div')
    volumeBar.className = 'volumeBar'
    volumeController.appendChild(volumeBar)

    let activeVolume = false

    // Create currentTimer
    let currentTimer = document.createElement('div')
    currentTimer.className = 'currentTimer'
    currentTimer.innerHTML = '0:00'
    controlBar.appendChild(currentTimer)

    // Create Timeline
    let timeline = document.createElement('div')
    timeline.className = 'timeline'
    controlBar.appendChild(timeline)
    let activeTimeline = false

    // Create vars for lerp
    let position = 0
    let amount = 0.1

    // Create TimelineLoadingBar
    let timelineLoadingBar = document.createElement('div')
    timelineLoadingBar.className = 'timelineLoadingBar'
    timeline.appendChild(timelineLoadingBar)

    // Create Timeline Bar
    let timelineBar = document.createElement('div')
    timelineBar.className = 'timelineBar'
    timeline.appendChild(timelineBar)

    // Create durationTimer
    let durationTimer = document.createElement('div')
    durationTimer.className = 'durationTimer'
    durationTimer.innerHTML = '0:00'
    controlBar.appendChild(durationTimer)

    // Create fullscreenButton
    let fullscreenButton = document.createElement('div')
    fullscreenButton.className = 'fullscreenButton'
    controlBar.appendChild(fullscreenButton)

    let fullscreenMode = false

    // Check at start

    // Check Video Status to display the right button
    if (player.autoplay) {
      playPauseButton.classList.add('isPlaying')
    } else {
      playPauseButton.classList.remove('isPlaying')
    }

    // Set volume at start
    player.volume = 0
    volumeBar.style.transform = 'scaleX(' + player.volume + ')'

    // Events

    // PlayPause Events
    let playPauseEvents = [player, playPauseButton]
    playPauseEvents.forEach(function(e) {
      e.addEventListener('click', function() {
        if (player.paused) {
          player.play()
          playPauseButton.classList.add('isPlaying')
        } else {
          player.pause()
          playPauseButton.classList.remove('isPlaying')
        }
      })
    })

    parent.addEventListener('keydown', function(e) {
      if (e.keyCode === 32) {
        if (player.paused) {
          player.play()
          playPauseButton.classList.add('isPlaying')
        } else {
          player.pause()
          playPauseButton.classList.remove('isPlaying')
        }
      }
    })

    // Volume Events
    muteButton.addEventListener('click', function() {
      let volumeSaved = 0
      if (!muteButton.classList.contains('isMuted')) {
        this.volumeSaved = player.volume
        player.volume = 0
        muteButton.classList.toggle('isMuted')
      } else {
        player.volume = this.volumeSaved
        muteButton.classList.toggle('isMuted')
      }
    })

    volumeController.addEventListener('mousedown', function(event) {
      activeVolume = true
      muteButton.classList.remove('isMuted')
      if (0.1 <= event.offsetX / volumeController.offsetWidth && event.offsetX / volumeController.offsetWidth <= 0.9) {
        player.volume = event.offsetX / volumeController.offsetWidth
      } else if (event.offsetX / volumeController.offsetWidth < 0.1) {
        player.volume = 0
        muteButton.classList.add('isMuted')
      } else {
        player.volume = 1
      }
      volumeBar.style.transform = 'scaleX(' + player.volume + ')'
    })

    volumeController.addEventListener('mousemove', function(event) {
      if (activeVolume) {
        muteButton.classList.remove('isMuted')
        if (0.1 <= event.offsetX / volumeController.offsetWidth && event.offsetX / volumeController.offsetWidth <= 0.9) {
          player.volume = event.offsetX / volumeController.offsetWidth
        } else if (event.offsetX / volumeController.offsetWidth < 0.1) {
          player.volume = 0
          muteButton.classList.add('isMuted')
        } else {
          player.volume = 1
        }
        volumeBar.style.transform = 'scaleX(' + player.volume + ')'
      }
    })

    window.addEventListener('mouseup', function() {
      activeVolume = false
    })

    // Timeline Events
    setInterval(function barProgression() {
      // Display bar progression
      let timelineBarProgression = player.currentTime / player.duration

      if (position === 0) {
        timelineBar.style.transform = 'scaleX(' + timelineBarProgression + ')'
        position += player.currentTime
      } else {
        position += (player.currentTime - position) * amount
        timelineBarProgression = position / player.duration
        timelineBar.style.transform = 'scaleX(' + timelineBarProgression + ')'
      }

      // Display on timeline what is already loaded
      timelineLoadingBar.style.transform = 'scaleX(' + player.buffered.end(0) / player.duration + ')'

    }, 16)

    player.addEventListener('timeupdate', function() {

      // Display time formated
      let durationTimeFormated = new Date(null)
      durationTimeFormated.setSeconds(Math.floor(player.duration))
      let ds = durationTimeFormated.getSeconds()
      let dm = durationTimeFormated.getMinutes()
      let dh = durationTimeFormated.getUTCHours()

      let currentTimeFormated = new Date(null)
      currentTimeFormated.setSeconds(Math.floor(player.currentTime))

      let cs = currentTimeFormated.getSeconds()
      let cm = currentTimeFormated.getMinutes()
      let ch = currentTimeFormated.getUTCHours()

      // Checks for currentTime display
      if (cs >= 0 && cs < 10)  {
        cs = '0' + cs
      }
      if (ch > 0 && (cm === 0 && cm < 10)) {
        cm = '0' + cm
      }

      // Checks for durationTime display
      if (ds >= 0 && ds < 10) {
        ds = '0' + ds
      }
      if (dh > 0 && (dm === 0 && dm < 10)) {
        dm = '0' + cm
      }

      //
      if (dh === 0 || ch === 0) {
        currentTimer.innerHTML = cm + ':' + cs
        durationTimer.innerHTML = dm + ':' + ds
      } else {
        currentTimer.innerHTML = ch + ':' + cm + ':' + cs
        durationTimer.innerHTML = dh + ':' + dm + ':' + ds
      }
    })

    timeline.addEventListener('mousedown', function(event) {
      player.pause()
      timelineBar.classList.add('isTransiting')
      activeTimeline = true
      let requestedPosition = event.offsetX / timeline.offsetWidth
      player.currentTime = player.duration * requestedPosition
      timelineBar.style.transform = 'scaleX(' + requestedPosition + ')'
      position = player.currentTime
    })

    timeline.addEventListener('mousemove', function(event) {
      if (activeTimeline) {
        let requestedPosition = event.offsetX / timeline.offsetWidth
        player.currentTime = player.duration * requestedPosition
        timelineBar.style.transform = 'scaleX(' + requestedPosition + ')'
        position = player.currentTime
      }
    })

    window.addEventListener('mouseup', function() {
      if (activeTimeline) {
        timelineBar.classList.remove('isTransiting')
        player.play()
        playPauseButton.classList.add('isPlaying')
        activeTimeline = false
      }
    })

    // Fullscreen
    fullscreenButton.addEventListener('click', function(e) {
      if (!fullscreenMode) {
        if (playerContainer.requestFullscreen) {
          playerContainer.requestFullscreen()
        } else if (playerContainer.mozRequestFullScreen) {
          playerContainer.mozRequestFullScreen()
        } else if (playerContainer.webkitRequestFullscreen) {
          playerContainer.webkitRequestFullscreen()
        }
        fullscreenMode = true
      } else {
        if (document.cancelFullScreen) {
          document.cancelFullScreen()
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen()
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen()
        }
        fullscreenMode = false
      }
    })

    // Fullscreen on double click
    player.addEventListener('dblclick', function(e) {
      if (!fullscreenMode) {
        if (playerContainer.requestFullscreen) {
          playerContainer.requestFullscreen()
        } else if (playerContainer.mozRequestFullScreen) {
          playerContainer.mozRequestFullScreen()
        } else if (playerContainer.webkitRequestFullscreen) {
          playerContainer.webkitRequestFullscreen()
        }
        fullscreenMode = true
      } else {
        if (document.cancelFullScreen) {
          document.cancelFullScreen()
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen()
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen()
        }
        fullscreenMode = false
      }
    })

    let isFullscreen = false

    const fullscreenEvents = ["fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "msfullscreenchange"]
    fullscreenEvents.forEach(function(event) {
      document.addEventListener(event, function() {
        isFullscreen = !isFullscreen
        if (!isFullscreen) {
          fullscreenMode = false
        }
      })
    })
  }
}

// Creating new Player
let customPlayer = new Player({
  basePath: './src/videos/',
  parent: '.container',
  id: '1',
  className: 'customPlayer',
  link: 'video.mp4',
  width: 800,
  height: 'auto',
  controls: true,
  autoplay: true
})<|endoftext|>


<commit_before>var assets = {
	objects: {
		"fern-01": { randScale: 0.3, noShadows: true },
		"fern-02": { randScale: 0.3, noShadows: true },
		"plant-01": { randScale: 0.3, noShadows: true },
		"plant-02": { randScale: 0.3, noShadows: true },
		"plant-03": { randScale: 0.3, noShadows: true },
		"plant-04": { randScale: 0.3, noShadows: true },
		"plant-05": { randScale: 0.3, noShadows: true },
		"rock-01": { collision: "sphere", mass: 400, randScale: 0.4 },
		"rock-02": { collision: "box", mass: 400, randScale: 0.4 },
		"rock-03": { collision: "box", mass: 400, randScale: 0.4 },
		"rock-04": { collision: "box", mass: 500, randScale: 0.4 },
		"barrel": { collision: "cylinder", mass: 250 },
		"box": { collision: "box", mass: 150 },
		"netted-jar": { collision: "cylinder", mass: 100 },
		"table-big": { collision: "box", mass: 1000 },
		"table-old": { collision: "box", mass: 800 },
		"chair-01": { collision: "box", mass: 200 },
		"torch-standing": { collision: "cylinder", mass: 150 },
		"mine-cart": { collision: "box", mass: 900 },
		"obelisk-01": { collision: "box", mass: 0 },
		"obelisk-02": { collision: "box", mass: 0 },
		"pillar-broken-01": { collision: "cylinder", mass: 0 },
		"pillar-broken-02": { collision: "cylinder", mass: 0 },
		"pillar-greek": { collision: "cylinder", mass: 0 },
		"forge": { collision: "concave", mass: 0 },
		"teleporter": { collision: "cylinder", mass: 0 }
	},
	items: {
		"key": {}
	},
	materials: {
		"rock-01": { roughness: 0.15 },
		"rock-02": { roughness: 0.15 },
		"rock-03": { roughness: 0.15 },
		"rock-04": { roughness: 0.15 }
	},
	monsters: {
		"cerberus": { collision: "box", character: { speed: 120 }, animation: { duration: 750 } }
	},
	environments: {
		"cave": {
			wall: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			floor: [ "sand-01", "sand-02", "sand-03", "sand-04" ],
			ceiling: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			objects: [ "rock-01", "rock-02", "rock-03", "rock-04" ]
		},
		"mine": {
			wall: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			floor: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			ceiling: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			objects: [ "mine-cart", "rock-01", "rock-02", "rock-03", "rock-04", "barrel", "box", "netted-jar", "table-old" ]
		},
		"dungeon": {
			wall: [ "stone-01", "stone-02", "stone-03" ],
			floor: [ "stone-floor-02", "stone-floor-05" ],
			ceiling: [ "stone-01" ],
			objects: [ "barrel", "box", "netted-jar", "table-old", "chair-01" ]
		},
		"castle": {
			wall: [ "stone-01", "tiles-01", "tiles-02" ],
			floor: [ "stone-floor-01", "stone-floor-03", "stone-floor-04", "stone-floor-06", "wood-floor-01" ],
			ceiling: [ "stone-01" ],
			objects: [ "barrel", "netted-jar", "table-big", "chair-01" ]
		},
		"temple": {
			wall: [ "stone-01", "tiles-01", "tiles-02" ],
			floor: [ "stone-floor-01", "stone-floor-03", "stone-floor-04", "stone-floor-06", "wood-floor-01" ],
			ceiling: [ "stone-01" ],
			objects: [ "pillar-greek", "pillar-greek", "netted-jar", "table-old", "chair-01" ]
		}
	}
};
<commit_msg>Add knife to editor.<commit_after>var assets = {
	objects: {
		"fern-01": { randScale: 0.3, noShadows: true },
		"fern-02": { randScale: 0.3, noShadows: true },
		"plant-01": { randScale: 0.3, noShadows: true },
		"plant-02": { randScale: 0.3, noShadows: true },
		"plant-03": { randScale: 0.3, noShadows: true },
		"plant-04": { randScale: 0.3, noShadows: true },
		"plant-05": { randScale: 0.3, noShadows: true },
		"rock-01": { collision: "sphere", mass: 400, randScale: 0.4 },
		"rock-02": { collision: "box", mass: 400, randScale: 0.4 },
		"rock-03": { collision: "box", mass: 400, randScale: 0.4 },
		"rock-04": { collision: "box", mass: 500, randScale: 0.4 },
		"barrel": { collision: "cylinder", mass: 250 },
		"box": { collision: "box", mass: 150 },
		"netted-jar": { collision: "cylinder", mass: 100 },
		"table-big": { collision: "box", mass: 1000 },
		"table-old": { collision: "box", mass: 800 },
		"chair-01": { collision: "box", mass: 200 },
		"torch-standing": { collision: "cylinder", mass: 150 },
		"mine-cart": { collision: "box", mass: 900 },
		"obelisk-01": { collision: "box", mass: 0 },
		"obelisk-02": { collision: "box", mass: 0 },
		"pillar-broken-01": { collision: "cylinder", mass: 0 },
		"pillar-broken-02": { collision: "cylinder", mass: 0 },
		"pillar-greek": { collision: "cylinder", mass: 0 },
		"forge": { collision: "concave", mass: 0 },
		"teleporter": { collision: "cylinder", mass: 0 }
	},
	items: {
		"key": {},
		"knife": {}
	},
	materials: {
		"rock-01": { roughness: 0.15 },
		"rock-02": { roughness: 0.15 },
		"rock-03": { roughness: 0.15 },
		"rock-04": { roughness: 0.15 }
	},
	monsters: {
		"cerberus": { collision: "box", character: { speed: 120 }, animation: { duration: 750 } }
	},
	environments: {
		"cave": {
			wall: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			floor: [ "sand-01", "sand-02", "sand-03", "sand-04" ],
			ceiling: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			objects: [ "rock-01", "rock-02", "rock-03", "rock-04" ]
		},
		"mine": {
			wall: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			floor: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			ceiling: [ "rock-01", "rock-02", "rock-03", "rock-04" ],
			objects: [ "mine-cart", "rock-01", "rock-02", "rock-03", "rock-04", "barrel", "box", "netted-jar", "table-old" ]
		},
		"dungeon": {
			wall: [ "stone-01", "stone-02", "stone-03" ],
			floor: [ "stone-floor-02", "stone-floor-05" ],
			ceiling: [ "stone-01" ],
			objects: [ "barrel", "box", "netted-jar", "table-old", "chair-01" ]
		},
		"castle": {
			wall: [ "stone-01", "tiles-01", "tiles-02" ],
			floor: [ "stone-floor-01", "stone-floor-03", "stone-floor-04", "stone-floor-06", "wood-floor-01" ],
			ceiling: [ "stone-01" ],
			objects: [ "barrel", "netted-jar", "table-big", "chair-01" ]
		},
		"temple": {
			wall: [ "stone-01", "tiles-01", "tiles-02" ],
			floor: [ "stone-floor-01", "stone-floor-03", "stone-floor-04", "stone-floor-06", "wood-floor-01" ],
			ceiling: [ "stone-01" ],
			objects: [ "pillar-greek", "pillar-greek", "netted-jar", "table-old", "chair-01" ]
		}
	}
};
<|endoftext|>


<commit_before>---
  #CAREFUL
---
console.log("ZZOOOOOOO88O888888888888OZ8ZZO$O77$I$II$\nZZZZOOOOOOO8OO888888888O8Z8ZZO$O77$I$II$\nZZZOOOOOOOO88O88O88888Z8OZ8ZZO$Z77$I$II$\nZO........88888OO88888ZOOZ8$ZZ7Z77$7Z77Z\nOOOZO?. . .OO8888888Z8ZOOZ8$.........77Z\nOOOOOO......O888888OZ8ZOOZOI.Z7Z..$7Z77Z\nOOOOOO.    .8O888Z8OZ8ZOOZO.ZZ7Z.7Z7Z7$O\nOOOOOO..8. ..O8O8Z8OZ8ZOO$.+..7Z.7Z7Z77Z\nO8OOOO. OO....8Z8Z8OZ8ZOO.....$O.7Z7O$$Z\nOOOOOO..88.....:8Z8ZZ8ZOO...+.$O.$Z$$$ZZ\nOOOOOO..8OO..8Z.8Z8OZ8ZO.Z.Z+.$O.$OZZZZZ\nOOOOOO. 8888.8ZZ.Z8ZZ8Z.,.8Z?.$O.$ZZZZZZ\nOOOOOO..8OO8~.ZZ..8ZZ8....8Z?.Z8.ZZZZZZZ\nOOOOO8. OOZ8Z..Z8 IOZ8.?.Z8Z?.Z8ZZZZZZZZ\nOOOOOO..=.Z8Z8.Z8Z.OZ.Z.OZ8Z?.ZOOOOOOZZZ\nOOOOOO.. .Z8Z8O.8Z$....ZOZ8Z?.OOOOOOOOOO\nOOO888O. .OOZ8Z. Z8....8OZ8ZIOOOOOOOOOOO\nO8OOOOO...OOZ8ZO..8O$.Z8OZ8ZOOOOOOOOOOOO\nOOOOZO7.,.OOZ8ZO8.8O.8Z8OZOOOOOOOOOOOOOO\nOO8....Z8 ...8Z88Z..?8Z8OOOOOOOOOOOOOOOO\nOOZ$I7$I$I7$I8ZO8Z$7Z8Z8OOOOOOOOOOOOOOOO\nOOZ8ZOOZ8ZZ8Z8ZZ8Z8OZ8ZOOOOOOOOOOOOOOOOO\nOOZ8ZOOZ8ZZ8Z8ZZ8Z8OZ8OOOOOOOOOOOOOOOOOO\n\nYou probably are here because you want to know how we made the site:\n\n- Generator: Jekyll (http://jekyllrb.com/)\n- Template: Thinny (https://github.com/camporez/Thinny)\n- Our files and mods (http://git.io/j8Z6)");
var width = $(window).width()
if ( width > 899 )
$( function(){
  $.stellar({
    responsive: true,
  verticalScrolling: true,
  horizontalOffset: 0,
  verticalOffset: 0,
  positionProperty: 'transform',
  hideDistantElements: false
  });
})
{% for author_entry in site.data.authors %}{% assign author = author_entry[1] %}
$('.{{ author.id }}').hovercard({
  detailsHTML: "
{{ author.name }} is the {{ author.role }} at {{ site.title }}. {% if author.github %}
 Github profile: {{ author.github }}{% endif %}"
})
{% endfor %}
$('.mms').hovercard({
  detailsHTML: "
 The official blog profile for {{ site.title }}."
})
<commit_msg>Update app.js<commit_after>---
  #CAREFUL
---
console.log("ZZOOOOOOO88O888888888888OZ8ZZO$O77$I$II$\nZZZZOOOOOOO8OO888888888O8Z8ZZO$O77$I$II$\nZZZOOOOOOOO88O88O88888Z8OZ8ZZO$Z77$I$II$\nZO........88888OO88888ZOOZ8$ZZ7Z77$7Z77Z\nOOOZO?. . .OO8888888Z8ZOOZ8$.........77Z\nOOOOOO......O888888OZ8ZOOZOI.Z7Z..$7Z77Z\nOOOOOO.    .8O888Z8OZ8ZOOZO.ZZ7Z.7Z7Z7$O\nOOOOOO..8. ..O8O8Z8OZ8ZOO$.+..7Z.7Z7Z77Z\nO8OOOO. OO....8Z8Z8OZ8ZOO.....$O.7Z7O$$Z\nOOOOOO..88.....:8Z8ZZ8ZOO...+.$O.$Z$$$ZZ\nOOOOOO..8OO..8Z.8Z8OZ8ZO.Z.Z+.$O.$OZZZZZ\nOOOOOO. 8888.8ZZ.Z8ZZ8Z.,.8Z?.$O.$ZZZZZZ\nOOOOOO..8OO8~.ZZ..8ZZ8....8Z?.Z8.ZZZZZZZ\nOOOOO8. OOZ8Z..Z8 IOZ8.?.Z8Z?.Z8ZZZZZZZZ\nOOOOOO..=.Z8Z8.Z8Z.OZ.Z.OZ8Z?.ZOOOOOOZZZ\nOOOOOO.. .Z8Z8O.8Z$....ZOZ8Z?.OOOOOOOOOO\nOOO888O. .OOZ8Z. Z8....8OZ8ZIOOOOOOOOOOO\nO8OOOOO...OOZ8ZO..8O$.Z8OZ8ZOOOOOOOOOOOO\nOOOOZO7.,.OOZ8ZO8.8O.8Z8OZOOOOOOOOOOOOOO\nOO8....Z8 ...8Z88Z..?8Z8OOOOOOOOOOOOOOOO\nOOZ$I7$I$I7$I8ZO8Z$7Z8Z8OOOOOOOOOOOOOOOO\nOOZ8ZOOZ8ZZ8Z8ZZ8Z8OZ8ZOOOOOOOOOOOOOOOOO\nOOZ8ZOOZ8ZZ8Z8ZZ8Z8OZ8OOOOOOOOOOOOOOOOOO\n\nYou probably are here because you want to know how we made the site:\n\n- Generator: Jekyll (http://jekyllrb.com/)\n- Template: Thinny (https://github.com/camporez/Thinny)\n- Our files and mods (http://git.io/j8Z6)");var width=$(window).width();width>899&&$(function(){$.stellar({responsive:!0,verticalScrolling:!0,horizontalOffset:0,verticalOffset:0,positionProperty:"transform",hideDistantElements:!1})}),{% for author_entry in site.data.authors %}{% assign author = author_entry[1] %}$(".{{ author.id }}").hovercard({detailsHTML:'
{{ author.name }} is the {{ author.role }} at {{ site.title }}. {% if author.github %}
 Github profile: {{ author.github }}{% endif %}'}),{% endfor %}$(".mms").hovercard({detailsHTML:'
 The official blog profile for {{ site.title }}.'});
<|endoftext|>


<commit_before>var _ = {};

_.now = Date.now || function() {
  return new Date().getTime();
};

_.throttle = function(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  if (!options) options = {};
  var later = function() {
    previous = options.leading === false ? 0 : _.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };
  return function() {
    var now = _.now();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };
};

var nav = $('nav.global');
$(window).scroll(_.throttle(function(){
  nav.toggleClass('full', $(window).scrollTop() > 0);
}, 100));

$('.menu-btn').click(function(evt){
  $(this).toggleClass('activated');
  $('.full-only').toggleClass('active');
  evt.stopPropagation();
});

$('.show-menu').click(function (evt) {
  nav.addClass('full');
  $('.menu-btn').addClass('activated');
  $('.full-only').addClass('active');
  evt.stopPropagation();
});

$('body').click(function(){
  $('.menu-btn').removeClass('activated');
  $('.full-only').removeClass('active');
});

var videoBanner = $('.hero[data-video]');
videoBanner.each(function () {
  // Check connection speed and widow width
  if ('connection' in window.navigator &&
      window.navigator.connection.type === 'cellular' ||
      $(window).width() < 800)
  {
    return;
  }

  // Feature detect for HTML5 video with h.264 support
  var video = document.createElement('video');
  if (!('canPlayType' in video) || video.canPlayType('video/mp4') === '') {
    return;
  }

  video.src = videoBanner.data('video');
  video.controls = false;
  video.loop = true;

  video.addEventListener('loadeddata', function() {
    // If video has enough data
    if (video.readyState > 2) {
      videoBanner.find('.video-overlay')
        .fadeTo(400, 1, function(){
          videoBanner.append(video);
          video.play();
        })
        .fadeTo(400, .5);
    }
  });
});

function padLeft(s, l, c) {
  s = s.toString();
  return Array(l - s.length + 1).join(c || "0") + s;
}

var signupDate = Date.UTC(2016, 4, 9, -8);

if (signupDate > Date.now()) {
  $('.signup').addClass('disabled');
  setInterval(function () {
    var diff = (signupDate - Date.now()) / 1000,
      s = Math.floor(diff % 60),
      m = Math.floor(diff / 60) % 60,
      h = Math.floor(diff / 3600),
      timeString = [padLeft(h, 2), padLeft(m, 2), padLeft(s, 2)].join(':');

    $('.signup').text('Sign Up Open In ' + timeString);
  }, 1000);
}<commit_msg>Countdown starts immediately<commit_after>var _ = {};

_.now = Date.now || function() {
  return new Date().getTime();
};

_.throttle = function(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  if (!options) options = {};
  var later = function() {
    previous = options.leading === false ? 0 : _.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };
  return function() {
    var now = _.now();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };
};

var nav = $('nav.global');
$(window).scroll(_.throttle(function(){
  nav.toggleClass('full', $(window).scrollTop() > 0);
}, 100));

$('.menu-btn').click(function(evt){
  $(this).toggleClass('activated');
  $('.full-only').toggleClass('active');
  evt.stopPropagation();
});

$('.show-menu').click(function (evt) {
  nav.addClass('full');
  $('.menu-btn').addClass('activated');
  $('.full-only').addClass('active');
  evt.stopPropagation();
});

$('body').click(function(){
  $('.menu-btn').removeClass('activated');
  $('.full-only').removeClass('active');
});

var videoBanner = $('.hero[data-video]');
videoBanner.each(function () {
  // Check connection speed and widow width
  if ('connection' in window.navigator &&
      window.navigator.connection.type === 'cellular' ||
      $(window).width() < 800)
  {
    return;
  }

  // Feature detect for HTML5 video with h.264 support
  var video = document.createElement('video');
  if (!('canPlayType' in video) || video.canPlayType('video/mp4') === '') {
    return;
  }

  video.src = videoBanner.data('video');
  video.controls = false;
  video.loop = true;

  video.addEventListener('loadeddata', function() {
    // If video has enough data
    if (video.readyState > 2) {
      videoBanner.find('.video-overlay')
        .fadeTo(400, 1, function(){
          videoBanner.append(video);
          video.play();
        })
        .fadeTo(400, .5);
    }
  });
});

function padLeft(s, l, c) {
  s = s.toString();
  return Array(l - s.length + 1).join(c || "0") + s;
}

var signupDate = Date.UTC(2016, 4, 9, -8);

if (signupDate > Date.now()) {
  $('.signup').addClass('disabled');

  var updateTime = function () {
    var diff = (signupDate - Date.now()) / 1000,
      s = Math.floor(diff % 60),
      m = Math.floor(diff / 60) % 60,
      h = Math.floor(diff / 3600),
      timeString = [padLeft(h, 2), padLeft(m, 2), padLeft(s, 2)].join(':');

    $('.signup').text('Sign Up Open In ' + timeString);
  };

  setInterval(updateTime, 1000);
  updateTime();
}<|endoftext|>


<commit_before>/**
 * Default model configuration
 * (sails.config.models)
 *
 * Unless you override them, the following properties will be included
 * in each of your models.
 *
 * For more info on Sails models, see:
 * http://sailsjs.org/#!/documentation/concepts/ORM
 */

module.exports.models = {

  /***************************************************************************
  *                                                                          *
  * Your app's default connection. i.e. the name of one of your app's        *
  * connections (see `config/connections.js`)                                *
  *                                                                          *
  ***************************************************************************/
  connection: 'mysql',

  /***************************************************************************
  *                                                                          *
  * How and whether Sails will attempt to automatically rebuild the          *
  * tables/collections/etc. in your schema.                                  *
  *                                                                          *
  * See http://sailsjs.org/#!/documentation/concepts/ORM/model-settings.html  *
  *                                                                          *
  ***************************************************************************/
  migrate: 'safe',

  beforeDestroy: function(model, cb) {
    model.updatedAt = MysqlTimestamps.currentTimestamp();
    model.save();
  }
};
<commit_msg>Updates to base user model<commit_after>/**
 * Default model configuration
 * (sails.config.models)
 *
 * Unless you override them, the following properties will be included
 * in each of your models.
 *
 * For more info on Sails models, see:
 * http://sailsjs.org/#!/documentation/concepts/ORM
 */

module.exports.models = {

  /***************************************************************************
  *                                                                          *
  * Your app's default connection. i.e. the name of one of your app's        *
  * connections (see `config/connections.js`)                                *
  *                                                                          *
  ***************************************************************************/
  connection: 'mysql',

  /***************************************************************************
  *                                                                          *
  * How and whether Sails will attempt to automatically rebuild the          *
  * tables/collections/etc. in your schema.                                  *
  *                                                                          *
  * See http://sailsjs.org/#!/documentation/concepts/ORM/model-settings.html  *
  *                                                                          *
  ***************************************************************************/
  migrate: 'safe',

  beforeUpdate: function(model, cb) {
    if(model.autoUpdatedAt) {
      model.updatedBy = req.user.id;
    }
    cb();
  },

  beforeDestroy: function(model, cb) {
    if(model.autoUpdatedAt) {
      model.updatedAt = MysqlTimestamps.currentTimestamp();
      model.save();
    } else {
      cb();
    }
  }
};
<|endoftext|>