<commit_before>var document   = window.document
  , _tire      = window.tire
  , _$         = window.$
  , idExp      = /^#[\w\-]+$/
  , classExp   = /^\.[\w\-]+$/
  , tagNameExp = /^[\w\-]+$/
  , tagExp     = /<([\w:]+)/
  , slice      = [].slice;

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

// If slice is not available we provide a backup
try {
  slice.call(document.documentElement.childNodes, 0)[0].nodeType;
} catch(e) {
  slice = function (i) {
    i = i || 0;
    var elem, results = [];
    for (; (elem = this[i]); i++) {
      results.push(elem);
    }
    return results;
  };
}

var tire = function (selector, context) {
  return new tire.fn.find(selector, context);
};

tire.fn = tire.prototype = {

  /**
   * Default length is zero
   */

  length: 0,

  /**
   * Extend `tire.fn`
   *
   * @param {Object} o
   */

  extend: function (o) {
    for (var k in o) {
      this[k] = o[k];
    }
  },

  /**
   * Find elements by selector
   *
   * @param {String|Object|Function|Array} selector
   * @param {Object} context
   *
   * @return {Object}
   */

  find: function (selector, context) {
    var elms = [], attrs;

    if (!selector) {
      return this;
    }

    if (tire.isFunction(selector)) {
      return tire.ready(selector);
    }

    if (selector.nodeType) {
      this.selector = '';
      this.context = selector;
      return this.set([selector]);
    }

    if (selector.length === 1 && selector[0].nodeType) {
      this.selector = selector.selector;
      this.context = selector[0];
      return this.set(selector);
    }

    context = this.context ? this.context : (context || document);

    if (tire.isPlainObject(context)) {
      attrs = context;
      context = document;
    }

    if (tire.isString(selector)) {
      this.selector = selector;
      if (idExp.test(selector) && context.nodeType === context.DOCUMENT_NODE) {
        elms = (elms = context.getElementById(selector.substr(1))) ? [elms] : [];
      } else if (context.nodeType !== 1 && context.nodeType !== 9) {
        elms = [];
      } else if (tagExp.test(selector)) {
        var tmp = context.createElement('div');
        tmp.innerHTML = selector;
        this.each.call(slice.call(tmp.childNodes, 0), function () {
          elms.push(this);
        });
      } else {
        elms = slice.call(
          classExp.test(selector) && context.getElementsByClassName !== undefined ? context.getElementsByClassName(selector.substr(1)) :
          tagNameExp.test(selector) ? context.getElementsByTagName(selector) :
          context.querySelectorAll(selector)
        );
      }
    } else if (selector.nodeName || selector === window) {
      elms = [selector];
    } else if (tire.isArray(selector)) {
      elms = selector;
    }

    if (selector.selector !== undefined) {
      this.selector = selector.selector;
      this.context = selector.context;
    } else if (this.context === undefined) {
      if (elms[0] !== undefined && !tire.isString(elms[0])) {
        this.context = elms[0];
      } else {
        this.context = document;
      }
    }

    return this.set(elms).each(function () {
      return attrs && $(this).attr(attrs);
    });
  },

  /**
   * Fetch property from elements
   *
   * @param {String} prop
   * @return {Array}
   */

  pluck: function (prop) {
    var result = [];
    this.each(function () {
      if (this[prop]) result.push(this[prop]);
    });
    return result;
  },

  /**
   * Run callback for each element in the collection
   *
   * @param {Function} callback
   * @return {Object}
   */

  each: function(target, callback) {
    var i, key;

    if (typeof target === 'function') {
      callback = target;
      target = this;
    }

    if (target === this || target instanceof Array) {
      for (i = 0; i < target.length; ++i) {
        if (callback.call(target[i], i, target[i]) === false) break;
      }
    } else {
      for (key in target) {
        if (target.hasOwnProperty(key) && callback.call(target[key], key, target[key]) === false) break;
      }
    }

    return target;
  },

  /**
   * Set elements to tire object before returning `this`
   *
   * @param {Array} elements
   * @return {Object}
   */

  set: function (elements) {
    var i = 0;
    for (; i < elements.length; i++) {
      this[i] = elements[i];
    }
    this.length = i;
    return this;
  }
};

/**
 * Extend `tire` with arguments, if the arguments length is one the extend target is `tire`
 */

tire.extend = function () {
  var target = arguments[0] || {};

  if (typeof target !== 'object' && typeof target !== 'function') {
    target = {};
  }

  if (arguments.length === 1) target = this;

  tire.fn.each(slice.call(arguments), function (index, value) {
    for (var key in value) {
      if (target[key] !== value[key]) target[key] = value[key];
    }
  });

  return target;
};

tire.fn.find.prototype = tire.fn;

tire.extend({

  // We sould be able to use slice outside
  slice: slice,

  // We sould be able to use each outside
  each: tire.fn.each,

  /**
   * Trim string
   *
   * @param {String} str
   * @return {String}
   */

  trim: function (str) {
    return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
  },

  /**
   * Check if the element matches the selector
   *
   * @param {Object} element
   * @param {String} selector
   * @return {Boolean}
   */

  matches: function (element, selector) {
    if (!element || element.nodeType !== 1) return false;

    // Trying to use matchesSelector if it is available
    var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.matchesSelector;
    if (matchesSelector) {
      return matchesSelector.call(element, selector);
    }

    // querySelectorAll fallback
    if (document.querySelectorAll !== undefined) {
      var nodes = element.parentNode.querySelectorAll(selector);

      for (var i = 0; i < nodes.length; i++) {
        if (nodes[i] === element) return true;
      }
    }

    return false;
  },

  /**
   * Check if the `obj` is a function
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isFunction: function (obj) {
    return typeof obj === 'function';
  },

  /**
   * Check if the `obj` is a array
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isArray: function (obj) {
    return obj instanceof Array;
  },

  /**
   * Check if the `obj` is a string
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isString: function (obj) {
    return typeof obj === 'string';
  },

  /**
   * Check if the `obj` is a number
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isNumeric: function (obj) {
    return typeof obj === 'number';
  },

  /**
   * Check if the `obj` is a object
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isObject: function (obj) {
    return obj instanceof Object && !this.isArray(obj) && !this.isFunction(obj) && !this.isWindow(obj);
  },

  /**
   * Check if `obj` is a plain object
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isPlainObject: function (obj) {
    if (!obj || !this.isObject(obj) || this.isWindow(obj) || obj.nodeType) {
      return false;
    } else if (obj.__proto__ === Object.prototype) {
      return true;
    } else {
      var key;
      for (key in obj) {}
      return key === undefined || {}.hasOwnProperty.call(obj, key);
    }
  },

  /**
   * Check if `obj` is a `window` object
   */

  isWindow: function (obj) {
    return obj !== null && obj !== undefined && (obj === obj.window || 'setInterval' in obj);
  },

  /**
   * Parse JSON string to object.
   *
   * @param {String} str
   * @return {Object|null)
   */

  parseJSON: function (str) {
    if (!this.isString(str) || !str) {
      return null;
    }

    str = this.trim(str);

    if (window.JSON && window.JSON.parse) {
      return window.JSON.parse(str);
    }

    // Solution to fix JSON parse support for older browser. Not so nice but it works.
    try { return (new Function('return ' + str))(); }
    catch (e) { return null; }
  },

  /**
   * Calling .noConflict will restore the window.$` to its previous value.
   *
   * @param {Boolean} name Restore `tire` to it's previous value.
   * @return {Object}
   */

  noConflict: function (name) {
    if (name) {
      window.tire = _tire;
    }

    window.$ = _$;
    return tire;
  }
});<commit_msg>Fixed brackets<commit_after>var document   = window.document
  , _tire      = window.tire
  , _$         = window.$
  , idExp      = /^#[\w\-]+$/
  , classExp   = /^\.[\w\-]+$/
  , tagNameExp = /^[\w\-]+$/
  , tagExp     = /<([\w:]+)/
  , slice      = [].slice;

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

// If slice is not available we provide a backup
try {
  slice.call(document.documentElement.childNodes, 0)[0].nodeType;
} catch(e) {
  slice = function (i) {
    i = i || 0;
    var elem, results = [];
    for (; (elem = this[i]); i++) {
      results.push(elem);
    }
    return results;
  };
}

var tire = function (selector, context) {
  return new tire.fn.find(selector, context);
};

tire.fn = tire.prototype = {

  /**
   * Default length is zero
   */

  length: 0,

  /**
   * Extend `tire.fn`
   *
   * @param {Object} o
   */

  extend: function (o) {
    for (var k in o) {
      this[k] = o[k];
    }
  },

  /**
   * Find elements by selector
   *
   * @param {String|Object|Function|Array} selector
   * @param {Object} context
   *
   * @return {Object}
   */

  find: function (selector, context) {
    var elms = [], attrs;

    if (!selector) {
      return this;
    }

    if (tire.isFunction(selector)) {
      return tire.ready(selector);
    }

    if (selector.nodeType) {
      this.selector = '';
      this.context = selector;
      return this.set([selector]);
    }

    if (selector.length === 1 && selector[0].nodeType) {
      this.selector = selector.selector;
      this.context = selector[0];
      return this.set(selector);
    }

    context = this.context ? this.context : (context || document);

    if (tire.isPlainObject(context)) {
      attrs = context;
      context = document;
    }

    if (tire.isString(selector)) {
      this.selector = selector;
      if (idExp.test(selector) && context.nodeType === context.DOCUMENT_NODE) {
        elms = (elms = context.getElementById(selector.substr(1))) ? [elms] : [];
      } else if (context.nodeType !== 1 && context.nodeType !== 9) {
        elms = [];
      } else if (tagExp.test(selector)) {
        var tmp = context.createElement('div');
        tmp.innerHTML = selector;
        this.each.call(slice.call(tmp.childNodes, 0), function () {
          elms.push(this);
        });
      } else {
        elms = slice.call(
          classExp.test(selector) && context.getElementsByClassName !== undefined ? context.getElementsByClassName(selector.substr(1)) :
          tagNameExp.test(selector) ? context.getElementsByTagName(selector) :
          context.querySelectorAll(selector)
        );
      }
    } else if (selector.nodeName || selector === window) {
      elms = [selector];
    } else if (tire.isArray(selector)) {
      elms = selector;
    }

    if (selector.selector !== undefined) {
      this.selector = selector.selector;
      this.context = selector.context;
    } else if (this.context === undefined) {
      if (elms[0] !== undefined && !tire.isString(elms[0])) {
        this.context = elms[0];
      } else {
        this.context = document;
      }
    }

    return this.set(elms).each(function () {
      return attrs && $(this).attr(attrs);
    });
  },

  /**
   * Fetch property from elements
   *
   * @param {String} prop
   * @return {Array}
   */

  pluck: function (prop) {
    var result = [];
    this.each(function () {
      if (this[prop]) result.push(this[prop]);
    });
    return result;
  },

  /**
   * Run callback for each element in the collection
   *
   * @param {Function} callback
   * @return {Object}
   */

  each: function(target, callback) {
    var i, key;

    if (typeof target === 'function') {
      callback = target;
      target = this;
    }

    if (target === this || target instanceof Array) {
      for (i = 0; i < target.length; ++i) {
        if (callback.call(target[i], i, target[i]) === false) break;
      }
    } else {
      for (key in target) {
        if (target.hasOwnProperty(key) && callback.call(target[key], key, target[key]) === false) break;
      }
    }

    return target;
  },

  /**
   * Set elements to tire object before returning `this`
   *
   * @param {Array} elements
   * @return {Object}
   */

  set: function (elements) {
    var i = 0;
    for (; i < elements.length; i++) {
      this[i] = elements[i];
    }
    this.length = i;
    return this;
  }
};

/**
 * Extend `tire` with arguments, if the arguments length is one the extend target is `tire`
 */

tire.extend = function () {
  var target = arguments[0] || {};

  if (typeof target !== 'object' && typeof target !== 'function') {
    target = {};
  }

  if (arguments.length === 1) target = this;

  tire.fn.each(slice.call(arguments), function (index, value) {
    for (var key in value) {
      if (target[key] !== value[key]) target[key] = value[key];
    }
  });

  return target;
};

tire.fn.find.prototype = tire.fn;

tire.extend({

  // We sould be able to use slice outside
  slice: slice,

  // We sould be able to use each outside
  each: tire.fn.each,

  /**
   * Trim string
   *
   * @param {String} str
   * @return {String}
   */

  trim: function (str) {
    return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
  },

  /**
   * Check if the element matches the selector
   *
   * @param {Object} element
   * @param {String} selector
   * @return {Boolean}
   */

  matches: function (element, selector) {
    if (!element || element.nodeType !== 1) return false;

    // Trying to use matchesSelector if it is available
    var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.matchesSelector;
    if (matchesSelector) {
      return matchesSelector.call(element, selector);
    }

    // querySelectorAll fallback
    if (document.querySelectorAll !== undefined) {
      var nodes = element.parentNode.querySelectorAll(selector);

      for (var i = 0; i < nodes.length; i++) {
        if (nodes[i] === element) return true;
      }
    }

    return false;
  },

  /**
   * Check if the `obj` is a function
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isFunction: function (obj) {
    return typeof obj === 'function';
  },

  /**
   * Check if the `obj` is a array
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isArray: function (obj) {
    return obj instanceof Array;
  },

  /**
   * Check if the `obj` is a string
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isString: function (obj) {
    return typeof obj === 'string';
  },

  /**
   * Check if the `obj` is a number
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isNumeric: function (obj) {
    return typeof obj === 'number';
  },

  /**
   * Check if the `obj` is a object
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isObject: function (obj) {
    return obj instanceof Object && !this.isArray(obj) && !this.isFunction(obj) && !this.isWindow(obj);
  },

  /**
   * Check if `obj` is a plain object
   *
   * @param {Object} obj
   * @return {Boolean}
   */

  isPlainObject: function (obj) {
    if (!obj || !this.isObject(obj) || this.isWindow(obj) || obj.nodeType) {
      return false;
    } else if (obj.__proto__ === Object.prototype) {
      return true;
    } else {
      var key;
      for (key in obj) {}
      return key === undefined || {}.hasOwnProperty.call(obj, key);
    }
  },

  /**
   * Check if `obj` is a `window` object
   */

  isWindow: function (obj) {
    return obj !== null && obj !== undefined && (obj === obj.window || 'setInterval' in obj);
  },

  /**
   * Parse JSON string to object.
   *
   * @param {String} str
   * @return {Object|null}
   */

  parseJSON: function (str) {
    if (!this.isString(str) || !str) {
      return null;
    }

    str = this.trim(str);

    if (window.JSON && window.JSON.parse) {
      return window.JSON.parse(str);
    }

    // Solution to fix JSON parse support for older browser. Not so nice but it works.
    try { return (new Function('return ' + str))(); }
    catch (e) { return null; }
  },

  /**
   * Calling .noConflict will restore the window.$` to its previous value.
   *
   * @param {Boolean} name Restore `tire` to it's previous value.
   * @return {Object}
   */

  noConflict: function (name) {
    if (name) {
      window.tire = _tire;
    }

    window.$ = _$;
    return tire;
  }
});<|endoftext|>


<commit_before>import React from "react";
import PropTypes from "prop-types";
import cx from "classnames";

/**
 * A Generic button component.
 */
class Button extends React.PureComponent {
  constructor(props) {
    super(props);
  }

  render() {
    const {
      onClick,
      className,
      children,
      disabled,
      large,
      small,
      primary,
      secondary,
      warning,
      error,
      link,
      outline,
      icon,
      type,
      href,
      style
    } = this.props;

    let mainStyle = "button";
    if (primary) {
      mainStyle = "primary";
    } else if (secondary) {
      mainStyle = "secondary";
    } else if (warning) {
      mainStyle = "warning";
    } else if (error) {
      mainStyle = "error";
    } else if (link) {
      mainStyle = "link";
    } else {
      mainStyle = "default_btn";
    }

    if (outline) {
      mainStyle += "_outline";
    }

    /**
     * Use cx to construct a CSS class object.
     * cx will automatically remove falsy values
     * for us. This way only passed props will be
     * transformed into CSS classes.
     */
    const classes = cx(
      {
        "disabled": disabled,
        "large": large,
        "small": small,
        "button": true
      },
      mainStyle
    );

    let text = children;
    let iconClass = false;

    /* Just use the icon instead of text when an icon
     * is passed and no children(text) is set. */
    if (icon && children === "Default Button") {
      text = null;
    } else if (icon) {
      text = children;
      iconClass = "ra_Button__icon-left";
    }

    return (

        {href
          ?
            <button
              onClick={onClick}
              className={cx(className)}
              styleName={classes}
              style={style}
              type={type}
              href={href}
            >
              {icon ?  : null}
              {text}
            </button>
          : <button
              onClick={onClick}
              className={cx(className)}
              styleName={classes}
              style={style}
              type={type}
              href={href}
            >
              {icon ?  : null}
              {text}
            </button>
        }

    );
  }
}

Button.propTypes = {
  /** HTML5 button type, eg submit, button, etc */
  "type": PropTypes.string,
  /** The URL to link to. */
  "href": PropTypes.string,
  /**
     * Define a mini button.
     *
     */
  "children": PropTypes.node,
  /**
   * Click event handler.
   */
  "onClick": PropTypes.func,
  /** An Object, array, or string of CSS classes to apply to button.*/
  "className": PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.object,
    PropTypes.array
  ]),
  /**
     * define a custom css class name
     * @examples "btn", "btn-active"
     */
  "disabled": PropTypes.bool,
  /**
     * use outline styled button
     * @examples <Button outline>
     */
  "outline": PropTypes.bool,
  /**
     * define button href if anchor
     * @examples '#', 'http://some-website.com/'
     */
  "primary": PropTypes.bool,
  /**
     * use secondary style button
     * @examples <Button secondary>
     */
  "secondary": PropTypes.bool,
  /**
     * use warning style button
     * @examples <Button warning>
     */
  "warning": PropTypes.bool,
  /**
     * use error style button
     * @examples <Button error>
     */
  "error": PropTypes.bool,
  /**
     * use link style button
     * @examples <Button link>
     */
  "link": PropTypes.bool,
  /**
     * use large style button
     * @examples <Button large>
     */
  "large": PropTypes.bool,
  /**
     * use small style button
     * @examples <Button small>
     */
  "small": PropTypes.bool,

  /**
    * The class name of the icon you want to set.
    */
  "icon": PropTypes.string,

  /**
    * Pass inline styles here.
    */
  "style": PropTypes.object
};

Button.defaultProps = {
  "children": "Default Button",
  "outline": false,
  "primary": false,
  "secondary": false,
  "warning": false,
  "error": false,
  "link": false,
  "large": false,
  "small": false,
  "disabled": false,
  "type": "button"
};

export default Button;
<commit_msg>created button variable outside render return<commit_after>import React from "react";
import PropTypes from "prop-types";
import cx from "classnames";

/**
 * A Generic button component.
 */
class Button extends React.PureComponent {
  constructor(props) {
    super(props);
  }

  render() {
    const {
      onClick,
      className,
      children,
      disabled,
      large,
      small,
      primary,
      secondary,
      warning,
      error,
      link,
      outline,
      icon,
      type,
      href,
      style
    } = this.props;

    let mainStyle = "button";
    if (primary) {
      mainStyle = "primary";
    } else if (secondary) {
      mainStyle = "secondary";
    } else if (warning) {
      mainStyle = "warning";
    } else if (error) {
      mainStyle = "error";
    } else if (link) {
      mainStyle = "link";
    } else {
      mainStyle = "default_btn";
    }

    if (outline) {
      mainStyle += "_outline";
    }

    /**
     * Use cx to construct a CSS class object.
     * cx will automatically remove falsy values
     * for us. This way only passed props will be
     * transformed into CSS classes.
     */
    const classes = cx(
      {
        "disabled": disabled,
        "large": large,
        "small": small,
        "button": true
      },
      mainStyle
    );

    let text = children;
    let iconClass = false;

    /* Just use the icon instead of text when an icon
     * is passed and no children(text) is set. */
    if (icon && children === "Default Button") {
      text = null;
    } else if (icon) {
      text = children;
      iconClass = "ra_Button__icon-left";
    }

    let renderButton =  href
      ?
          <button onClick={onClick}
                className={cx(className)}
                styleName={classes}
                style={style}
                type={type}
                href={href}>
                  {icon ?  : null}
                  {text}
          </button>

      : <button onClick={onClick}
              className={cx(className)}
              styleName={classes}
              style={style}
              type={type}
              href={href}>
                {icon ?  : null}
                {text}
        </button>;

    return (

        {renderButton}

    );
  }
}

Button.propTypes = {
  /** HTML5 button type, eg submit, button, etc */
  "type": PropTypes.string,
  /** The URL to link to. */
  "href": PropTypes.string,
  /**
     * Define a mini button.
     *
     */
  "children": PropTypes.node,
  /**
   * Click event handler.
   */
  "onClick": PropTypes.func,
  /** An Object, array, or string of CSS classes to apply to button.*/
  "className": PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.object,
    PropTypes.array
  ]),
  /**
     * define a custom css class name
     * @examples "btn", "btn-active"
     */
  "disabled": PropTypes.bool,
  /**
     * use outline styled button
     * @examples <Button outline>
     */
  "outline": PropTypes.bool,
  /**
     * define button href if anchor
     * @examples '#', 'http://some-website.com/'
     */
  "primary": PropTypes.bool,
  /**
     * use secondary style button
     * @examples <Button secondary>
     */
  "secondary": PropTypes.bool,
  /**
     * use warning style button
     * @examples <Button warning>
     */
  "warning": PropTypes.bool,
  /**
     * use error style button
     * @examples <Button error>
     */
  "error": PropTypes.bool,
  /**
     * use link style button
     * @examples <Button link>
     */
  "link": PropTypes.bool,
  /**
     * use large style button
     * @examples <Button large>
     */
  "large": PropTypes.bool,
  /**
     * use small style button
     * @examples <Button small>
     */
  "small": PropTypes.bool,

  /**
    * The class name of the icon you want to set.
    */
  "icon": PropTypes.string,

  /**
    * Pass inline styles here.
    */
  "style": PropTypes.object
};

Button.defaultProps = {
  "children": "Default Button",
  "outline": false,
  "primary": false,
  "secondary": false,
  "warning": false,
  "error": false,
  "link": false,
  "large": false,
  "small": false,
  "disabled": false,
  "type": "button"
};

export default Button;
<|endoftext|>


<commit_before>var timer = (function() {
  'use strict';

  var intervalIndex = 0;
  var timerInterval = config.workInterval;

  var intervals = [];
  var timer;

  var init = function () {
    // initialize intervals array
    for (var i = 0; i < config.repeat; i++) {
      intervals.push(config.workInterval);
      if (i < config.repeat - 1) {
        intervals.push(config.breakInterval);
      }
    }
    intervals.push(config.longbreakInterval);

    // load save progress
    intervalIndex = services.storage.get('intervalIndex') || intervalIndex;
    timerInterval = services.storage.get('timerInterval') || timerInterval;

    for (var index = 0; index <= intervalIndex; index++) {
      updateTimerViews(index, true);
    }

    if (intervalIndex === 0 && timerInterval < config.workInterval) {
      views.progress.setImageType('work', 0);
      views.progress.setDescription('work');
    }

    if (intervalIndex === 0 && timerInterval === config.workInterval) {
      services.title.resetTitle();
    } else {
      services.title.setTitle(secondsToTime(timerInterval));
    }

  };

  var secondsToTime = function(seconds) {
    var addLeadingZero = function(number) {
      if (number < 10) {
        number = '0' + number;
      }

      return number;
    };

    var minutes = Math.floor(seconds / 60);
    seconds = seconds % 60;

    return addLeadingZero(minutes) + ':' + addLeadingZero(seconds);
  };

  var timerTick = function () {
    timerInterval--;

    if (timerInterval <= 0) {
      nextInterval();
    }

    var time = secondsToTime(timerInterval);

    views.timer.setTime(time);

    services.title.setTitle(time, timer);
    services.storage.set('timerInterval', timerInterval);
  };

  var nextInterval = function(skipped) {
    skipped = skipped || false;

    intervalIndex++;
    if (intervalIndex > intervals.length - 1) {
      intervalIndex = 0;
      resetTimer();
    }

    timerInterval = intervals[intervalIndex];

    updateTimerViews(intervalIndex, skipped);

    services.storage.set('intervalIndex', intervalIndex);

    if (skipped) {
      if (timer) {
        // resets timeout countdown
        pauseTimer();
        runTimer();
      }

      services.title.setTitle(secondsToTime(timerInterval), timer);
      services.storage.set('intervalIndex', intervalIndex);
      services.storage.set('timerInterval', timerInterval);
    }
  };

  var updateTimerViews = function(index, skipped) {
    var imageIndex = Math.floor(index / 2);

    views.timer.setTime(secondsToTime(timerInterval));

    // invervals[ work, break, work, break, ... , long break ]
    if (index === intervals.length - 1) {
      // last interval

      services.favicon.setFavicon('longbreak');
      if (!skipped) {
        services.notification.newNotification(config.longbreakInterval / 60 +
          ' minute long break', 'longbreak');
          services.audio.play();
      }

      views.progress.setDescription('long break');
      views.progress.setImageType('longbreak', imageIndex);

    } else if (index === 0) {
      // first interval: 0

      services.favicon.setFavicon('work');
      if (!skipped) {
        // TODO: think of better notification text
        services.notification.newNotification('Done', 'work');
        services.audio.play();
      }

    } else if (index % 2 === 0) {
      // even interval: 2, 4, 6

      services.favicon.setFavicon('work');
      if (!skipped) {
        services.notification.newNotification(config.workInterval / 60 +
          ' minute work', 'work');
        services.audio.play();
      }

      views.progress.setDescription('work');
      views.progress.setImageType('work', imageIndex);
      views.progress.setImageType('finished', imageIndex - 1);

    } else if (index % 2 === 1) {
      // odd interval: 1, 3, 6..

      services.favicon.setFavicon('break');
      if (!skipped) {
        services.notification.newNotification(config.breakInterval / 60 +
          ' minute break', 'break');
        services.audio.play();
      }

      views.progress.setDescription('break');
      views.progress.setImageType('break', imageIndex);

    }

  };

  var skipInterval = function () {
    nextInterval(true);

    console.log('timerInterval', timerInterval);
    console.log('intervalIndex', intervalIndex);

  };

  var startTimer = function() {
    if (!timer) {
      runTimer();
    } else {
      pauseTimer();
    }

    services.title.setTitle(secondsToTime(timerInterval), timer);
    views.controls.toogleStartButtonCaption();

    if (intervalIndex === 0) {
      views.progress.setImageType('work', 0);
      views.progress.setDescription('work');
    }
  };

  var runTimer = function () {
    timer = setInterval(timerTick, 1000);
  };

  var pauseTimer = function() {
    timer = clearInterval(timer);
  };

  var resetTimer = function() {
    pauseTimer();

    intervalIndex = 0;
    timerInterval = config.workInterval;

    var time = secondsToTime(timerInterval);

    views.timer.setTime(time);
    views.controls.resetStartButton();

    services.title.resetTitle();
    services.favicon.setFavicon('work');
    services.storage.set('intervalIndex', intervalIndex);
    services.storage.set('timerInterval', timerInterval);

    views.progress.resetProgress();
  };

  return {
    init: init,
    startTimer: startTimer,
    pauseTimer: pauseTimer,
    skipInterval: skipInterval,
    resetTimer: resetTimer
  };

}());
<commit_msg>timer: removed console.log<commit_after>var timer = (function() {
  'use strict';

  var intervalIndex = 0;
  var timerInterval = config.workInterval;

  var intervals = [];
  var timer;

  var init = function () {
    // initialize intervals array
    for (var i = 0; i < config.repeat; i++) {
      intervals.push(config.workInterval);
      if (i < config.repeat - 1) {
        intervals.push(config.breakInterval);
      }
    }
    intervals.push(config.longbreakInterval);

    // load save progress
    intervalIndex = services.storage.get('intervalIndex') || intervalIndex;
    timerInterval = services.storage.get('timerInterval') || timerInterval;

    for (var index = 0; index <= intervalIndex; index++) {
      updateTimerViews(index, true);
    }

    if (intervalIndex === 0 && timerInterval < config.workInterval) {
      views.progress.setImageType('work', 0);
      views.progress.setDescription('work');
    }

    if (intervalIndex === 0 && timerInterval === config.workInterval) {
      services.title.resetTitle();
    } else {
      services.title.setTitle(secondsToTime(timerInterval));
    }

  };

  var secondsToTime = function(seconds) {
    var addLeadingZero = function(number) {
      if (number < 10) {
        number = '0' + number;
      }

      return number;
    };

    var minutes = Math.floor(seconds / 60);
    seconds = seconds % 60;

    return addLeadingZero(minutes) + ':' + addLeadingZero(seconds);
  };

  var timerTick = function () {
    timerInterval--;

    if (timerInterval <= 0) {
      nextInterval();
    }

    var time = secondsToTime(timerInterval);

    views.timer.setTime(time);

    services.title.setTitle(time, timer);
    services.storage.set('timerInterval', timerInterval);
  };

  var nextInterval = function(skipped) {
    skipped = skipped || false;

    intervalIndex++;
    if (intervalIndex > intervals.length - 1) {
      intervalIndex = 0;
      resetTimer();
    }

    timerInterval = intervals[intervalIndex];

    updateTimerViews(intervalIndex, skipped);

    services.storage.set('intervalIndex', intervalIndex);

    if (skipped) {
      if (timer) {
        // resets timeout countdown
        pauseTimer();
        runTimer();
      }

      services.title.setTitle(secondsToTime(timerInterval), timer);
      services.storage.set('intervalIndex', intervalIndex);
      services.storage.set('timerInterval', timerInterval);
    }
  };

  var updateTimerViews = function(index, skipped) {
    var imageIndex = Math.floor(index / 2);

    views.timer.setTime(secondsToTime(timerInterval));

    // invervals[ work, break, work, break, ... , long break ]
    if (index === intervals.length - 1) {
      // last interval

      services.favicon.setFavicon('longbreak');
      if (!skipped) {
        services.notification.newNotification(config.longbreakInterval / 60 +
          ' minute long break', 'longbreak');
          services.audio.play();
      }

      views.progress.setDescription('long break');
      views.progress.setImageType('longbreak', imageIndex);

    } else if (index === 0) {
      // first interval: 0

      services.favicon.setFavicon('work');
      if (!skipped) {
        // TODO: think of better notification text
        services.notification.newNotification('Done', 'work');
        services.audio.play();
      }

    } else if (index % 2 === 0) {
      // even interval: 2, 4, 6

      services.favicon.setFavicon('work');
      if (!skipped) {
        services.notification.newNotification(config.workInterval / 60 +
          ' minute work', 'work');
        services.audio.play();
      }

      views.progress.setDescription('work');
      views.progress.setImageType('work', imageIndex);
      views.progress.setImageType('finished', imageIndex - 1);

    } else if (index % 2 === 1) {
      // odd interval: 1, 3, 6..

      services.favicon.setFavicon('break');
      if (!skipped) {
        services.notification.newNotification(config.breakInterval / 60 +
          ' minute break', 'break');
        services.audio.play();
      }

      views.progress.setDescription('break');
      views.progress.setImageType('break', imageIndex);

    }

  };

  var skipInterval = function () {
    nextInterval(true);
  };

  var startTimer = function() {
    if (!timer) {
      runTimer();
    } else {
      pauseTimer();
    }

    services.title.setTitle(secondsToTime(timerInterval), timer);
    views.controls.toogleStartButtonCaption();

    if (intervalIndex === 0) {
      views.progress.setImageType('work', 0);
      views.progress.setDescription('work');
    }
  };

  var runTimer = function () {
    timer = setInterval(timerTick, 1000);
  };

  var pauseTimer = function() {
    timer = clearInterval(timer);
  };

  var resetTimer = function() {
    pauseTimer();

    intervalIndex = 0;
    timerInterval = config.workInterval;

    var time = secondsToTime(timerInterval);

    views.timer.setTime(time);
    views.controls.resetStartButton();

    services.title.resetTitle();
    services.favicon.setFavicon('work');
    services.storage.set('intervalIndex', intervalIndex);
    services.storage.set('timerInterval', timerInterval);

    views.progress.resetProgress();
  };

  return {
    init: init,
    startTimer: startTimer,
    pauseTimer: pauseTimer,
    skipInterval: skipInterval,
    resetTimer: resetTimer
  };

}());
<|endoftext|>


<commit_before>define(function(require) {
	var registerSuite = require('intern!object'),
		assert = require('intern/chai!assert'),
		el;

	require('js/tests/support/exports.js');

	registerSuite({
		name: 'Events',

		beforeEach: function() {
			el = document.createElement('div');

			el.id = 'wee';
			el.className = 'js-wee';

			document.body.appendChild(el);
		},

		afterEach: function() {
			el.parentNode.removeChild(el);
		},

		on: {
			simple: function() {
				Wee.events.on(el, 'click', function() {
					Wee.$addClass(el, 'test');
				});

				Wee.events.trigger(el, 'click');

				assert.ok(Wee.$hasClass(el, 'test'),
					'Event was not bound successfully'
				);
			},

			once: function() {
				Wee.events.on(el, 'click', function() {
					Wee.$append(el, '

');
				}, {
					once: true
				});

				Wee.events.trigger(el, 'click');
				Wee.events.trigger(el, 'click');

				assert.strictEqual(Wee.$children(el).length, 1,
					'Event was triggered more than once'
				);
			},

			delegate: function() {
				// TODO: Complete
				assert.isTrue(true);
			},

			'multiple events': function() {
				Wee.events.on(el, {
					click: function() {
						Wee.$addClass(el, 'test');
					},
					blur: function() {
						Wee.$removeClass(el, 'test');
						Wee.$addClass(el, 'test-2');
					}
				});

				Wee.events.trigger(el, 'click');
				Wee.events.trigger(el, 'blur');

				assert.ok(Wee.$hasClass(el, 'test-2'),
					'Multple events were not triggered successfully'
				);
			},

			'multiple selections': function() {
				Wee.$append(el, '
inner
');

				Wee.events.on({
					'#wee': {
						click: function() {
							Wee.$addClass(this, 'test');
						}
					},
					'#test': {
						click: function() {
							Wee.$addClass(this, 'test-inner');
						}
					}
				});

				Wee.events.trigger(el, 'click');
				Wee.events.trigger('#test', 'click');

				assert.ok(Wee.$hasClass(el, 'test'),
					'Multiple selections not selected successfully'
				);

				assert.ok(Wee.$hasClass('#test', 'test-inner'),
					'Multiple selections not selected successfully'
				);
			}
		},

		off: {
			target: function() {
				var $el = Wee.$('#wee');

				Wee.events.on({
					'#wee': {
						click: function() {
							Wee.$addClass($el, 'test-class');
						},
						blur: function() {
							Wee.$addClass('#wee-inner', 'test-class-2');
						}
					}
				});

				Wee.events.off($el);

				Wee.events.trigger($el, 'click');
				Wee.events.trigger($el, 'blur');

				assert.notOk(Wee.$hasClass($el, 'test-class'),
					'Event was not removed successfully'
				);
				assert.notOk(Wee.$hasClass($el, 'test-class-2'),
					'Event was not removed successfully'
				);
			},

			'selection event': function() {
				var $el = Wee.$('#wee');

				Wee.events.on({
					'#wee': {
						click: function() {
							Wee.$addClass($el, 'test-class');
						},
						blur: function() {
							Wee.$addClass($el, 'test-class-2');
						}
					}
				});

				Wee.events.off($el, 'blur');

				Wee.events.trigger($el, 'click');
				Wee.events.trigger($el, 'blur');

				assert.ok(Wee.$hasClass($el, 'test-class'),
					'Event was not removed successfully'
				);
				assert.notOk(Wee.$hasClass($el, 'test-class-2'),
					'Event was not removed successfully'
				);
			},

			'selection event callback': function() {
				var $el = Wee.$('#wee');

				var callbackFunction = function() {
					Wee.$removeClass($el, 'test-class');
				};

				Wee.events.on($el, 'click', function() {
					Wee.$addClass($el, 'test-class');
				});

				Wee.events.trigger($el, 'click');

				Wee.events.off($el, 'click', callbackFunction());

				assert.notOk(Wee.$hasClass($el, 'test-class-2'),
					'Callback function was not executed successfully'
				);
			},

			'multiple selections': function() {
				var $el = Wee.$('#wee');

				Wee.$append($el, '

');

				var callbackFunctionOne = function() {
						Wee.$removeClass($el, 'test-class');
					},
					callbackFunctionTwo = function() {
						Wee.$removeClass('#wee-inner', 'test-class-2');
					};

				Wee.events.on($el, 'click', function() {
					Wee.$addClass($el, 'test-class');
				});

				Wee.events.on('#wee-inner', 'blur', function() {
					Wee.$addClass('#wee-inner', 'test-class-2');
				}, {
					delegate: $el
				});

				Wee.events.trigger($el, 'click');
				Wee.events.trigger('#wee-inner', 'blur');

				Wee.events.off({
				    '#wee': {
				        click: callbackFunctionOne()
				    },
				    '#wee-inner': {
				        blur: callbackFunctionTwo()
				    }
				});

				assert.notOk(Wee.$hasClass($el, 'test-class'),
					'Multiple selections were not called back successfully'
				);
				assert.notOk(Wee.$hasClass('#wee-inner', 'test-class-2'),
					'Multiple selections were not called back successfully'
				);
			}
		},

		bound: function() {
			var $el = Wee.$('#wee');

			Wee.events.on($el, 'click', function() {
				Wee.$addClass($el, 'test-class');
			});

			assert.isArray(Wee.events.bound());
		},

		trigger: function() {
			var $el = Wee.$('#wee');

			Wee.events.on($el, 'click', function() {
				Wee.$addClass($el, 'test-class');
			});

			Wee.events.trigger($el, 'click');

			assert.ok(Wee.$hasClass($el, 'test-class'),
				'Event was not triggered successfully'
			);
		}
	});
});<commit_msg>Add tests for .bound method<commit_after>define(function(require) {
	var registerSuite = require('intern!object'),
		assert = require('intern/chai!assert'),
		el;

	require('js/tests/support/exports.js');

	registerSuite({
		name: 'Events',

		beforeEach: function() {
			el = document.createElement('div');

			el.id = 'wee';
			el.className = 'js-wee';

			document.body.appendChild(el);

			$el = $(el);
		},

		afterEach: function() {
			el.parentNode.removeChild(el);
		},

		on: {
			simple: function() {
				Wee.events.on(el, 'click', function() {
					Wee.$addClass(el, 'test');
				});

				Wee.events.trigger(el, 'click');

				assert.ok(Wee.$hasClass(el, 'test'),
					'Event was not bound successfully'
				);
			},

			once: function() {
				Wee.events.on(el, 'click', function() {
					Wee.$append(el, '

');
				}, {
					once: true
				});

				Wee.events.trigger(el, 'click');
				Wee.events.trigger(el, 'click');

				assert.strictEqual(Wee.$children(el).length, 1,
					'Event was triggered more than once'
				);
			},

			delegate: function() {
				// TODO: Complete
				assert.isTrue(true);
			},

			'multiple events': function() {
				Wee.events.on(el, {
					click: function() {
						Wee.$addClass(el, 'test');
					},
					blur: function() {
						Wee.$removeClass(el, 'test');
						Wee.$addClass(el, 'test-2');
					}
				});

				Wee.events.trigger(el, 'click');
				Wee.events.trigger(el, 'blur');

				assert.ok(Wee.$hasClass(el, 'test-2'),
					'Multple events were not triggered successfully'
				);
			},

			'multiple selections': function() {
				Wee.$append(el, '
inner
');

				Wee.events.on({
					'#wee': {
						click: function() {
							Wee.$addClass(this, 'test');
						}
					},
					'#test': {
						click: function() {
							Wee.$addClass(this, 'test-inner');
						}
					}
				});

				Wee.events.trigger(el, 'click');
				Wee.events.trigger('#test', 'click');

				assert.ok(Wee.$hasClass(el, 'test'),
					'Multiple selections not selected successfully'
				);

				assert.ok(Wee.$hasClass('#test', 'test-inner'),
					'Multiple selections not selected successfully'
				);
			}
		},

		off: {
			target: function() {
				var $el = Wee.$('#wee');

				Wee.events.on({
					'#wee': {
						click: function() {
							Wee.$addClass($el, 'test-class');
						},
						blur: function() {
							Wee.$addClass('#wee-inner', 'test-class-2');
						}
					}
				});

				Wee.events.off($el);

				Wee.events.trigger($el, 'click');
				Wee.events.trigger($el, 'blur');

				assert.notOk(Wee.$hasClass($el, 'test-class'),
					'Event was not removed successfully'
				);
				assert.notOk(Wee.$hasClass($el, 'test-class-2'),
					'Event was not removed successfully'
				);
			},

			'selection event': function() {
				var $el = Wee.$('#wee');

				Wee.events.on({
					'#wee': {
						click: function() {
							Wee.$addClass($el, 'test-class');
						},
						blur: function() {
							Wee.$addClass($el, 'test-class-2');
						}
					}
				});

				Wee.events.off($el, 'blur');

				Wee.events.trigger($el, 'click');
				Wee.events.trigger($el, 'blur');

				assert.ok(Wee.$hasClass($el, 'test-class'),
					'Event was not removed successfully'
				);
				assert.notOk(Wee.$hasClass($el, 'test-class-2'),
					'Event was not removed successfully'
				);
			},

			'selection event callback': function() {
				var $el = Wee.$('#wee');

				var callbackFunction = function() {
					Wee.$removeClass($el, 'test-class');
				};

				Wee.events.on($el, 'click', function() {
					Wee.$addClass($el, 'test-class');
				});

				Wee.events.trigger($el, 'click');

				Wee.events.off($el, 'click', callbackFunction());

				assert.notOk(Wee.$hasClass($el, 'test-class-2'),
					'Callback function was not executed successfully'
				);
			},

			'multiple selections': function() {
				var $el = Wee.$('#wee');

				Wee.$append($el, '

');

				var callbackFunctionOne = function() {
						Wee.$removeClass($el, 'test-class');
					},
					callbackFunctionTwo = function() {
						Wee.$removeClass('#wee-inner', 'test-class-2');
					};

				Wee.events.on($el, 'click', function() {
					Wee.$addClass($el, 'test-class');
				});

				Wee.events.on('#wee-inner', 'blur', function() {
					Wee.$addClass('#wee-inner', 'test-class-2');
				}, {
					delegate: $el
				});

				Wee.events.trigger($el, 'click');
				Wee.events.trigger('#wee-inner', 'blur');

				Wee.events.off({
				    '#wee': {
				        click: callbackFunctionOne()
				    },
				    '#wee-inner': {
				        blur: callbackFunctionTwo()
				    }
				});

				assert.notOk(Wee.$hasClass($el, 'test-class'),
					'Multiple selections were not called back successfully'
				);
				assert.notOk(Wee.$hasClass('#wee-inner', 'test-class-2'),
					'Multiple selections were not called back successfully'
				);
			}
		},

		bound: function() {
			$el.html(
				'
Div 1
' +
				'
Div 2
' +
				'
Div 3
'
			);

			$('.bound-test').on('click', function() {
				return 'click';
			});

			$('.bound-test').trigger('click');

			assert.isArray($('.bound-test').bound(),
				'Did not return an array'
			);

			assert.strictEqual($('.bound-test').trigger('click')[0].innerText, 'Div 1',
				'Event was not bound to object'
			);
		},

		trigger: function() {
			var $el = Wee.$('#wee');

			Wee.events.on($el, 'click', function() {
				Wee.$addClass($el, 'test-class');
			});

			Wee.events.trigger($el, 'click');

			assert.ok(Wee.$hasClass($el, 'test-class'),
				'Event was not triggered successfully'
			);
		}
	});
});<|endoftext|>


<commit_before>/**
* @license GrapeFruit Game Engine
* Copyright (x) 2012, Chad Engler
*
* GrapeFruit is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license.php
*
*/

/****************************************************************************
 * Global GrapeFruit Object with constants
 ****************************************************************************/
window.gf = window.gf || {
    types: {
        //Entity types
        ENTITY: {
            PLAYER: 'player',
            ENEMY: 'enemy',
            FRIENDLY: 'friendly',
            NEUTRAL: 'neutral',
            COLLECTABLE: 'collectable'
        },
        //Layer types
        LAYER: {
            TILE_LAYER: 'tilelayer',
            OBJECT_GROUP: 'objectgroup' // each zone is defined as an object group
        },
        //Tile collision types
        COLLISION: {
            NONE: 'none',
            SOLID: 'solid',
            CLIFF: 'cliff',
            LADDER: 'ladder',
            WATER: 'water',
            DEEP_WATER: 'deep_water'
        },
        //pubsub events
        EVENT: {
            ENTITY_MOVE: 'gf.entity.move',
            LOADER_START: 'gf.loader.start',
            LOADER_ERROR: 'gf.loader.error',
            LOADER_PROGRESS: 'gf.loader.progress',
            LOADER_LOAD: 'gf.loader.load',
            LOADER_COMPLETE: 'gf.loader.complete'
        },
        //Bindable keycodes
        KEY: {
            BACKSPACE: 8,
            TAB: 9,
            ENTER: 13,
            SHIFT: 16,
            CTRL: 17,
            ALT: 18,
            PAUSE: 19,
            ESC: 27,
            SPACE: 32,
            PAGE_UP: 33,
            PAGE_DOWN: 34,
            END: 35,
            HOME: 36,
            LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40,
            INSERT: 45,
            DELETE: 46,
            NUM0: 48,
            NUM1: 49,
            NUM2: 50,
            NUM3: 51,
            NUM4: 52,
            NUM5: 53,
            NUM6: 54,
            NUM7: 55,
            NUM8: 56,
            NUM9: 57,
            PLUS: 61,
            A : 65,
            B : 66,
            C : 67,
            D : 68,
            E : 69,
            F : 70,
            G : 71,
            H : 72,
            I : 73,
            J : 74,
            K : 75,
            L : 76,
            M : 77,
            N : 78,
            O : 79,
            P : 80,
            Q : 81,
            R : 82,
            S : 83,
            T : 84,
            U : 85,
            V : 86,
            W : 87,
            X : 88,
            Y : 89,
            Z : 90,
            NUMPAD0: 96,
            NUMPAD1: 97,
            NUMPAD2: 98,
            NUMPAD3: 99,
            NUMPAD4: 100,
            NUMPAD5: 101,
            NUMPAD6: 102,
            NUMPAD7: 103,
            NUMPAD8: 104,
            NUMPAD9: 105,
            NUMPAD_STAR: 106,
            NUMPAD_PLUS: 107,
            NUMPAD_MINUS: 109,
            NUMPAD_DOT: 110,
            NUMPAD_SLASH: 111,
            F1: 112,
            F2: 113,
            F3: 114,
            F4: 115,
            MINUS: 173,
            TILDE: 192
        }
    },
    support: {
        canvas: !! window.CanvasRenderingContext2D,
        webgl: ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(),
        workers: !! window.Worker,
        fileapi: window.File && window.FileReader && window.FileList && window.Blob,
    }
};

/****************************************************************************
 * Javascript Inheritance Helper (use functional mixins instead?)
 ****************************************************************************/

/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

// The base Class implementation (does nothing)
Class = function() {};

// Create a new Class that inherits from this class
Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
        // Check if we're overwriting an existing function
        prototype[name] = typeof prop[name] == "function" &&
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
            (function(name, fn){
                return function() {
                    var tmp = this._super;

                    // Add a new ._super() method that is the same method
                    // but on the super-class
                    this._super = _super[name];

                    // The method only need to be bound temporarily, so we
                    // remove it when we're done executing
                    var ret = fn.apply(this, arguments);
                    this._super = tmp;

                    return ret;
                };
            })(name, prop[name]) :
            prop[name];
    }

    // The dummy class constructor
    Class = function () {
        // All construction is actually done in the init method
        if ( !initializing && this.init )
            this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
};

/****************************************************************************
 * mrdoob's stats.js (stats.js r10 - http://github.com/mrdoob/stats.js)
 ****************************************************************************/
gf.FpsCounter=function(){var l=Date.now(),m=l,g=0,n=1E3,o=0,h=0,p=1E3,q=0,r=0,s=0,f=document.createElement("div");f.id="stats";f.addEventListener("mousedown",function(b){b.preventDefault();t(++s%2)},!1);f.style.cssText="width:80px;opacity:0.9;cursor:pointer";var a=document.createElement("div");a.id="fps";a.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#002";f.appendChild(a);var i=document.createElement("div");i.id="fpsText";i.style.cssText="color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";
i.innerHTML="FPS";a.appendChild(i);var c=document.createElement("div");c.id="fpsGraph";c.style.cssText="position:relative;width:74px;height:30px;background-color:#0ff";for(a.appendChild(c);74>c.children.length;){var j=document.createElement("span");j.style.cssText="width:1px;height:30px;float:left;background-color:#113";c.appendChild(j)}var d=document.createElement("div");d.id="ms";d.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#020;display:none";f.appendChild(d);var k=document.createElement("div");
k.id="msText";k.style.cssText="color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";k.innerHTML="MS";d.appendChild(k);var e=document.createElement("div");e.id="msGraph";e.style.cssText="position:relative;width:74px;height:30px;background-color:#0f0";for(d.appendChild(e);74>e.children.length;)j=document.createElement("span"),j.style.cssText="width:1px;height:30px;float:left;background-color:#131",e.appendChild(j);var t=function(b){s=b;switch(s){case 0:a.style.display=
"block";d.style.display="none";break;case 1:a.style.display="none",d.style.display="block"}};return{domElement:f,setMode:t,begin:function(){l=Date.now()},end:function(){var b=Date.now();g=b-l;n=Math.min(n,g);o=Math.max(o,g);k.textContent=g+" MS ("+n+"-"+o+")";var a=Math.min(30,30-30*(g/200));e.appendChild(e.firstChild).style.height=a+"px";r++;b>m+1E3&&(h=Math.round(1E3*r/(b-m)),p=Math.min(p,h),q=Math.max(q,h),i.textContent=h+" FPS ("+p+"-"+q+")",a=Math.min(30,30-30*(h/100)),c.appendChild(c.firstChild).style.height=
a+"px",m=b,r=0);return b},update:function(){l=this.end()}}};

/****************************************************************************
 * Main game object
 ****************************************************************************/

(function() {
    gf.game = {
        //array of objects in the scene
        objects: {},

        //special user-defined entity types
        entTypes: {},

        //maximum Z index, where the camera lies
        MAX_Z: 500,

        //raw THREE objects that will control rendering
        _scene: new THREE.Scene(),
        _clock: new THREE.Clock(false),
        _renderer: null,
        _camera: null,

        //id for the next entity to be added
        _nextId: Date.now(),

        //the object that will contain the render domElement
        _$cont: null,

        //have we initialized the game already?
        _initialized: false,

        init: function(contId, width, height, renderMethod) {
            if(gf.controls._initialized) return;

            //if they speciy a method, check if it is available
            if(renderMethod) {
                if(!gf.support[renderMethod]) {
                    throw 'Render method ' + renderMethod + ' is not supported by this browser!';
                    return;
                }
            }
            //if they don't specify a method, guess the best to use
            else {
                if(gf.support.webgl) renderMethod = 'webgl';
                else if(gf.support.canvas) renderMethod = 'canvas';
                else {
                    throw 'Neither WebGL nor Canvas is supported by this browser!';
                    return;
                }
            }

            //initialize the correct renderer
            if(renderMethod == 'webgl') {
                gf.game._renderer = new THREE.WebGLRenderer({
                    //can also specify 'canvas' dom element, but we just let THREE generate one
                    precision: 'highp',
                    alpha: true,
                    premultipliedAlpha: true,
                    antialias: false,
                    clearColor: 0xff00ff,
                    clearAlpha: 0,
                    maxLights: 4
                });
            } else if(renderMethod == 'canvas') {
                gf.game._renderer = new THREE.CanvasRenderer({
                    //can also specify 'canvas' dom element, but we just let THREE generate one
                });
            }

            gf.game._renderMethod = renderMethod;

            //cache the container object
            gf.game._$cont = $('#' + contId);

            var w = width || gf.game._$cont.width(),
                h = height || gf.game._$cont.height();

            //initialize the renderer
            gf.game._renderer.setSize(w, h);
            gf.game._$cont.append(gf.game._renderer.domElement);

            //initialize the camera
            gf.game._camera = new THREE.OrthographicCamera(w / -2, w / 2, h / 2, h / -2, 1, 1000);
            gf.game._camera.position.z = gf.game.MAX_Z;

            gf.game._scene.add(this.camera);

            //add ambient light to the scene
            gf.game._scene.add(new THREE.AmbientLight(0xffffff));

            //initialize the controls
            gf.controls.init();

            //initialize the audio player
            gf.audio.init();

            //initialize the GUI (HUD, menus, etc)
            gf.gui.init();

            //fps counter
            if(gf.debug.showFps) {
                gf.debug._fpsCounter = new gf.FpsCounter();
                gf.debug._fpsCounter.domElement.style.position = gf.debug.fpsStyle.position;
                gf.debug._fpsCounter.domElement.style.top = gf.debug.fpsStyle.top;
                gf.debug._fpsCounter.domElement.style.left =gf.debug.fpsStyle.left;

                $('body').append(gf.debug._fpsCounter.domElement);
            }

            gf.game._initialized = true;

            return this;
        },
        getNextObjectId: function() {
            return gf.game._nextId++;
        },
        addObject: function(obj) {
            if(!obj) return;

            if(!obj.id) obj.id = gf.game.getNextObjectId();
            gf.game.objects[obj.id] = obj;

            if(obj.addToScene) obj.addToScene(gf.game._scene);

            return this;
        },
        removeObject: function(obj) {
            if(!obj) return;

            //remove object from our list
            delete gf.game.objects[obj.id];

            if(obj.removeFromScene) obj.removeFromScene(gf.game._scene);

            return this;
        },
        loadWorld: function(world) {
            if(typeof world == 'string'){
                if(gf.resources[world]) world = gf.resources[world].data;
                else {
                    throw 'World not found in resources!';
                    return;
                }
            }

            gf.game.world = new gf.TiledMap(world);
            gf.game.addObject(gf.game.world);
        },
        render: function() {
            gf.game._clock.start();
            gf.game._tick();

            return this;
        },
        //Check if passed entity collides with any others
        checkCollisions: function(obj) {
            var colliders = [];

            $.each(gf.game.objects, function(id, o) {
                //check if this object collides with any others
                if(/*o.inViewport &&*/ o.isVisible && o.isCollidable && o.isEntity && (o != obj)) {
                    var collisionVector = o.checkCollision(obj);
                    if(!collisionVector.isZero()) {
                        colliders.push({
                            entity: o,
                            vector: collisionVector
                        });
                        o.onCollision(obj);
                    }
                }
            });

            return colliders;
        },
        //check if passed entity collides with any map tile after applying the velocity movement
        checkMapCollision: function() {

        },
        //lock the camera on an entity
        //I need an event system :/
        cameraTrack: function(ent) {
            if(ent.isEntity) {
                if(this._trackedEntMoveHandle) {
                    gf.event.unsubscribe(this._trackedEntMoveHandle);
                }

                this._trackedEntMoveHandle = gf.event.subscribe(gf.types.EVENT.ENTITY_MOVE + '.' + ent.id, function(velocity) {
                    gf.game._camera.translateX(velocity.x);
                    gf.game._camera.translateY(velocity.y);
                });
            }

            return this;
        },
        _tick: function() {
            //start render loop
            requestAnimationFrame(gf.game._tick);

            //get clock delta
            gf.game._delta = gf.game._clock.getDelta();

            //update fps box
            if(gf.debug._fpsCounter) gf.debug._fpsCounter.update();

            //update each object
            $.each(gf.game.objects, function(id, o) {
                o.update();
            });

            //render scene
            gf.game._renderer.render(gf.game._scene, gf.game._camera);
        }
    };
})();<commit_msg>dealloc code for entities removed from game<commit_after>/**
* @license GrapeFruit Game Engine
* Copyright (x) 2012, Chad Engler
*
* GrapeFruit is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license.php
*
*/

/****************************************************************************
 * Global GrapeFruit Object with constants
 ****************************************************************************/
window.gf = window.gf || {
    types: {
        //Entity types
        ENTITY: {
            PLAYER: 'player',
            ENEMY: 'enemy',
            FRIENDLY: 'friendly',
            NEUTRAL: 'neutral',
            COLLECTABLE: 'collectable'
        },
        //Layer types
        LAYER: {
            TILE_LAYER: 'tilelayer',
            OBJECT_GROUP: 'objectgroup' // each zone is defined as an object group
        },
        //Tile collision types
        COLLISION: {
            NONE: 'none',
            SOLID: 'solid',
            CLIFF: 'cliff',
            LADDER: 'ladder',
            WATER: 'water',
            DEEP_WATER: 'deep_water'
        },
        //pubsub events
        EVENT: {
            ENTITY_MOVE: 'gf.entity.move',
            LOADER_START: 'gf.loader.start',
            LOADER_ERROR: 'gf.loader.error',
            LOADER_PROGRESS: 'gf.loader.progress',
            LOADER_LOAD: 'gf.loader.load',
            LOADER_COMPLETE: 'gf.loader.complete'
        },
        //Bindable keycodes
        KEY: {
            BACKSPACE: 8,
            TAB: 9,
            ENTER: 13,
            SHIFT: 16,
            CTRL: 17,
            ALT: 18,
            PAUSE: 19,
            ESC: 27,
            SPACE: 32,
            PAGE_UP: 33,
            PAGE_DOWN: 34,
            END: 35,
            HOME: 36,
            LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40,
            INSERT: 45,
            DELETE: 46,
            NUM0: 48,
            NUM1: 49,
            NUM2: 50,
            NUM3: 51,
            NUM4: 52,
            NUM5: 53,
            NUM6: 54,
            NUM7: 55,
            NUM8: 56,
            NUM9: 57,
            PLUS: 61,
            A : 65,
            B : 66,
            C : 67,
            D : 68,
            E : 69,
            F : 70,
            G : 71,
            H : 72,
            I : 73,
            J : 74,
            K : 75,
            L : 76,
            M : 77,
            N : 78,
            O : 79,
            P : 80,
            Q : 81,
            R : 82,
            S : 83,
            T : 84,
            U : 85,
            V : 86,
            W : 87,
            X : 88,
            Y : 89,
            Z : 90,
            NUMPAD0: 96,
            NUMPAD1: 97,
            NUMPAD2: 98,
            NUMPAD3: 99,
            NUMPAD4: 100,
            NUMPAD5: 101,
            NUMPAD6: 102,
            NUMPAD7: 103,
            NUMPAD8: 104,
            NUMPAD9: 105,
            NUMPAD_STAR: 106,
            NUMPAD_PLUS: 107,
            NUMPAD_MINUS: 109,
            NUMPAD_DOT: 110,
            NUMPAD_SLASH: 111,
            F1: 112,
            F2: 113,
            F3: 114,
            F4: 115,
            MINUS: 173,
            TILDE: 192
        }
    },
    support: {
        canvas: !! window.CanvasRenderingContext2D,
        webgl: ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(),
        workers: !! window.Worker,
        fileapi: window.File && window.FileReader && window.FileList && window.Blob,
    }
};

/****************************************************************************
 * Javascript Inheritance Helper (use functional mixins instead?)
 ****************************************************************************/

/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

// The base Class implementation (does nothing)
Class = function() {};

// Create a new Class that inherits from this class
Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
        // Check if we're overwriting an existing function
        prototype[name] = typeof prop[name] == "function" &&
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
            (function(name, fn){
                return function() {
                    var tmp = this._super;

                    // Add a new ._super() method that is the same method
                    // but on the super-class
                    this._super = _super[name];

                    // The method only need to be bound temporarily, so we
                    // remove it when we're done executing
                    var ret = fn.apply(this, arguments);
                    this._super = tmp;

                    return ret;
                };
            })(name, prop[name]) :
            prop[name];
    }

    // The dummy class constructor
    Class = function () {
        // All construction is actually done in the init method
        if ( !initializing && this.init )
            this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
};

/****************************************************************************
 * mrdoob's stats.js (stats.js r10 - http://github.com/mrdoob/stats.js)
 ****************************************************************************/
gf.FpsCounter=function(){var l=Date.now(),m=l,g=0,n=1E3,o=0,h=0,p=1E3,q=0,r=0,s=0,f=document.createElement("div");f.id="stats";f.addEventListener("mousedown",function(b){b.preventDefault();t(++s%2)},!1);f.style.cssText="width:80px;opacity:0.9;cursor:pointer";var a=document.createElement("div");a.id="fps";a.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#002";f.appendChild(a);var i=document.createElement("div");i.id="fpsText";i.style.cssText="color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";
i.innerHTML="FPS";a.appendChild(i);var c=document.createElement("div");c.id="fpsGraph";c.style.cssText="position:relative;width:74px;height:30px;background-color:#0ff";for(a.appendChild(c);74>c.children.length;){var j=document.createElement("span");j.style.cssText="width:1px;height:30px;float:left;background-color:#113";c.appendChild(j)}var d=document.createElement("div");d.id="ms";d.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#020;display:none";f.appendChild(d);var k=document.createElement("div");
k.id="msText";k.style.cssText="color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";k.innerHTML="MS";d.appendChild(k);var e=document.createElement("div");e.id="msGraph";e.style.cssText="position:relative;width:74px;height:30px;background-color:#0f0";for(d.appendChild(e);74>e.children.length;)j=document.createElement("span"),j.style.cssText="width:1px;height:30px;float:left;background-color:#131",e.appendChild(j);var t=function(b){s=b;switch(s){case 0:a.style.display=
"block";d.style.display="none";break;case 1:a.style.display="none",d.style.display="block"}};return{domElement:f,setMode:t,begin:function(){l=Date.now()},end:function(){var b=Date.now();g=b-l;n=Math.min(n,g);o=Math.max(o,g);k.textContent=g+" MS ("+n+"-"+o+")";var a=Math.min(30,30-30*(g/200));e.appendChild(e.firstChild).style.height=a+"px";r++;b>m+1E3&&(h=Math.round(1E3*r/(b-m)),p=Math.min(p,h),q=Math.max(q,h),i.textContent=h+" FPS ("+p+"-"+q+")",a=Math.min(30,30-30*(h/100)),c.appendChild(c.firstChild).style.height=
a+"px",m=b,r=0);return b},update:function(){l=this.end()}}};

/****************************************************************************
 * Main game object
 ****************************************************************************/

(function() {
    gf.game = {
        //array of objects in the scene
        objects: {},

        //special user-defined entity types
        entTypes: {},

        //maximum Z index, where the camera lies
        MAX_Z: 500,

        //raw THREE objects that will control rendering
        _scene: new THREE.Scene(),
        _clock: new THREE.Clock(false),
        _renderer: null,
        _camera: null,

        //id for the next entity to be added
        _nextId: Date.now(),

        //the object that will contain the render domElement
        _$cont: null,

        //have we initialized the game already?
        _initialized: false,

        init: function(contId, width, height, renderMethod) {
            if(gf.controls._initialized) return;

            //if they speciy a method, check if it is available
            if(renderMethod) {
                if(!gf.support[renderMethod]) {
                    throw 'Render method ' + renderMethod + ' is not supported by this browser!';
                    return;
                }
            }
            //if they don't specify a method, guess the best to use
            else {
                if(gf.support.webgl) renderMethod = 'webgl';
                else if(gf.support.canvas) renderMethod = 'canvas';
                else {
                    throw 'Neither WebGL nor Canvas is supported by this browser!';
                    return;
                }
            }

            //initialize the correct renderer
            if(renderMethod == 'webgl') {
                gf.game._renderer = new THREE.WebGLRenderer({
                    //can also specify 'canvas' dom element, but we just let THREE generate one
                    precision: 'highp',
                    alpha: true,
                    premultipliedAlpha: true,
                    antialias: false,
                    clearColor: 0xff00ff,
                    clearAlpha: 0,
                    maxLights: 4
                });
            } else if(renderMethod == 'canvas') {
                gf.game._renderer = new THREE.CanvasRenderer({
                    //can also specify 'canvas' dom element, but we just let THREE generate one
                });
            }

            gf.game._renderMethod = renderMethod;

            //cache the container object
            gf.game._$cont = $('#' + contId);

            var w = width || gf.game._$cont.width(),
                h = height || gf.game._$cont.height();

            //initialize the renderer
            gf.game._renderer.setSize(w, h);
            gf.game._$cont.append(gf.game._renderer.domElement);

            //initialize the camera
            gf.game._camera = new THREE.OrthographicCamera(w / -2, w / 2, h / 2, h / -2, 1, 1000);
            gf.game._camera.position.z = gf.game.MAX_Z;

            gf.game._scene.add(this.camera);

            //add ambient light to the scene
            gf.game._scene.add(new THREE.AmbientLight(0xffffff));

            //initialize the controls
            gf.controls.init();

            //initialize the audio player
            gf.audio.init();

            //initialize the GUI (HUD, menus, etc)
            gf.gui.init();

            //fps counter
            if(gf.debug.showFps) {
                gf.debug._fpsCounter = new gf.FpsCounter();
                gf.debug._fpsCounter.domElement.style.position = gf.debug.fpsStyle.position;
                gf.debug._fpsCounter.domElement.style.top = gf.debug.fpsStyle.top;
                gf.debug._fpsCounter.domElement.style.left =gf.debug.fpsStyle.left;

                $('body').append(gf.debug._fpsCounter.domElement);
            }

            gf.game._initialized = true;

            return this;
        },
        getNextObjectId: function() {
            return gf.game._nextId++;
        },
        addObject: function(obj) {
            if(!obj) return;

            if(!obj.id) obj.id = gf.game.getNextObjectId();
            gf.game.objects[obj.id] = obj;

            if(obj.addToScene) obj.addToScene(gf.game._scene);

            return this;
        },
        removeObject: function(obj) {
            if(!obj) return;

            //remove object from our list
            delete gf.game.objects[obj.id];

            if(obj.removeFromScene) obj.removeFromScene(gf.game._scene);

            //deallocate resources for this entity
            gf.game._renderer.deallocateObject(obj._mesh);
            gf.game._renderer.deallocateObject(obj._hitboxMesh);

            return this;
        },
        loadWorld: function(world) {
            if(typeof world == 'string'){
                if(gf.resources[world]) world = gf.resources[world].data;
                else {
                    throw 'World not found in resources!';
                    return;
                }
            }

            gf.game.world = new gf.TiledMap(world);
            gf.game.addObject(gf.game.world);
        },
        render: function() {
            gf.game._clock.start();
            gf.game._tick();

            return this;
        },
        //Check if passed entity collides with any others
        checkCollisions: function(obj) {
            var colliders = [];

            $.each(gf.game.objects, function(id, o) {
                //check if this object collides with any others
                if(/*o.inViewport &&*/ o.isVisible && o.isCollidable && o.isEntity && (o != obj)) {
                    var collisionVector = o.checkCollision(obj);
                    if(!collisionVector.isZero()) {
                        colliders.push({
                            entity: o,
                            vector: collisionVector
                        });
                        o.onCollision(obj);
                    }
                }
            });

            return colliders;
        },
        //check if passed entity collides with any map tile after applying the velocity movement
        checkMapCollision: function() {

        },
        //lock the camera on an entity
        //I need an event system :/
        cameraTrack: function(ent) {
            if(ent.isEntity) {
                if(this._trackedEntMoveHandle) {
                    gf.event.unsubscribe(this._trackedEntMoveHandle);
                }

                this._trackedEntMoveHandle = gf.event.subscribe(gf.types.EVENT.ENTITY_MOVE + '.' + ent.id, function(velocity) {
                    gf.game._camera.translateX(velocity.x);
                    gf.game._camera.translateY(velocity.y);
                });
            }

            return this;
        },
        _tick: function() {
            //start render loop
            requestAnimationFrame(gf.game._tick);

            //get clock delta
            gf.game._delta = gf.game._clock.getDelta();

            //update fps box
            if(gf.debug._fpsCounter) gf.debug._fpsCounter.update();

            //update each object
            $.each(gf.game.objects, function(id, o) {
                o.update();
            });

            //render scene
            gf.game._renderer.render(gf.game._scene, gf.game._camera);
        }
    };
})();<|endoftext|>


<commit_before>angular.module('timer', [])
  .directive('timer', function ($timeout, $compile) {
    return  {
      restrict: 'E',
      replace: false,
      scope: {
          interval: '=interval',
          countdownattr: '=countdown'
      },
      controller: function ($scope, $element) {
        if ($element.html().trim().length === 0) {
          $element.append($compile('{{millis}}')($scope));
        }

        $scope.startTime = null;
        $scope.timeoutId = null;
        $scope.countdown = $scope.countdownattr && parseInt($scope.countdownattr, 10) > 0 ? parseInt($scope.countdownattr, 10) : undefined;
        $scope.isRunning = false;

        $scope.$on('timer-start', function (){
          $scope.start();
        });

        $scope.$on('timer-resume', function (){
          $scope.resume();
        });

        $scope.$on('timer-stop', function (){
          $scope.stop();
        });

        function init() {
          if ($scope.timeoutId) {
            $timeout.cancel($scope.timeoutId);
          }
        }

        $scope.start = $element[0].start = function () {
          $scope.startTime = new Date();
          init();
          tick();
        };

        $scope.resume = $element[0].resume = function () {
          init();
          $scope.startTime = new Date() - ($scope.stoppedTime - $scope.startTime);
          tick();
        };

        $scope.stop = $element[0].stop = function () {
          $scope.stoppedTime = new Date();
          $timeout.cancel($scope.timeoutId);
          $scope.timeoutId = null;
        };

        $element.bind('$destroy', function () {
          $timeout.cancel($scope.timeoutId);
        });

        var tick = function (){
            if ($scope.countdown > 0) {
                $scope.countdown--;
            }
            else if ($scope.countdown <= 0) {
                $scope.stop();
            }
            $scope.millis = new Date() - $scope.startTime;
            $scope.seconds = Math.floor(($scope.millis / 1000) % 60) ;
            $scope.minutes = Math.floor((($scope.millis / (1000*60)) % 60));
            $scope.hours = Math.floor((($scope.millis / (1000*60*60)) % 24));
            $scope.timeoutId = $timeout(function () {
              tick();
            }, $scope.interval);
        };

        $scope.start();
      }
    };
  });<commit_msg>method name refactoring<commit_after>angular.module('timer', [])
  .directive('timer', function ($timeout, $compile) {
    return  {
      restrict: 'E',
      replace: false,
      scope: {
          interval: '=interval',
          countdownattr: '=countdown'
      },
      controller: function ($scope, $element) {
        if ($element.html().trim().length === 0) {
          $element.append($compile('{{millis}}')($scope));
        }

        $scope.startTime = null;
        $scope.timeoutId = null;
        $scope.countdown = $scope.countdownattr && parseInt($scope.countdownattr, 10) > 0 ? parseInt($scope.countdownattr, 10) : undefined;
        $scope.isRunning = false;

        $scope.$on('timer-start', function (){
          $scope.start();
        });

        $scope.$on('timer-resume', function (){
          $scope.resume();
        });

        $scope.$on('timer-stop', function (){
          $scope.stop();
        });

        function reset() {
          if ($scope.timeoutId) {
            $timeout.cancel($scope.timeoutId);
          }
        }

        $scope.start = $element[0].start = function () {
          $scope.startTime = new Date();
          reset();
          tick();
        };

        $scope.resume = $element[0].resume = function () {
          reset();
          $scope.startTime = new Date() - ($scope.stoppedTime - $scope.startTime);
          tick();
        };

        $scope.stop = $element[0].stop = function () {
          $scope.stoppedTime = new Date();
          $timeout.cancel($scope.timeoutId);
          $scope.timeoutId = null;
        };

        $element.bind('$destroy', function () {
          $timeout.cancel($scope.timeoutId);
        });

        var tick = function (){
            if ($scope.countdown > 0) {
                $scope.countdown--;
            }
            else if ($scope.countdown <= 0) {
                $scope.stop();
            }
            $scope.millis = new Date() - $scope.startTime;
            $scope.seconds = Math.floor(($scope.millis / 1000) % 60) ;
            $scope.minutes = Math.floor((($scope.millis / (1000*60)) % 60));
            $scope.hours = Math.floor((($scope.millis / (1000*60*60)) % 24));
            $scope.timeoutId = $timeout(function () {
              tick();
            }, $scope.interval);
        };

        $scope.start();
      }
    };
  });<|endoftext|>


<commit_before>const Discord = require("discord.js"),
    beheeyem = new Discord.Client(),
    fs = require("fs"),
    jsonfile = require("jsonfile"),
    path = require("path"),
    request = require("request"),
    colors = require('colors');
var config = require('./config.js'),
    imageCheck;

console.log("Starting Beheeyem...");

var commands = loadCommands();

beheeyem.on("ready", function() {
    console.log(("Beheeyem is active! Currently serving in " + String(beheeyem.guilds.size).white + " guilds.\n".green).bold);
    beheeyem.user.setGame("b.help");
    try {
        request.post("https://bots.discord.pw/api/bots/" + beheeyem.user.id + "/stats", {
            server_count: beheeyem.guilds.size
        });
    } catch (err) {
        console.log("Could not update server count on Discord Bots website.".yellow);
    }

});

function loadCommands() {
    console.log('Loading commands...'.cyan)
    var commands = {};
    let errCount = 0;
    cmdfiles = fs.readdirSync('./commands/');
    cmdfiles.forEach(filename => {
        var cmdName = filename.split('.')[0];
        try {
            commands[cmdName] = require('./commands/' + filename);
            console.log('Loaded '.green + cmdName.yellow.bold);
        } catch (err) {
            if (err) {
                errCount++;
                console.log('Error in '.red + cmdName.yellow + '!'.red + '\n' + err.stack);
            }
        }
    });
    console.log('Loaded commands with '.cyan + (errCount > 0 ? errCount.toString().red : 'no'.green) + ` error${errCount == 1? '' : 's'}!`.cyan);
    return commands;
}

beheeyem.on("message", msg => {
    if (msg.author.id != beheeyem.user.id && !msg.author.bot) {
        if (msg.content.startsWith(config.prefix)) {
            var commandstring = msg.content.substring(config.prefix.length);
            var cmd = commandstring.split(" ")[0];
            var args = commandstring.substring(cmd.length + 1);

            if (commands[cmd]) {
                commands[cmd].action(msg, args, beheeyem);
            } else if (cmd == "obtain") {
                msg.channel.send("Honestly, just use Bulbapedia. The encounter data on the web is so inconsistent and undreadable that there's no way I could create an obtainability command. Sorry about that. 🙁");
            } else if (cmd == "deathbird") {
                msg.channel.send('', {
                    file: "https://i.imgur.com/pIxQQXA.png",
                    name: "DEATHBIRD.png"
                });
            } else if (cmd == "youtried") {
                msg.channel.send('', {
                    file: "https://i.imgur.com/bAxMdQ0.png",
                    name: "Filename.jpeg.gif.webp.mp4.exe.bat.sh.app.png"
                });
            } else if (msg.author.id == 120887602395086848) {
                if (cmd == "addnonya") {
                    var nonyas = require("./data/nonyas.json");
                    nonyas.nonyas.push(args);
                    jsonfile.writeFileSync("./data/nonyas.json", nonyas);
                    msg.channel.send("👌🏾 Sucessfully added Nonya!");
                } else if (cmd == 'eval') {
                    try {
                        msg.channel.sendMessage("", {
                            embed: {
                                title: '🖥 JavaScript Eval',
                                fields: [{
                                        name: "Input",
                                        value: args
                                    },
                                    {
                                        name: "Output",
                                        value: eval(args)
                                    }
                                ],
                                color: 5561189
                            }
                        });
                    } catch (err) {
                        msg.channel.sendMessage("", {
                            embed: {
                                title: '⚠ Error',
                                fields: [{
                                        name: "Input",
                                        value: args
                                    },
                                    {
                                        name: "Error",
                                        value: err.toString()
                                    }
                                ],
                                color: 16724015
                            }
                        });
                    }
                }
            }
        }
        imageCheck = false;
        checkItalics(msg);
    }
});

beheeyem.login(config.token);

beheeyem.on("guildCreate", (guild) => {
    try {
        request.post({
            url: "https://bots.discord.pw/api/bots/" + beheeyem.user.id + "/stats",
            headers: {
                authorization: config.dbotsToken
            }
        }, {
            server_count: beheeyem.guilds.size
        });
    } catch (err) {
        console.log("Could not update server count on Discord Bots website.".yellow);
    }
});

function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

function checkItalics(msg) {
    let isShiny = false;
    var isFound = false;
    let urlBuild = 'https://play.pokemonshowdown.com/sprites/xyani/';
    var asteriskSplit = msg.content.split("*");
    var pokeName;
    for (var i = 1; i < asteriskSplit.length - 1; i++) {
        pokeName = asteriskSplit[i].toLowerCase();
        if (pokeName.indexOf('shiny') != -1) {
            isShiny = true;
            pokeName = pokeName.replace(' shiny', '').replace('shiny ', '').replace('-shiny', '').replace('shiny-', '').replace('shiny', '');
        }
        pokeName = pokeName.replace(" ", "-");
        if (isShiny) urlBuild = 'https://play.pokemonshowdown.com/sprites/xyani-shiny/';
        request(urlBuild + pokeName + ".gif", (err, response) => {;
            if (!err) {
                if (response.statusCode == 200) {
                    msg.channel.send('', {
                        file: response.request.href
                    });
                    isFound = true;
                }
            }
        });
        if (isFound) break;
    }
    if (!isFound) {
        var underSplit = msg.content.split("_");
        var pokeName;
        for (var i = 1; i < underSplit.length - 1; i++) {
            pokeName = underSplit[i].toLowerCase();
            if (pokeName.indexOf('shiny') != -1) {
                isShiny = true;
                pokeName = pokeName.replace(' shiny', '').replace('shiny ', '').replace('-shiny', '').replace('shiny-', '').replace('shiny', '');
            }
            pokeName = pokeName.replace(" ", "-");
            if (isShiny) urlBuild = 'https://play.pokemonshowdown.com/sprites/xyani-shiny/';
            request(urlBuild + pokeName + ".gif", (err, response) => {
                if (!err) {
                    if (response.statusCode == 200) {
                        isFound == true;
                        msg.channel.send({
                            file: response.request.href
                        });
                    }
                }
            });
            if (isFound) break;
        }
    }
}<commit_msg>Fixed italicized pokemon picking up special URL characters<commit_after>const Discord = require("discord.js"),
    beheeyem = new Discord.Client(),
    fs = require("fs"),
    jsonfile = require("jsonfile"),
    path = require("path"),
    request = require("request"),
    colors = require('colors');
var config = require('./config.js'),
    imageCheck;

console.log("Starting Beheeyem...");

var commands = loadCommands();

beheeyem.on("ready", function() {
    console.log(("Beheeyem is active! Currently serving in " + String(beheeyem.guilds.size).white + " guilds.\n".green).bold);
    beheeyem.user.setGame("b.help");
    try {
        request.post("https://bots.discord.pw/api/bots/" + beheeyem.user.id + "/stats", {
            server_count: beheeyem.guilds.size
        });
    } catch (err) {
        console.log("Could not update server count on Discord Bots website.".yellow);
    }

});

function loadCommands() {
    console.log('Loading commands...'.cyan)
    var commands = {};
    let errCount = 0;
    cmdfiles = fs.readdirSync('./commands/');
    cmdfiles.forEach(filename => {
        var cmdName = filename.split('.')[0];
        try {
            commands[cmdName] = require('./commands/' + filename);
            console.log('Loaded '.green + cmdName.yellow.bold);
        } catch (err) {
            if (err) {
                errCount++;
                console.log('Error in '.red + cmdName.yellow + '!'.red + '\n' + err.stack);
            }
        }
    });
    console.log('Loaded commands with '.cyan + (errCount > 0 ? errCount.toString().red : 'no'.green) + ` error${errCount == 1? '' : 's'}!`.cyan);
    return commands;
}

beheeyem.on("message", msg => {
    if (msg.author.id != beheeyem.user.id && !msg.author.bot) {
        if (msg.content.startsWith(config.prefix)) {
            var commandstring = msg.content.substring(config.prefix.length);
            var cmd = commandstring.split(" ")[0];
            var args = commandstring.substring(cmd.length + 1);

            if (commands[cmd]) {
                commands[cmd].action(msg, args, beheeyem);
            } else if (cmd == "obtain") {
                msg.channel.send("Honestly, just use Bulbapedia. The encounter data on the web is so inconsistent and undreadable that there's no way I could create an obtainability command. Sorry about that. 🙁");
            } else if (cmd == "deathbird") {
                msg.channel.send('', {
                    file: "https://i.imgur.com/pIxQQXA.png",
                    name: "DEATHBIRD.png"
                });
            } else if (cmd == "youtried") {
                msg.channel.send('', {
                    file: "https://i.imgur.com/bAxMdQ0.png",
                    name: "Filename.jpeg.gif.webp.mp4.exe.bat.sh.app.png"
                });
            } else if (msg.author.id == 120887602395086848) {
                if (cmd == "addnonya") {
                    var nonyas = require("./data/nonyas.json");
                    nonyas.nonyas.push(args);
                    jsonfile.writeFileSync("./data/nonyas.json", nonyas);
                    msg.channel.send("👌🏾 Sucessfully added Nonya!");
                } else if (cmd == 'eval') {
                    try {
                        msg.channel.sendMessage("", {
                            embed: {
                                title: '🖥 JavaScript Eval',
                                fields: [{
                                        name: "Input",
                                        value: args
                                    },
                                    {
                                        name: "Output",
                                        value: eval(args)
                                    }
                                ],
                                color: 5561189
                            }
                        });
                    } catch (err) {
                        msg.channel.sendMessage("", {
                            embed: {
                                title: '⚠ Error',
                                fields: [{
                                        name: "Input",
                                        value: args
                                    },
                                    {
                                        name: "Error",
                                        value: err.toString()
                                    }
                                ],
                                color: 16724015
                            }
                        });
                    }
                }
            }
        }
        imageCheck = false;
        checkItalics(msg);
    }
});

beheeyem.login(config.token);

beheeyem.on("guildCreate", (guild) => {
    try {
        request.post({
            url: "https://bots.discord.pw/api/bots/" + beheeyem.user.id + "/stats",
            headers: {
                authorization: config.dbotsToken
            }
        }, {
            server_count: beheeyem.guilds.size
        });
    } catch (err) {
        console.log("Could not update server count on Discord Bots website.".yellow);
    }
});

function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

function checkItalics(msg) {
    let isShiny = false;
    var isFound = false;
    let urlBuild = 'https://play.pokemonshowdown.com/sprites/xyani/';
    var asteriskSplit = msg.content.replace('#', '').replace('?', '').split("*");
    var pokeName;
    for (var i = 1; i < asteriskSplit.length - 1; i++) {
        pokeName = asteriskSplit[i].toLowerCase();
        if (pokeName.indexOf('shiny') != -1) {
            isShiny = true;
            pokeName = pokeName.replace(' shiny', '').replace('shiny ', '').replace('-shiny', '').replace('shiny-', '').replace('shiny', '');
        }
        pokeName = pokeName.replace(" ", "-");
        if (isShiny) urlBuild = 'https://play.pokemonshowdown.com/sprites/xyani-shiny/';
        request(urlBuild + pokeName + ".gif", (err, response) => {;
            if (!err) {
                if (response.statusCode == 200) {
                    msg.channel.send('', {
                        file: response.request.href
                    });
                    isFound = true;
                }
            }
        });
        if (isFound) break;
    }
    if (!isFound) {
        var underSplit = msg.content.replace('#', '').replace('?', '').split("_");
        var pokeName;
        for (var i = 1; i < underSplit.length - 1; i++) {
            pokeName = underSplit[i].toLowerCase();
            if (pokeName.indexOf('shiny') != -1) {
                isShiny = true;
                pokeName = pokeName.replace(' shiny', '').replace('shiny ', '').replace('-shiny', '').replace('shiny-', '').replace('shiny', '');
            }
            pokeName = pokeName.replace(" ", "-");
            if (isShiny) urlBuild = 'https://play.pokemonshowdown.com/sprites/xyani-shiny/';
            request(urlBuild + pokeName + ".gif", (err, response) => {
                if (!err) {
                    if (response.statusCode == 200) {
                        isFound == true;
                        msg.channel.send({
                            file: response.request.href
                        });
                    }
                }
            });
            if (isFound) break;
        }
    }
}<|endoftext|>