<commit_before>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        this.$el = document.getElementById(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        // Utility: Raw Attributes -> Key Value Pairs
        var extractAttrs = function(node) {
          var attrs = {};
          if(!node.attributes) return attrs;
          var rawAttrs = node.attributes;
          for(var i = 0; i < rawAttrs.length; i++) {
            attrs[rawAttrs[i].name] = rawAttrs[i].value
          }

          return attrs;
        }

        // Utility: Compile a template and return html
        var compileTemplate = function(template, data) {
          var code = template,
              re = /{{([.]?\w+)}}/gi;
          code.replace(re, function(match, p) {
            code = code.replace(match, "` + data." + p + " + `");
          });
          var compile = new Function("data", "var out = `" + code + "`; return out");
          return compile(data);
        }

        // Utility: Create Elements Recursively For all Children
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        // Utility: Create Virtual DOM Instance
        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        // Build the DOM with $data
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        // Create Virtual DOM Object from Params
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        // Set any value in $data
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        // Get any value in $data
        this.get = function(key) {
          return this.$data[key];
        }

        // Make AJAX GET/POST requests
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        // Call a method defined in _methods
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
          this.build(this.dom.children);
        }

        // Default Directives
        var dirSelf = this;
        directives["m-if"] = function(el, val) {
          var evaluated = new Function("return " + val);
          if(!evaluated) {
            el.textContent = "";
          }
        }

        // Initialize
        this.createVirtualDOM(this.$el);
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<commit_msg>if components<commit_after>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        this.$el = document.getElementById(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        // Utility: Raw Attributes -> Key Value Pairs
        var extractAttrs = function(node) {
          var attrs = {};
          if(!node.attributes) return attrs;
          var rawAttrs = node.attributes;
          for(var i = 0; i < rawAttrs.length; i++) {
            attrs[rawAttrs[i].name] = rawAttrs[i].value
          }

          return attrs;
        }

        // Utility: Compile a template and return html
        var compileTemplate = function(template, data) {
          var code = template,
              re = /{{([.]?\w+)}}/gi;
          code.replace(re, function(match, p) {
            code = code.replace(match, "` + data." + p + " + `");
          });
          var compile = new Function("data", "var out = `" + code + "`; return out");
          return compile(data);
        }

        // Utility: Create Elements Recursively For all Children
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        // Utility: Create Virtual DOM Instance
        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        // Build the DOM with $data
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            if(this.components[el.type])

            this.build(el.children);
          }
        }

        // Create Virtual DOM Object from Params
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        // Set any value in $data
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        // Get any value in $data
        this.get = function(key) {
          return this.$data[key];
        }

        // Make AJAX GET/POST requests
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        // Call a method defined in _methods
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
          this.build(this.dom.children);
        }

        // Default Directives
        var dirSelf = this;
        directives["m-if"] = function(el, val) {
          var evaluated = new Function("return " + val);
          if(!evaluated) {
            el.textContent = "";
          }
        }

        // Initialize
        this.createVirtualDOM(this.$el);
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<|endoftext|>


<commit_before>
describe('button text', function() {

  var settings = {};

  beforeEach(function() {
    affix('#cal');
    settings = {
      header: {
        left: 'prevYear,prev,today,next,nextYear',
        center: '',
        right: 'month,basicWeek,basicDay,agendaWeek,agendaDay'
      },
      buttonIcons: {
        prev: null,
        next: null,
        prevYear: null,
        nextYear: null
      }
    };
  });

  describe('when lang is default', function() {
    beforeEach(function() {
      $('#cal').fullCalendar(settings);
    });

    it('should contain the default text values', function() {
      expect($('.fc-button-today')).toContainText('today');

      expect($('.fc-button-next')).toContainText('next');
      expect($('.fc-button-nextYear')).toContainText('next year');
      expect($('.fc-button-prev')).toContainText('prev');
      expect($('.fc-button-prevYear')).toContainText('prev year');

      expect($('.fc-button-month')).toContainText('month');

      expect($('.fc-button-basicWeek')).toContainText('week');
      expect($('.fc-button-agendaWeek')).toContainText('week');

      expect($('.fc-button-basicDay')).toContainText('day');
      expect($('.fc-button-agendaDay')).toContainText('day');
    });
  });

  describe('when buttonText is specified', function() {
    beforeEach(function() {
      settings.buttonText = {
        prev: '<-',
        next: '->',
        prevYear: '<--',
        nextYear: '-->',
        today: 'tidei',
        month: 'mun',
        week: 'wiki',
        day: 'dei'
      }
      $('#cal').fullCalendar(settings);
    });

    it('should contain the specified text values', function() {
      expect($('.fc-button-today')).toContainText('tidei');

      expect($('.fc-button-next')).toContainText('->');
      expect($('.fc-button-nextYear')).toContainText('-->');
      expect($('.fc-button-prev')).toContainText('<-');
      expect($('.fc-button-prevYear')).toContainText('<--');

      expect($('.fc-button-month')).toContainText('mun');

      expect($('.fc-button-agendaDay')).toContainText('dei');
      expect($('.fc-button-agendaWeek')).toContainText('wiki');

      expect($('.fc-button-basicDay')).toContainText('dei');
      expect($('.fc-button-basicWeek')).toContainText('wiki');
    });
  });

  describe('when lang is not default', function() {

    beforeEach(function() {
      settings.lang = 'nl';
      $('#cal').fullCalendar(settings);
    });

    it('should contain the default text values', function() {
      expect($('.fc-button-today')).toContainText('Vandaag');

      expect($('.fc-button-month')).toContainText('Maand');

      expect($('.fc-button-basicWeek')).toContainText('Week');
      expect($('.fc-button-agendaWeek')).toContainText('Week');

      expect($('.fc-button-basicDay')).toContainText('Dag');
      expect($('.fc-button-agendaDay')).toContainText('Dag');
    });
  });

});
<commit_msg>Ensuring text is empty when icons are set (by default or explicitly) + using toHaveText matcher instead of toContainSet<commit_after>
describe('button text', function() {

  var settings = {};

  beforeEach(function() {
    affix('#cal');
    settings = {
      header: {
        left: 'prevYear,prev,today,next,nextYear',
        center: '',
        right: 'month,basicWeek,basicDay,agendaWeek,agendaDay'
      }
    };
  });

  describe('with buttonIcons', function() {
    describe('when lang is default', function() {
      it('should have no text', function() {
        expect($('.fc-button-next')).toHaveText('');
        expect($('.fc-button-nextYear')).toHaveText('');
        expect($('.fc-button-prev')).toHaveText('');
        expect($('.fc-button-prevYear')).toHaveText('');
      });
    });

    describe('when lang is not default', function() {
      it('should have no text', function() {
        settings.lang = 'nl';
        $('#cal').fullCalendar(settings);

        expect($('.fc-button-next')).toHaveText('');
        expect($('.fc-button-nextYear')).toHaveText('');
        expect($('.fc-button-prev')).toHaveText('');
        expect($('.fc-button-prevYear')).toHaveText('');
      });
    });

    describe('when buttonText is set to custom value', function() {
      it('should have no text', function() {
        settings.buttonText = {
          prev: '<-',
          next: '->',
          prevYear: '<--',
          nextYear: '-->',
          today: 'tidei',
          month: 'mun',
          week: 'wiki',
          day: 'dei'
        };
        $('#cal').fullCalendar(settings);

        expect($('.fc-button-next')).toHaveText('');
        expect($('.fc-button-nextYear')).toHaveText('');
        expect($('.fc-button-prev')).toHaveText('');
        expect($('.fc-button-prevYear')).toHaveText('');
      });
    });
  });
  describe('without buttonIcons', function() {
    beforeEach(function() {
      settings.buttonIcons = {
        prev: null,
        next: null,
        prevYear: null,
        nextYear: null
      };
    });

    describe('when lang is default', function() {
      beforeEach(function() {
        $('#cal').fullCalendar(settings);
      });

      it('should contain the default text values', function() {
        expect($('.fc-button-today')).toHaveText('today');

        expect($('.fc-button-next')).toHaveText('next');
        expect($('.fc-button-nextYear')).toHaveText('next year');
        expect($('.fc-button-prev')).toHaveText('prev');
        expect($('.fc-button-prevYear')).toHaveText('prev year');

        expect($('.fc-button-month')).toHaveText('month');

        expect($('.fc-button-basicWeek')).toHaveText('week');
        expect($('.fc-button-agendaWeek')).toHaveText('week');

        expect($('.fc-button-basicDay')).toHaveText('day');
        expect($('.fc-button-agendaDay')).toHaveText('day');
      });
    });

    describe('when buttonText is specified', function() {
      beforeEach(function() {
        settings.buttonText = {
          prev: '<-',
          next: '->',
          prevYear: '<--',
          nextYear: '-->',
          today: 'tidei',
          month: 'mun',
          week: 'wiki',
          day: 'dei'
        }
        $('#cal').fullCalendar(settings);
      });

      it('should contain the specified text values', function() {
        expect($('.fc-button-today')).toHaveText('tidei');

        expect($('.fc-button-next')).toHaveText('->');
        expect($('.fc-button-nextYear')).toHaveText('-->');
        expect($('.fc-button-prev')).toHaveText('<-');
        expect($('.fc-button-prevYear')).toHaveText('<--');

        expect($('.fc-button-month')).toHaveText('mun');

        expect($('.fc-button-agendaDay')).toHaveText('dei');
        expect($('.fc-button-agendaWeek')).toHaveText('wiki');

        expect($('.fc-button-basicDay')).toHaveText('dei');
        expect($('.fc-button-basicWeek')).toHaveText('wiki');
      });
    });

    describe('when lang is not default', function() {

      beforeEach(function() {
        settings.lang = 'nl';
        $('#cal').fullCalendar(settings);
      });

      it('should contain the default text values', function() {
        expect($('.fc-button-today')).toHaveText('Vandaag');

        expect($('.fc-button-month')).toHaveText('Maand');

        expect($('.fc-button-basicWeek')).toHaveText('Week');
        expect($('.fc-button-agendaWeek')).toHaveText('Week');

        expect($('.fc-button-basicDay')).toHaveText('Dag');
        expect($('.fc-button-agendaDay')).toHaveText('Dag');
      });
    });
  });
});
<|endoftext|>


<commit_before>import {List, Map} from 'immutable';
import {v4} from 'node-uuid';

export function createGame() {
    return Map({players: Map({})});
}

export function createPlayer(name) {
    return {name, id: v4(), hand: List.of()};
}

export function addPlayerToGame(game, player) {
    const players = game.get('players').set(player.id, player);
    return game.set('players', players);;
}<commit_msg>Extra semicolon gives me a sad<commit_after>import {List, Map} from 'immutable';
import {v4} from 'node-uuid';

export function createGame() {
    return Map({players: Map({})});
}

export function createPlayer(name) {
    return {name, id: v4(), hand: List.of()};
}

export function addPlayerToGame(game, player) {
    const players = game.get('players').set(player.id, player);
    return game.set('players', players);
}<|endoftext|>


<commit_before>function Eventi(){ return _.create.apply(this, arguments); }
var _ = {
    global: document || global,
    noop: function(){},
    slice: function(a, i){ return Array.prototype.slice.call(a, i); },
    copy: function(a, b, p) {
        for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; } }
    },
    resolveRE: /^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/,
    resolve: function(reference, context) {
        if (_.resolveRE.test(reference)) {
            context = context || global;
            return eval('context'+(reference.charAt(0) !== '[' ? '.'+reference : reference));
        }
    },

    create: function(type, copyThese) {
        var props = {};
        type = _.parse(type+'', props);
        _.copy(copyThese, props);
        if (!('bubbles' in props)) {
            props.bubbles = true;// must bubble by default
        }

        var event = new CustomEvent(type, props);
        delete props.bubbles;
        delete props.cancelable;
        delete props.detail;
        for (var prop in props) {
            event[_.prop(prop)] = props[prop];
        }
        event.stopImmediatePropagation = _.sIP;//TODO: consider prototype extension
        return event;
    },
    prop: function(prop){ return prop; },// only an extension hook
    sIP: function() {
        this.immediatePropagationStopped = true;
        (Event.prototype.stopImmediatePropagation || _.noop).call(this);
    },
    parse: function(type, props) {
        props.text = type;// save original
        _.properties.forEach(function(property) {
            type = type.replace(property[0], function() {
                return property[1].apply(props, arguments) || '';
            });
        });
        return type;
    },
    properties: [
/*nobubble*/[/^_/,          function(){ this.bubbles = false; }],
/*detail*/  [/\((.*)\)/,    function(m, val) {
                                try {
                                    this.detail = _.resolve(val) || JSON.parse(val);
                                } catch (e) {
                                    this.detail = val;
                                }
                            }],
/*tags*/    [/#(\w+)/g,     function(m, tag) {
                                (this.tags||(this.tags=[])).push(tag);
                                this[tag] = true;
                            }],
/*category*/[/^(\w+):/,     function(m, category){ this.category = category; }]//
    ],

    splitRE: / (?![^\(\)]*\))+/g,
    wrap: function(fn, expect, index) {
        return function(target) {
            var args = _.slice(arguments);
            // ensure target param precedes event text
            if (!target || typeof target === "string") {
                target = !this || this === Eventi ? _.global : this;
                args.unshift(target);
            }
            // convert to array of event text inputs
            index = index || 1;
            args[index] = (args[index]+'').split(_.splitRE);
            // gather ...data the old way
            if (args.length > expect) {
                args[expect] = args.slice(expect);
                args = args.slice(0, expect+1);
            }
            // call fn for each target
            var ret;
            if ('length' in target) {
                for (var i=0,m=target.length; i<m; i++) {
                    ret = fn.apply(args[0] = target[i], args);
                }
            } else {
                ret = fn.apply(target, args);
            }
            // be fluent
            return ret === undefined ? this : ret;
        };
    }
};
Eventi._ = _;
Eventi.fy = function(o, p, v) {
    for (p in Eventi) {
        if (p !== 'fy' && !(p in o) && typeof (v=Eventi[p]) === "function") {
            o[p] = v;
        }
    }
    return o;
};
<commit_msg>expose wrapper's event type index and make fy() functions writeable<commit_after>function Eventi(){ return _.create.apply(this, arguments); }
var _ = {
    global: document || global,
    noop: function(){},
    slice: function(a, i){ return Array.prototype.slice.call(a, i); },
    copy: function(a, b, p) {
        for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; } }
    },
    resolveRE: /^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/,
    resolve: function(reference, context) {
        if (_.resolveRE.test(reference)) {
            context = context || global;
            return eval('context'+(reference.charAt(0) !== '[' ? '.'+reference : reference));
        }
    },

    create: function(type, copyThese) {
        var props = {};
        type = _.parse(type+'', props);
        _.copy(copyThese, props);
        if (!('bubbles' in props)) {
            props.bubbles = true;// must bubble by default
        }

        var event = new CustomEvent(type, props);
        delete props.bubbles;
        delete props.cancelable;
        delete props.detail;
        for (var prop in props) {
            event[_.prop(prop)] = props[prop];
        }
        event.stopImmediatePropagation = _.sIP;//TODO: consider prototype extension
        return event;
    },
    prop: function(prop){ return prop; },// only an extension hook
    sIP: function() {
        this.immediatePropagationStopped = true;
        (Event.prototype.stopImmediatePropagation || _.noop).call(this);
    },
    parse: function(type, props) {
        props.text = type;// save original
        _.properties.forEach(function(property) {
            type = type.replace(property[0], function() {
                return property[1].apply(props, arguments) || '';
            });
        });
        return type;
    },
    properties: [
/*nobubble*/[/^_/,          function(){ this.bubbles = false; }],
/*detail*/  [/\((.*)\)/,    function(m, val) {
                                try {
                                    this.detail = _.resolve(val) || JSON.parse(val);
                                } catch (e) {
                                    this.detail = val;
                                }
                            }],
/*tags*/    [/#(\w+)/g,     function(m, tag) {
                                (this.tags||(this.tags=[])).push(tag);
                                this[tag] = true;
                            }],
/*category*/[/^(\w+):/,     function(m, category){ this.category = category; }]//
    ],

    splitRE: / (?![^\(\)]*\))+/g,
    wrap: function(fn, expect, index) {
        index = index || 1;
        var wrapper = function wrapper(target) {
            var args = _.slice(arguments);
            // ensure target param precedes event text
            if (!target || typeof target === "string") {
                target = !this || this === Eventi ? _.global : this;
                args.unshift(target);
            }
            // convert to array of event text inputs
            args[index] = (args[index]+'').split(_.splitRE);
            // gather ...data the old way
            if (args.length > expect) {
                args[expect] = args.slice(expect);
                args = args.slice(0, expect+1);
            }
            // call fn for each target
            var ret;
            if ('length' in target) {
                for (var i=0,m=target.length; i<m; i++) {
                    ret = fn.apply(args[0] = target[i], args);
                }
            } else {
                ret = fn.apply(target, args);
            }
            // be fluent
            return ret === undefined ? this : ret;
        };
        wrapper.index = index;
        return wrapper;
    }
};
Eventi._ = _;
(Eventi.fy = function fy(o) {
    for (var p in Eventi) {
        var fn = Eventi[p];
        if (typeof fn === "function" && !fn.utility) {
            Object.defineProperty(o, p, {value:fn, writable:true, configurable:true});
        }
    }
    return o;
}).utility = true;
<|endoftext|>


<commit_before>'use strict';

/**
 * A collection of core utility functions.
 * @const
 */
class core {
  /**
   * When defining a class Foo with an abstract method bar(), you can do:
   * Foo.prototype.bar = core.abstractMethod
   *
   * Now if a subclass of Foo fails to override bar(), an error will be thrown
   * when bar() is invoked.
   *
   * @type {!Function}
   * @throws {Error} when invoked to indicate the method should be overridden.
   */
  static abstractMethod() {
    throw Error('Unimplemented abstract method');
  }

  /**
   * Loops constructor super classes collecting its properties values. If
   * property is not available on the super class `undefined` will be
   * collected as value for the class hierarchy position. Must be used with
   * classes created using `core.inherits`.
   * @param {!function()} constructor Class constructor.
   * @param {string} propertyName Property name to be collected.
   * @return {Array.<*>} Array of collected values.
   * TODO(*): Rethink superclass loop.
   */
  static collectSuperClassesProperty(constructor, propertyName) {
    var propertyValues = [constructor[propertyName]];

    if (constructor.superClass_) {
      while (constructor.superClass_) {
        constructor = constructor.superClass_.constructor;
        propertyValues.push(constructor[propertyName]);
      }
    }
    else {
      while (!constructor.__proto__.isPrototypeOf(Function)) {
        constructor = constructor.__proto__;
        propertyValues.push(constructor[propertyName]);
      }
    }
    return propertyValues;
  }

  /**
   * Gets an unique id. If `opt_object` argument is passed, the object is
   * mutated with an unique id. Consecutive calls with the same object
   * reference won't mutate the object again, instead the current object uid
   * returns. See {@link core.UID_PROPERTY}.
   * @type {opt_object} Optional object to be mutated with the uid. If not
   *     specified this method only returns the uid.
   * @throws {Error} when invoked to indicate the method should be overridden.
   */
  static getUid(opt_object) {
    if (opt_object) {
      return opt_object[core.UID_PROPERTY] ||
        (opt_object[core.UID_PROPERTY] = core.uniqueIdCounter_++);
    }
    return core.uniqueIdCounter_++;
  }

  /**
   * Inherits the prototype methods from one constructor into another.
   *
   * Usage:
   *

   * function ParentClass(a, b) { }
   * ParentClass.prototype.foo = function(a) { }
   *
   * function ChildClass(a, b, c) {
   *   core.base(this, a, b);
   * }
   * core.inherits(ChildClass, ParentClass);
   *
   * var child = new ChildClass('a', 'b', 'c');
   * child.foo();
   *

   *
   * @param {Function} childCtor Child class.
   * @param {Function} parentCtor Parent class.
   */
  static inherits(childCtor, parentCtor) {
    function TempCtor() {
    }
    TempCtor.prototype = parentCtor.prototype;
    childCtor.superClass_ = parentCtor.prototype;
    childCtor.prototype = new TempCtor();
    childCtor.prototype.constructor = childCtor;

    /**
     * Calls superclass constructor/method.
     *
     * This function is only available if you use core.inherits to express
     * inheritance relationships between classes.
     *
     * @param {!object} me Should always be "this".
     * @param {string} methodName The method name to call. Calling superclass
     *     constructor can be done with the special string 'constructor'.
     * @param {...*} var_args The arguments to pass to superclass
     *     method/constructor.
     * @return {*} The return value of the superclass method/constructor.
     */
    childCtor.base = function(me, methodName) {
      var args = Array.prototype.slice.call(arguments, 2);
      return parentCtor.prototype[methodName].apply(me, args);
    };
  }

  /**
   * The identity function. Returns its first argument.
   * @param {*=} opt_returnValue The single value that will be returned.
   * @return {?} The first argument.
   */
  static identityFunction(opt_returnValue) {
    return opt_returnValue;
  }

  /**
   * Returns true if the specified value is a boolean.
   * @param {?} val Variable to test.
   * @return {boolean} Whether variable is boolean.
   */
  static isBoolean(val) {
    return typeof val === 'boolean';
  }

  /**
   * Returns true if the specified value is not undefined.
   * @param {?} val Variable to test.
   * @return {boolean} Whether variable is defined.
   */
  static isDef(val) {
    return val !== undefined;
  }

  /**
   * Returns true if value is not undefined or null.
   * @param {*} val
   * @return {Boolean}
   */
  static isDefAndNotNull(val) {
    return core.isDef(val) && !core.isNull(val);
  }

  /**
   * Returns true if value is a dom element.
   * @param {*} val
   * @return {Boolean}
   */
  static isElement(val) {
    return val && typeof val === 'object' && val.nodeType === 1;
  }

  /**
   * Returns true if the specified value is a function.
   * @param {?} val Variable to test.
   * @return {boolean} Whether variable is a function.
   */
  static isFunction(val) {
    return typeof val === 'function';
  }

  /**
   * Returns true if value is null.
   * @param {*} val
   * @return {Boolean}
   */
  static isNull(val) {
    return val === null;
  }

  /**
   * Returns true if the specified value is an object. This includes arrays
   * and functions.
   * @param {?} val Variable to test.
   * @return {boolean} Whether variable is an object.
   */
  static isObject(val) {
    var type = typeof val;
    return type === 'object' && val !== null || type === 'function';
  }

  /**
   * Returns true if value is a string.
   * @param {*} val
   * @return {Boolean}
   */
  static isString(val) {
    return typeof val === 'string';
  }

  /**
   * Merges the values of a static property a class with the values of that
   * property for all its super classes, and stores it as a new static
   * property of that class. If the static property already existed, it won't
   * be recalculated.
   * @param {!function()} constructor Class constructor.
   * @param {string} propertyName Property name to be collected.
   * @param {function(*, *):*=} opt_mergeFn Function that receives an array filled
   *   with the values of the property for the current class and all its super classes.
   *   Should return the merged value to be stored on the current class.
   * @return {*} The value of the merged property.
   */
  static mergeSuperClassesProperty(constructor, propertyName, opt_mergeFn) {
    var mergedName = propertyName + '_MERGED';
    if (constructor[mergedName]) {
      return constructor[mergedName];
    }

    var merged = core.collectSuperClassesProperty(constructor, propertyName);
    if (opt_mergeFn) {
      merged = opt_mergeFn(merged);
    }
    constructor[mergedName] = merged;
    return constructor[mergedName];
  }

  /**
   * Null function used for default values of callbacks, etc.
   * @return {void} Nothing.
   */
  static nullFunction() {

  }
}

/**
 * Unique id property prefix.
 * @type {String}
 * @protected
 */
core.UID_PROPERTY = 'core_' + ((Math.random() * 1e9) >>> 0);

/**
 * Counter for unique id.
 * @type {Number}
 * @private
 */
core.uniqueIdCounter_ = 1;

export default core;
<commit_msg>Fixes static merged values due to transpilation static inheritance<commit_after>'use strict';

/**
 * A collection of core utility functions.
 * @const
 */
class core {
  /**
   * When defining a class Foo with an abstract method bar(), you can do:
   * Foo.prototype.bar = core.abstractMethod
   *
   * Now if a subclass of Foo fails to override bar(), an error will be thrown
   * when bar() is invoked.
   *
   * @type {!Function}
   * @throws {Error} when invoked to indicate the method should be overridden.
   */
  static abstractMethod() {
    throw Error('Unimplemented abstract method');
  }

  /**
   * Loops constructor super classes collecting its properties values. If
   * property is not available on the super class `undefined` will be
   * collected as value for the class hierarchy position. Must be used with
   * classes created using `core.inherits`.
   * @param {!function()} constructor Class constructor.
   * @param {string} propertyName Property name to be collected.
   * @return {Array.<*>} Array of collected values.
   * TODO(*): Rethink superclass loop.
   */
  static collectSuperClassesProperty(constructor, propertyName) {
    var propertyValues = [constructor[propertyName]];

    if (constructor.superClass_) {
      while (constructor.superClass_) {
        constructor = constructor.superClass_.constructor;
        propertyValues.push(constructor[propertyName]);
      }
    }
    else {
      while (!constructor.__proto__.isPrototypeOf(Function)) {
        constructor = constructor.__proto__;
        propertyValues.push(constructor[propertyName]);
      }
    }
    return propertyValues;
  }

  /**
   * Gets an unique id. If `opt_object` argument is passed, the object is
   * mutated with an unique id. Consecutive calls with the same object
   * reference won't mutate the object again, instead the current object uid
   * returns. See {@link core.UID_PROPERTY}.
   * @type {opt_object} Optional object to be mutated with the uid. If not
   *     specified this method only returns the uid.
   * @throws {Error} when invoked to indicate the method should be overridden.
   */
  static getUid(opt_object) {
    if (opt_object) {
      return opt_object[core.UID_PROPERTY] ||
        (opt_object[core.UID_PROPERTY] = core.uniqueIdCounter_++);
    }
    return core.uniqueIdCounter_++;
  }

  /**
   * Inherits the prototype methods from one constructor into another.
   *
   * Usage:
   *

   * function ParentClass(a, b) { }
   * ParentClass.prototype.foo = function(a) { }
   *
   * function ChildClass(a, b, c) {
   *   core.base(this, a, b);
   * }
   * core.inherits(ChildClass, ParentClass);
   *
   * var child = new ChildClass('a', 'b', 'c');
   * child.foo();
   *

   *
   * @param {Function} childCtor Child class.
   * @param {Function} parentCtor Parent class.
   */
  static inherits(childCtor, parentCtor) {
    function TempCtor() {
    }
    TempCtor.prototype = parentCtor.prototype;
    childCtor.superClass_ = parentCtor.prototype;
    childCtor.prototype = new TempCtor();
    childCtor.prototype.constructor = childCtor;

    /**
     * Calls superclass constructor/method.
     *
     * This function is only available if you use core.inherits to express
     * inheritance relationships between classes.
     *
     * @param {!object} me Should always be "this".
     * @param {string} methodName The method name to call. Calling superclass
     *     constructor can be done with the special string 'constructor'.
     * @param {...*} var_args The arguments to pass to superclass
     *     method/constructor.
     * @return {*} The return value of the superclass method/constructor.
     */
    childCtor.base = function(me, methodName) {
      var args = Array.prototype.slice.call(arguments, 2);
      return parentCtor.prototype[methodName].apply(me, args);
    };
  }

  /**
   * The identity function. Returns its first argument.
   * @param {*=} opt_returnValue The single value that will be returned.
   * @return {?} The first argument.
   */
  static identityFunction(opt_returnValue) {
    return opt_returnValue;
  }

  /**
   * Returns true if the specified value is a boolean.
   * @param {?} val Variable to test.
   * @return {boolean} Whether variable is boolean.
   */
  static isBoolean(val) {
    return typeof val === 'boolean';
  }

  /**
   * Returns true if the specified value is not undefined.
   * @param {?} val Variable to test.
   * @return {boolean} Whether variable is defined.
   */
  static isDef(val) {
    return val !== undefined;
  }

  /**
   * Returns true if value is not undefined or null.
   * @param {*} val
   * @return {Boolean}
   */
  static isDefAndNotNull(val) {
    return core.isDef(val) && !core.isNull(val);
  }

  /**
   * Returns true if value is a dom element.
   * @param {*} val
   * @return {Boolean}
   */
  static isElement(val) {
    return val && typeof val === 'object' && val.nodeType === 1;
  }

  /**
   * Returns true if the specified value is a function.
   * @param {?} val Variable to test.
   * @return {boolean} Whether variable is a function.
   */
  static isFunction(val) {
    return typeof val === 'function';
  }

  /**
   * Returns true if value is null.
   * @param {*} val
   * @return {Boolean}
   */
  static isNull(val) {
    return val === null;
  }

  /**
   * Returns true if the specified value is an object. This includes arrays
   * and functions.
   * @param {?} val Variable to test.
   * @return {boolean} Whether variable is an object.
   */
  static isObject(val) {
    var type = typeof val;
    return type === 'object' && val !== null || type === 'function';
  }

  /**
   * Returns true if value is a string.
   * @param {*} val
   * @return {Boolean}
   */
  static isString(val) {
    return typeof val === 'string';
  }

  /**
   * Merges the values of a static property a class with the values of that
   * property for all its super classes, and stores it as a new static
   * property of that class. If the static property already existed, it won't
   * be recalculated.
   * @param {!function()} constructor Class constructor.
   * @param {string} propertyName Property name to be collected.
   * @param {function(*, *):*=} opt_mergeFn Function that receives an array filled
   *   with the values of the property for the current class and all its super classes.
   *   Should return the merged value to be stored on the current class.
   * @return {*} The value of the merged property.
   */
  static mergeSuperClassesProperty(constructor, propertyName, opt_mergeFn) {
    var mergedName = propertyName + '_MERGED';
    if (constructor.hasOwnProperty(mergedName)) {
      return constructor[mergedName];
    }

    var merged = core.collectSuperClassesProperty(constructor, propertyName);
    if (opt_mergeFn) {
      merged = opt_mergeFn(merged);
    }
    constructor[mergedName] = merged;
    return constructor[mergedName];
  }

  /**
   * Null function used for default values of callbacks, etc.
   * @return {void} Nothing.
   */
  static nullFunction() {

  }
}

/**
 * Unique id property prefix.
 * @type {String}
 * @protected
 */
core.UID_PROPERTY = 'core_' + ((Math.random() * 1e9) >>> 0);

/**
 * Counter for unique id.
 * @type {Number}
 * @private
 */
core.uniqueIdCounter_ = 1;

export default core;
<|endoftext|>


<commit_before>;(function(window, undefined) {
  var supportHashChange = 'onhashchange' in window;

  function getHash() {
    if (!supportHashChange) {
      return window.location.href.replace(/^[^#]#?(.*)$/, '$1');
    }
    var hash = window.location.hash;
    if (hash.charAt(0) === '#') {
      hash = hash.substr(1);
    }
    if (hash === '') hash = '/';
    return hash;
  }

  function onHashChange(cbk) {
    var hash = getHash();
    cbk.call(cbk, hash);
    if (supportHashChange) {
      window.onhashchange = function() {
        var hash = getHash();
        cbk.call(cbk, hash);
      };
      return;
    }
    window.___href___ = window.location.href;
    window.setInterval(function() {
      if (window.___href___ !== window.location.href) {
        window.__href__ = window.location.href;
        var hash = getHash();
        cbk.call(cbk, hash);
      }
    }, 50);
  }

  function getRequest(hash) {
    var params = {},
        kvPair = [],
        partList,
        path,
        query,
        part,
        key,
        value,
        index;
    if (hash.charAt(0) === '#') {
      hash = hash.substr(1);
    }
    index = hash.indexOf('?');
    if (index < 0) {
      return {
        path: hash,
        params: params
      };
    }
    path = hash.substr(0, index);
    query = hash.substr(index + 1);
    partList = query.split('&');

    for (var i = 0, l = partList.length; i < l; i++) {
      part = partList[i];
      kvPair = part.split('=');
      switch (kvPair.length) {
        case 1:
          key = kvPair[0];
          value = null;
          break;
        case 2:
          key = kvPair[0];
          value = kvPair[1];
          break;
        default:
          continue;
      }
      params[key] = value;
    }

    return {
      path: path,
      params: params,
      isCurrent: function() {
        return getHash() === path;
      }
    };
  }

  window.router = function(routerPairs) {
    onHashChange(function(hash) {
      var request = getRequest(hash),
          path = request.path,
          args = [request],
          match,
          pair,
          router,
          handler;

      if (typeof path !== 'string') {
        return;
      }

      for (var i = 0, l = routerPairs.length; i < l; i++) {
        pair = routerPairs[i];
        router = pair[0];
        handler = pair[1];
        if (typeof router === 'string') {
          router = new RegExp(router);
        }
        match = path.match(router);
        if (!match) {
          continue;
        }
        args.push.apply(args, match.slice(1));
        handler.apply(handler, args);
        break;
      }
    });
  };
})(window);
<commit_msg>fix bug<commit_after>;(function(window, undefined) {
  var supportHashChange = 'onhashchange' in window;

  function getHash() {
    if (!supportHashChange) {
      return window.location.href.replace(/^[^#]#?(.*)$/, '$1');
    }
    var hash = window.location.hash;
    if (hash.charAt(0) === '#') {
      hash = hash.substr(1);
    }
    if (hash === '') hash = '/';
    return hash;
  }

  function onHashChange(cbk) {
    var hash = getHash();
    cbk.call(cbk, hash);
    if (supportHashChange) {
      window.onhashchange = function() {
        var hash = getHash();
        cbk.call(cbk, hash);
      };
      return;
    }
    window.___href___ = window.location.href;
    window.setInterval(function() {
      if (window.___href___ !== window.location.href) {
        window.__href__ = window.location.href;
        var hash = getHash();
        cbk.call(cbk, hash);
      }
    }, 50);
  }

  function getRequest(hash) {
    var params = {},
        kvPair = [],
        partList,
        path,
        query,
        part,
        key,
        value,
        index;
    if (hash.charAt(0) === '#') {
      hash = hash.substr(1);
    }
    index = hash.indexOf('?');
    if (index < 0) {
      return {
        path: hash,
        params: params
      };
    }
    path = hash.substr(0, index);
    query = hash.substr(index + 1);
    partList = query.split('&');

    for (var i = 0, l = partList.length; i < l; i++) {
      part = partList[i];
      kvPair = part.split('=');
      switch (kvPair.length) {
        case 1:
          key = kvPair[0];
          value = null;
          break;
        case 2:
          key = kvPair[0];
          value = kvPair[1];
          break;
        default:
          continue;
      }
      params[key] = value;
    }

    return {
      path: path,
      params: params
    };
  }

  window.router = function(routerPairs) {
    onHashChange(function(hash) {
      var request = getRequest(hash),
          path = request.path,
          args = [request],
          match,
          pair,
          router,
          handler;

      if (typeof path !== 'string') {
        return;
      }

      for (var i = 0, l = routerPairs.length; i < l; i++) {
        pair = routerPairs[i];
        router = pair[0];
        handler = pair[1];
        if (typeof router === 'string') {
          router = new RegExp(router);
        }
        match = path.match(router);
        if (!match) {
          continue;
        }
        args.push.apply(args, match.slice(1));
        handler.apply(handler, args);
        break;
      }
    });
  };
})(window);
<|endoftext|>


<commit_before>/**
 * The Core module provides main functionalities of Editable.JS API.
 *
 * @module core
 */

(function(exports, undefined) {
  'use strict';

  var EVENTS = [
    /**
     * The focus event is triggered when an element gains focus.
     *
     * @event focus
     * @param {HTMLElement} element The element triggering the event.
     */
    'focus',

    /**
     * The blur event is triggered when an element looses focus.
     *
     * @event blur
     * @param {HTMLElement} element The element triggering the event.
     */
    'blur',

    /**
     * The flow event is triggered when the user starts typing or pause typing.
     *
     * @event flow
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} action The flow action: "start" or "pause".
     */
    'flow',

    /**
     * The selection event is triggered after the user has selected some
     * content.
     *
     * @event selection
     * @param {HTMLElement} element The element triggering the event.
     * @param {Selection} selection The actual Selection object.
     */
    'selection',

    /**
     * The cursor event is triggered after cursor position has changed.
     *
     * @event cursor
     * @param {HTMLElement} element The element triggering the event.
     * @param {Cursor} cursor The actual Cursor object.
     */
    'cursor',

    /**
     * The insert event is triggered when a new block should be inserted. This
     * happens when ENTER key is pressed at the beginning of a block (should
     * insert before) or at the end of a block (should insert after).
     *
     * @event insert
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} direction The insert direction: "before" or "after".
     */
    'insert',

    /**
     * The split event is triggered when a block should be splitted into two
     * blocks. This happens when ENTER is pressed within a non-empty block.
     *
     * @event split
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} before The HTML string before the split.
     * @param {String} after The HTML string after the split.
     */
    'split',

    /**
     * The merge event is triggered when two needs to be merged. This happens
     * when BACKSPACE is pressed at the beginning of a block (should merge with
     * the preceeding block) or DEL is pressed at the end of a block (should
     * merge with the following block).
     *
     * @event merge
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} direction The merge direction: "before" or "after".
     */
    'merge',

    /**
     * The empty event is triggered when a block is emptied.
     *
     * @event empty
     * @param {HTMLElement} element The element triggering the event.
     */
    'empty',

    /**
     * The switch event is triggered when the user switches to another block.
     * This happens when TAB is pressed (move one block after) or SHIFT+TAB
     * is pressed (move one block before).
     *
     * @event switch
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} direction The switch direction: "before" or "after".
     */
    'switch',

    /**
     * The move event is triggered when the user moves a selection in a block.
     * This happens when the user selects some (or all) content in a block and
     * an ARROW key is pressed (up: drag before, down: drag after).
     *
     * @event move
     * @param {HTMLElement} element The element triggering the event.
     * @param {Selection} selection The actual Selection object.
     * @param {String} direction The move direction: "before" or "after".
     */
    'move',

    /**
     * The clipboard event is triggered when the user copies, pastes or cuts
     * a selection within a block.
     *
     * @event clipboard
     * @param {HTMLElement} element The element triggering the event.
     * @param {Selection} selection The actual Selection object.
     * @param {String} action The clipboard action: "copy", "paste", "cut".
     */
    'cliboard'
  ];

  var isInitialized = false;

  /**
   * @class Editable
   * @static
   */
  exports.Editable = {
    /**
     * Initializes the API.
     *
     * @method init
     * @param {Object} [options={}] Configuration options override.
     * @static
     * @chainable
     */
    init: function(options) {
      if (isInitialized) { return; }
      isInitialized = true;

      this.events.setup();

      return this;
    },

    /**
     * Adds the API to the given target elements.
     *
     * @method add
     * @param {HTMLElement|Array(HTMLElement)|String} target A HTMLElement, an
     *    array of HTMLElement or a query selector representing the target where
     *    the API should be added on.
     * @param {Object} [options={}] Configuration options override.
     * @static
     * @chainable
     */
    add: function(target, options) {
      $(target).attr('contenteditable', true);
      $(target).addClass('-js-editable');
      // todo: check css whitespace settings
      // todo: much much more obviously...
      return this;
    },

    /**
     * Removes the API from the given target elements.
     *
     * @method remove
     * @param {HTMLElement|Array(HTMLElement)|String} target A HTMLElement, an
     *    array of HTMLElement or a query selector representing the target where
     *    the API should be removed from.
     * @static
     * @chainable
     */
    remove: function(target) {
      $(target).removeAttr('contenteditable');
      $(target).removeClass('-js-editable');
      return this;
    },

    /**
     * Subscribe a callback function to a custom event fired by the API.
     *
     * @method on
     * @param {String} event The name of the event.
     * @param {Function} handler The callback to execute in response to the
     *     event.
     * @static
     * @chainable
     */
    on: function(event, handler) {
      return this;
    },

    /**
     * Unsubscribe a callback function from a custom event fired by the API.
     *
     * @method off
     * @param {String} event The name of the event.
     * @param {Function|Boolean} handler The callback to remove from the
     *     event or the special value false to remove all callbacks.
     * @static
     * @chainable
     */
    off: function(event, handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/focus:event"}}{{/crossLink}}
     * event.
     *
     * @method focus
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    focus: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/blur:event"}}{{/crossLink}}
     * event.
     *
     * @method blur
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    blur: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/flow:event"}}{{/crossLink}}
     * event.
     *
     * @method flow
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    flow: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/selection:event"}}{{/crossLink}}
     * event.
     *
     * @method selection
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    selection: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/cursor:event"}}{{/crossLink}}
     * event.
     *
     * @method cursor
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    cursor: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/insert:event"}}{{/crossLink}}
     * event.
     *
     * @method insert
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    insert: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/split:event"}}{{/crossLink}}
     * event.
     *
     * @method split
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    split: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/merge:event"}}{{/crossLink}}
     * event.
     *
     * @method merge
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    merge: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/empty:event"}}{{/crossLink}}
     * event.
     *
     * @method empty
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    empty: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/switch:event"}}{{/crossLink}}
     * event.
     *
     * @method switch
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    'switch': function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/move:event"}}{{/crossLink}}
     * event.
     *
     * @method move
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    move: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/clipboard:event"}}{{/crossLink}}
     * event.
     *
     * @method clipboard
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    clipboard: function(handler) {
      return this;
    }
  };
})(window);
<commit_msg>Detect jQuery and if not present rely on own library (to be implemented). Editable.$ will be the alias<commit_after>/**
 * The Core module provides main functionalities of Editable.JS API.
 *
 * @module core
 */

(function(exports, undefined) {
  'use strict';

  var EVENTS = [
    /**
     * The focus event is triggered when an element gains focus.
     *
     * @event focus
     * @param {HTMLElement} element The element triggering the event.
     */
    'focus',

    /**
     * The blur event is triggered when an element looses focus.
     *
     * @event blur
     * @param {HTMLElement} element The element triggering the event.
     */
    'blur',

    /**
     * The flow event is triggered when the user starts typing or pause typing.
     *
     * @event flow
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} action The flow action: "start" or "pause".
     */
    'flow',

    /**
     * The selection event is triggered after the user has selected some
     * content.
     *
     * @event selection
     * @param {HTMLElement} element The element triggering the event.
     * @param {Selection} selection The actual Selection object.
     */
    'selection',

    /**
     * The cursor event is triggered after cursor position has changed.
     *
     * @event cursor
     * @param {HTMLElement} element The element triggering the event.
     * @param {Cursor} cursor The actual Cursor object.
     */
    'cursor',

    /**
     * The insert event is triggered when a new block should be inserted. This
     * happens when ENTER key is pressed at the beginning of a block (should
     * insert before) or at the end of a block (should insert after).
     *
     * @event insert
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} direction The insert direction: "before" or "after".
     */
    'insert',

    /**
     * The split event is triggered when a block should be splitted into two
     * blocks. This happens when ENTER is pressed within a non-empty block.
     *
     * @event split
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} before The HTML string before the split.
     * @param {String} after The HTML string after the split.
     */
    'split',

    /**
     * The merge event is triggered when two needs to be merged. This happens
     * when BACKSPACE is pressed at the beginning of a block (should merge with
     * the preceeding block) or DEL is pressed at the end of a block (should
     * merge with the following block).
     *
     * @event merge
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} direction The merge direction: "before" or "after".
     */
    'merge',

    /**
     * The empty event is triggered when a block is emptied.
     *
     * @event empty
     * @param {HTMLElement} element The element triggering the event.
     */
    'empty',

    /**
     * The switch event is triggered when the user switches to another block.
     * This happens when TAB is pressed (move one block after) or SHIFT+TAB
     * is pressed (move one block before).
     *
     * @event switch
     * @param {HTMLElement} element The element triggering the event.
     * @param {String} direction The switch direction: "before" or "after".
     */
    'switch',

    /**
     * The move event is triggered when the user moves a selection in a block.
     * This happens when the user selects some (or all) content in a block and
     * an ARROW key is pressed (up: drag before, down: drag after).
     *
     * @event move
     * @param {HTMLElement} element The element triggering the event.
     * @param {Selection} selection The actual Selection object.
     * @param {String} direction The move direction: "before" or "after".
     */
    'move',

    /**
     * The clipboard event is triggered when the user copies, pastes or cuts
     * a selection within a block.
     *
     * @event clipboard
     * @param {HTMLElement} element The element triggering the event.
     * @param {Selection} selection The actual Selection object.
     * @param {String} action The clipboard action: "copy", "paste", "cut".
     */
    'cliboard'
  ];

  var isInitialized = false;

  var $ = exports.jQuery || function() {
    throw new Error('jQuery-like library not yet implemented');
  };

  /**
   * @class Editable
   * @static
   */
  exports.Editable = {
    $: $,

    /**
     * Initializes the API.
     *
     * @method init
     * @param {Object} [options={}] Configuration options override.
     * @static
     * @chainable
     */
    init: function(options) {
      if (isInitialized) { return; }
      isInitialized = true;

      this.events.setup();

      return this;
    },

    /**
     * Adds the API to the given target elements.
     *
     * @method add
     * @param {HTMLElement|Array(HTMLElement)|String} target A HTMLElement, an
     *    array of HTMLElement or a query selector representing the target where
     *    the API should be added on.
     * @param {Object} [options={}] Configuration options override.
     * @static
     * @chainable
     */
    add: function(target, options) {
      $(target).attr('contenteditable', true);
      $(target).addClass('-js-editable');
      // todo: check css whitespace settings
      // todo: much much more obviously...
      return this;
    },

    /**
     * Removes the API from the given target elements.
     *
     * @method remove
     * @param {HTMLElement|Array(HTMLElement)|String} target A HTMLElement, an
     *    array of HTMLElement or a query selector representing the target where
     *    the API should be removed from.
     * @static
     * @chainable
     */
    remove: function(target) {
      $(target).removeAttr('contenteditable');
      $(target).removeClass('-js-editable');
      return this;
    },

    /**
     * Subscribe a callback function to a custom event fired by the API.
     *
     * @method on
     * @param {String} event The name of the event.
     * @param {Function} handler The callback to execute in response to the
     *     event.
     * @static
     * @chainable
     */
    on: function(event, handler) {
      return this;
    },

    /**
     * Unsubscribe a callback function from a custom event fired by the API.
     *
     * @method off
     * @param {String} event The name of the event.
     * @param {Function|Boolean} handler The callback to remove from the
     *     event or the special value false to remove all callbacks.
     * @static
     * @chainable
     */
    off: function(event, handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/focus:event"}}{{/crossLink}}
     * event.
     *
     * @method focus
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    focus: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/blur:event"}}{{/crossLink}}
     * event.
     *
     * @method blur
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    blur: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/flow:event"}}{{/crossLink}}
     * event.
     *
     * @method flow
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    flow: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/selection:event"}}{{/crossLink}}
     * event.
     *
     * @method selection
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    selection: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/cursor:event"}}{{/crossLink}}
     * event.
     *
     * @method cursor
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    cursor: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/insert:event"}}{{/crossLink}}
     * event.
     *
     * @method insert
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    insert: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/split:event"}}{{/crossLink}}
     * event.
     *
     * @method split
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    split: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/merge:event"}}{{/crossLink}}
     * event.
     *
     * @method merge
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    merge: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/empty:event"}}{{/crossLink}}
     * event.
     *
     * @method empty
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    empty: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/switch:event"}}{{/crossLink}}
     * event.
     *
     * @method switch
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    'switch': function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/move:event"}}{{/crossLink}}
     * event.
     *
     * @method move
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    move: function(handler) {
      return this;
    },

    /**
     * Subscribe to the {{#crossLink "Editable/clipboard:event"}}{{/crossLink}}
     * event.
     *
     * @method clipboard
     * @param {Function} handler The callback to execute in response to the
     *   event.
     * @static
     * @chainable
     */
    clipboard: function(handler) {
      return this;
    }
  };
})(window);
<|endoftext|>


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

var OPC = new require('./opc')

var fc = new OPC('localhost', 7890);

var sp = require('serialport');
var SerialPort = require('serialport').SerialPort;
var portName = "/dev/ttyArduino";

var runState = "down";

var BRIGHTEN = 100;
var DARKEN = 101;

var BRIGHTEN_S = 200;
var DARKEN_S = 201;

var SWEEP = 300;

var SENSORTEST = false;

var sensorCount = 8;

var pixelLength = 300;
var particleCount = 400;

var environmentLength = 3000;

var defaultScale = 7;

var pixels = [];
var particles = [];

var lookup = [];

var coordT = [];

var dist_v = [];

var timerIdle = true;

// MAIN COMPUTER PROGRAM!

initialize();
setInterval(evaluate, 30);

function initialize() {

	if ( process.argv.length > 2 ) {
			if ( process.argv[2] == "sensorTest" ) {
				SENSORTEST = true;
			}
	}

	serialport = new SerialPort(portName , { baudrate : 115200, parser: sp.parsers.readline("|") }, false);
	openPort();

	for ( var i=0; i<8; i++ ) { dist_v[i] = 0; }

	// Init coord lookup
	var coordRatio = ( ( pixelLength ) / environmentLength );
	for ( var t=0; t<environmentLength+1; t++ ){ coordT[t] = Math.floor( t * coordRatio ); }

	// Init scaling lookup

	lookup[defaultScale] = { 'environmentLength': defaultScale * pixelLength, 'positions': [] };

	for ( var p=0; p < lookup[defaultScale].environmentLength; p++ ){
		var div = p / defaultScale;
		var calc = {
			'left': Math.floor( div ),
			'right': Math.floor( div ) + 1,
			'wleft': 1 - ( div ) % 1,
			'wright': ( div ) % 1
		};

		lookup[defaultScale].positions.push( calc );
	}

	// Init pixel array
	for ( var i=0; i<pixelLength + 3; i++ ) { pixels.push({ 'r':0, 'g':0, 'b':0 }); }
}

function evaluate() {
	if ( runState == "open") {
  	updateParticles();
  	evaluateEnvironment();
  	draw();
	} else {
		if ( timerIdle ) {
			setTimeout( function() {
				openPort();
				timerIdle = true;
			}, 5000);
			timerIdle = false;
		}
	}
}

function updateParticles() {
  for ( var i=0; i<particles.length; i++ ){
		particles[i].update( i );
  }
}

function evaluateEnvironment() {
	// fill particle list
	if ( particles.length < particleCount ) {
		particles.push( getRandParticle() );
	}

	for ( var s=0; s < sensorCount; s++ ) {
//			if ( dist_v[s] > 0 && dist_v[s] < 50 ) {
//				particles.push( getProximateParticle( s, dist_v[s] ));
//			}
	}
}

function draw() {
  if ( runState == "open" ) {

		// Initialize
		initAllPixels( 20, 20, 40 );

	  // Compose
	  for ( var i=0; i<particles.length; i++ ){ particles[i].method(); }

	  // Render
	//	try {
	    for ( var i=0; i<pixels.length; i++ ){
	      fc.setPixel( pixels.length-i, pixels[i].red, pixels[i].green, pixels[i].blue );
	    }
	    fc.writePixels();
	//	} catch( err ) {
	//		console.log('fc write err: ' + error);
	//		runState = "fc write err";
	//	}

  } else {
    // display runstate graphics

  }
}

// update methods

function update_Discrete( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > environmentLength ) {
		particles[i] = getRandParticle();
	}
}

function update_Smooth( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > lookup[this.scale].environmentLength-1 ) {
    particles[i] = getRandParticle();
	}
}

function update_Glower( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > lookup[this.scale].environmentLength-1 ) {
    particles[i] = getRandParticle();
	}
}

// draw methods

function method_Brighten() {
	var dest = coordT[this.position];

	pixels[dest].red += this.color.r;
	pixels[dest].green += this.color.g;
	pixels[dest].blue += this.color.b;
}

function method_Darken() {
	var dest = coordT[this.position];

	pixels[dest].red -= this.color.r;
	pixels[dest].green -= this.color.g;
	pixels[dest].blue -= this.color.b;
}

function method_BrightenSmooth() {
	var pcalc = lookup[this.scale].positions[this.position];
	methodValueSmooth( this, pcalc );
}

function method_DarkenSmooth() {
	var pcalc = lookup[this.scale].positions[this.position];
	if ( this.method == DARKEN_S ) {
		pcalc.wleft *= -1;
		pcalc.wright *= -1;
	}
	methodValueSmooth( this, pcalc );
}

function methodValueSmooth( tgt, pcalc ){
	pixels[pcalc.left].red += tgt.color.r * pcalc.wleft;
	pixels[pcalc.left].green += tgt.color.g * pcalc.wleft;
	pixels[pcalc.left].blue += tgt.color.b * pcalc.wleft;

	pixels[pcalc.right].red += tgt.color.r * pcalc.wright;
	pixels[pcalc.right].green += tgt.color.g * pcalc.wright;
	pixels[pcalc.right].blue += tgt.color.b * pcalc.wright;
}

function method_Sweep() {
	var pcalc = lookup[this.scale].positions[this.position];

	var taillen = 6;
	var fraction = 1/taillen;

	for ( var t=0; t < taillen; t++ ) {
		try {
		var tail = pcalc.right - t;
	} catch ( err ) {
		console.log( i + " | " + this.position );
	}
		if ( tail > 0 ) {
			var factor = ( 6 - t ) * ( fraction );
			pixels[tail].red += this.color.r * factor;
			pixels[tail].green += this.color.g * factor;
			pixels[tail].blue += this.color.b * factor;
		}
	}
	var frontedge = pcalc.right + 1;
	if ( frontedge < pixelLength - 2 ) {
		pixels[frontedge].red = 0;
		pixels[frontedge].green = 0;
		pixels[frontedge].blue = 0;
	}
}

function setPixel( i, r, g, b ) {
	pixels[i].red = r;
	pixels[i].green = g;
	pixels[i].blue = b;
}

function initAllPixels( r, g, b ){
	for ( var i=0; i<pixels.length; i++ ) {
		pixels[i].red = r;
		pixels[i].green = g;
		pixels[i].blue = b;
	}
}

function getProximateParticle( s, dist ) {
	var pos = s * ( pixelLength / sensorCount );
	return getParticle( 4, pos, 2,  method_BrightenSmooth, update_Smooth, defaultScale, 85, 75, 15, 20 );
}

function getRandParticle() {
	var r = Math.random();

	if ( r < .10 ) {
		return getParticle( 4, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 10, 10, 85, 0 );
//	} else if ( r < .15 ) {
//		return getParticle( 3, 0, 1, method_Sweep, update_Smooth, defaultScale, 60, 10, 15, 0 );
//	} else if ( r < .30 ) {
//		return getParticle( 3, 0, 1, method_Sweep, update_Smooth, defaultScale, 30, 30, 95, 0 );
	} else if ( r < .50 ) {
		return getParticle( 4, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 45, 25, 100, 0 )
	} else {
		return getParticle( 2, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 5, 5, 10, 0 );
	}
}

function getParticle( v, p, r, g, b ) {
	return getParticle( v, p, 1, method_Brighten, update_Discrete, defaultScale, r, g, b, 0 );
}

function getParticle( v, p, i, m, u, s, r, g, b, l ) {
  var p = {
    'vel': v,
    'position': p,
    'intensity': i,
		'method': m,
		'update': u,
		'scale': s,
    'color': { 'r': r, 'g': g, 'b': b },
		'life': l
  };
  return p;
}

// Serial Access

function listPorts() {
  serialport.list(function (err, ports) {
    ports.forEach(function(port) {
      console.log(port.comName);
    });
  });
  return ports;
}

function openPort() {
	serialport.on('error', function(err){
		console.log('serialport general error' + err);
	});

  serialport.open(function (error) {
    if ( error ) {
      console.log('open err: ' + error);
//			runState = "conn open err";
	runState = "open";
    } else {
      console.log('open');
			runState = "open";

      serialport.on('data', function(data) {
    		var c = data.trim();
				try{
					//console.log('rcv: ' + c);
	    		dist_v = JSON.parse(c);
					//dist_v = {};
					if ( SENSORTEST ) {
						for ( var s=0; s < sensorCount; s++ ) {
	    				console.log( s + ' : ' + dist_v[s] );
						}
					}
				} catch( err ){
					console.log('parse err ' + err);
				}
	    });

    }
  });

}
<commit_msg>remove<commit_after>#!/usr/bin/env node

var OPC = new require('./opc')

var fc = new OPC('localhost', 7890);

var sp = require('serialport');
var SerialPort = require('serialport').SerialPort;
var portName = "/dev/ttyArduino";

var runState = "down";

var BRIGHTEN = 100;
var DARKEN = 101;

var BRIGHTEN_S = 200;
var DARKEN_S = 201;

var SWEEP = 300;

var SENSORTEST = false;

var sensorCount = 8;

var pixelLength = 300;
var particleCount = 400;

var environmentLength = 3000;

var defaultScale = 7;

var pixels = [];
var particles = [];

var lookup = [];

var coordT = [];

var dist_v = [];

var timerIdle = true;

// MAIN COMPUTER PROGRAM!

initialize();
setInterval(evaluate, 30);

function initialize() {

	if ( process.argv.length > 2 ) {
			if ( process.argv[2] == "sensorTest" ) {
				SENSORTEST = true;
			}
	}

	serialport = new SerialPort(portName , { baudrate : 115200, parser: sp.parsers.readline("|") }, false);
	openPort();

	for ( var i=0; i<8; i++ ) { dist_v[i] = 0; }

	// Init coord lookup
	var coordRatio = ( ( pixelLength ) / environmentLength );
	for ( var t=0; t<environmentLength+1; t++ ){ coordT[t] = Math.floor( t * coordRatio ); }

	// Init scaling lookup

	lookup[defaultScale] = { 'environmentLength': defaultScale * pixelLength, 'positions': [] };

	for ( var p=0; p < lookup[defaultScale].environmentLength; p++ ){
		var div = p / defaultScale;
		var calc = {
			'left': Math.floor( div ),
			'right': Math.floor( div ) + 1,
			'wleft': 1 - ( div ) % 1,
			'wright': ( div ) % 1
		};

		lookup[defaultScale].positions.push( calc );
	}

	// Init pixel array
	for ( var i=0; i<pixelLength + 3; i++ ) { pixels.push({ 'r':0, 'g':0, 'b':0 }); }
}

function evaluate() {
	if ( runState == "open") {
  	updateParticles();
  	evaluateEnvironment();
  	draw();
	} else {
		if ( timerIdle ) {
			setTimeout( function() {
				openPort();
				timerIdle = true;
			}, 5000);
			timerIdle = false;
		}
	}
}

function updateParticles() {
  for ( var i=0; i<particles.length; i++ ){
		particles[i].update( i );
  }
}

function evaluateEnvironment() {
	// fill particle list
	if ( particles.length < particleCount ) {
		particles.push( getRandParticle() );
	}

	for ( var s=0; s < sensorCount; s++ ) {
//			if ( dist_v[s] > 0 && dist_v[s] < 50 ) {
//				particles.push( getProximateParticle( s, dist_v[s] ));
//			}
	}
}

function draw() {
  if ( runState == "open" ) {

		// Initialize
		initAllPixels( 20, 20, 40 );

	  // Compose
	  for ( var i=0; i<particles.length; i++ ){ particles[i].method(); }

	  // Render
	//	try {
	    for ( var i=0; i<pixels.length; i++ ){
	      fc.setPixel( pixels.length-i, pixels[i].red, pixels[i].green, pixels[i].blue );
	    }
	    fc.writePixels();
	//	} catch( err ) {
	//		console.log('fc write err: ' + error);
	//		runState = "fc write err";
	//	}

  } else {
    // display runstate graphics

  }
}

// update methods

function update_Discrete( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > environmentLength ) {
		particles[i] = getRandParticle();
	}
}

function update_Smooth( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > lookup[this.scale].environmentLength-1 ) {
    particles[i] = getRandParticle();
	}
}

function update_Glower( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > lookup[this.scale].environmentLength-1 ) {
    particles[i] = getRandParticle();
	}
}

// draw methods

function method_Brighten() {
	var dest = coordT[this.position];

	pixels[dest].red += this.color.r;
	pixels[dest].green += this.color.g;
	pixels[dest].blue += this.color.b;
}

function method_Darken() {
	var dest = coordT[this.position];

	pixels[dest].red -= this.color.r;
	pixels[dest].green -= this.color.g;
	pixels[dest].blue -= this.color.b;
}

function method_BrightenSmooth() {
	var pcalc = lookup[this.scale].positions[this.position];
	methodValueSmooth( this, pcalc );
}

function method_DarkenSmooth() {
	var pcalc = lookup[this.scale].positions[this.position];
	if ( this.method == DARKEN_S ) {
		pcalc.wleft *= -1;
		pcalc.wright *= -1;
	}
	methodValueSmooth( this, pcalc );
}

function methodValueSmooth( tgt, pcalc ){
	pixels[pcalc.left].red += tgt.color.r * pcalc.wleft;
	pixels[pcalc.left].green += tgt.color.g * pcalc.wleft;
	pixels[pcalc.left].blue += tgt.color.b * pcalc.wleft;

	pixels[pcalc.right].red += tgt.color.r * pcalc.wright;
	pixels[pcalc.right].green += tgt.color.g * pcalc.wright;
	pixels[pcalc.right].blue += tgt.color.b * pcalc.wright;
}

function method_Sweep() {
	var pcalc = lookup[this.scale].positions[this.position];

	var taillen = 6;
	var fraction = 1/taillen;

	for ( var t=0; t < taillen; t++ ) {
		try {
		var tail = pcalc.right - t;
	} catch ( err ) {
		console.log( i + " | " + this.position );
	}
		if ( tail > 0 ) {
			var factor = ( 6 - t ) * ( fraction );
			pixels[tail].red += this.color.r * factor;
			pixels[tail].green += this.color.g * factor;
			pixels[tail].blue += this.color.b * factor;
		}
	}
	var frontedge = pcalc.right + 1;
	if ( frontedge < pixelLength - 2 ) {
		pixels[frontedge].red = 0;
		pixels[frontedge].green = 0;
		pixels[frontedge].blue = 0;
	}
}

function setPixel( i, r, g, b ) {
	pixels[i].red = r;
	pixels[i].green = g;
	pixels[i].blue = b;
}

function initAllPixels( r, g, b ){
	for ( var i=0; i<pixels.length; i++ ) {
		pixels[i].red = r;
		pixels[i].green = g;
		pixels[i].blue = b;
	}
}

function getProximateParticle( s, dist ) {
	var pos = s * ( pixelLength / sensorCount );
	return getParticle( 4, pos, 2,  method_BrightenSmooth, update_Smooth, defaultScale, 85, 75, 15, 20 );
}

function getRandParticle() {
	var r = Math.random();

	if ( r < .10 ) {
		return getParticle( 4, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 10, 10, 85, 0 );
//	} else if ( r < .15 ) {
//		return getParticle( 3, 0, 1, method_Sweep, update_Smooth, defaultScale, 60, 10, 15, 0 );
//	} else if ( r < .30 ) {
//		return getParticle( 3, 0, 1, method_Sweep, update_Smooth, defaultScale, 30, 30, 95, 0 );
	} else if ( r < .50 ) {
		return getParticle( 4, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 45, 25, 100, 0 )
	} else {
		return getParticle( 2, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 5, 5, 10, 0 );
	}
}

function getParticle( v, p, r, g, b ) {
	return getParticle( v, p, 1, method_Brighten, update_Discrete, defaultScale, r, g, b, 0 );
}

function getParticle( v, p, i, m, u, s, r, g, b, l ) {
  var p = {
    'vel': v,
    'position': p,
    'intensity': i,
		'method': m,
		'update': u,
		'scale': s,
    'color': { 'r': r, 'g': g, 'b': b },
		'life': l
  };
  return p;
}

// Serial Access

function listPorts() {
  serialport.list(function (err, ports) {
    ports.forEach(function(port) {
      console.log(port.comName);
    });
  });
  return ports;
}

function openPort() {
	serialport.on('error', function(err){
		console.log('serialport general error' + err);
	});

  serialport.open(function (error) {
    if ( error ) {
      console.log('open err: ' + error);
//			runState = "conn open err";
	runState = "open";
    } else {
      console.log('open');
			runState = "open";

      serialport.on('data', function(data) {
    		var c = data.trim();
				try{
					//console.log('rcv: ' + c);
	    		dist_v = JSON.parse(c);
					//dist_v = {};

					if ( SENSORTEST ) {
						var out = "";
						for ( var s=0; s < sensorCount; s++ ) {
							out += s + '=' + dist_v[s] + '  :  ';
						}
						console.log( out );
					}
				} catch( err ){
					console.log('parse err ' + err);
				}
	    });

    }
  });

}
<|endoftext|>


<commit_before>/*
 *  Copyright 2012 the original author or authors.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
dc = {
    version: "1.5.0",
    constants : {
        CHART_CLASS: "dc-chart",
        DEBUG_GROUP_CLASS: "debug",
        STACK_CLASS: "stack",
        DESELECTED_CLASS: "deselected",
        SELECTED_CLASS: "selected",
        NODE_INDEX_NAME: "__index__",
        GROUP_INDEX_NAME: "__group_index__",
        DEFAULT_CHART_GROUP: "__default_chart_group__",
        EVENT_DELAY: 40,
        NEGLIGIBLE_NUMBER: 1e-10
    },
    _renderlet : null
};

dc.chartRegistry = function() {
    // chartGroup:string => charts:array
    var _chartMap = {};

    this.has = function(chart) {
        for (var e in _chartMap) {
            if (_chartMap[e].indexOf(chart) >= 0)
                return true;
        }
        return false;
    };

    function initializeChartGroup(group) {
        if (!group)
            group = dc.constants.DEFAULT_CHART_GROUP;

        if (!_chartMap[group])
            _chartMap[group] = [];

        return group;
    }

    this.register = function(chart, group) {
        group = initializeChartGroup(group);
        _chartMap[group].push(chart);
    };

    this.clear = function() {
        _chartMap = {};
    };

    this.list = function(group) {
        group = initializeChartGroup(group);
        return _chartMap[group];
    };

    return this;
}();

dc.registerChart = function(chart, group) {
    dc.chartRegistry.register(chart, group);
};

dc.hasChart = function(chart) {
    return dc.chartRegistry.has(chart);
};

dc.deregisterAllCharts = function() {
    dc.chartRegistry.clear();
};

dc.filterAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].filterAll();
    }
};

dc.renderAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].render();
    }

    if(dc._renderlet !== null)
        dc._renderlet(group);
};

dc.redrawAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].redraw();
    }

    if(dc._renderlet !== null)
        dc._renderlet(group);
};

dc.transition = function(selections, duration, callback) {
    if (duration <= 0 || duration === undefined)
        return selections;

    var s = selections
        .transition()
        .duration(duration);

    if (callback instanceof Function) {
        callback(s);
    }

    return s;
};

dc.units = {};
dc.units.integers = function(s, e) {
    return Math.abs(e - s);
};

dc.units.ordinal = function(s, e, domain){
    return domain;
};
dc.units.fp = {};
dc.units.fp.precision= function(precision){
    var _f = function(s, e, domain){return Math.ceil(Math.abs((e-s)/_f.resolution));};
    _f.resolution = precision;
    return _f;
};

dc.round = {};
dc.round.floor = function(n) {
    return Math.floor(n);
};
dc.round.ceil = function(n) {
    return Math.ceil(n);
};
dc.round.round = function(n) {
    return Math.round(n);
};

dc.override = function(obj, functionName, newFunction) {
    var existingFunction = obj[functionName];
    obj["_" + functionName] = existingFunction;
    obj[functionName] = newFunction;
};

dc.renderlet = function(_){
    if(!arguments.length) return dc._renderlet;
    dc._renderlet = _;
    return dc;
};

dc.instanceOfChart = function (o) {
    return o instanceof Object && o.__dc_flag__;
};
<commit_msg>start v1.6 dev<commit_after>/*
 *  Copyright 2012 the original author or authors.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
dc = {
    version: "1.6.0",
    constants : {
        CHART_CLASS: "dc-chart",
        DEBUG_GROUP_CLASS: "debug",
        STACK_CLASS: "stack",
        DESELECTED_CLASS: "deselected",
        SELECTED_CLASS: "selected",
        NODE_INDEX_NAME: "__index__",
        GROUP_INDEX_NAME: "__group_index__",
        DEFAULT_CHART_GROUP: "__default_chart_group__",
        EVENT_DELAY: 40,
        NEGLIGIBLE_NUMBER: 1e-10
    },
    _renderlet : null
};

dc.chartRegistry = function() {
    // chartGroup:string => charts:array
    var _chartMap = {};

    this.has = function(chart) {
        for (var e in _chartMap) {
            if (_chartMap[e].indexOf(chart) >= 0)
                return true;
        }
        return false;
    };

    function initializeChartGroup(group) {
        if (!group)
            group = dc.constants.DEFAULT_CHART_GROUP;

        if (!_chartMap[group])
            _chartMap[group] = [];

        return group;
    }

    this.register = function(chart, group) {
        group = initializeChartGroup(group);
        _chartMap[group].push(chart);
    };

    this.clear = function() {
        _chartMap = {};
    };

    this.list = function(group) {
        group = initializeChartGroup(group);
        return _chartMap[group];
    };

    return this;
}();

dc.registerChart = function(chart, group) {
    dc.chartRegistry.register(chart, group);
};

dc.hasChart = function(chart) {
    return dc.chartRegistry.has(chart);
};

dc.deregisterAllCharts = function() {
    dc.chartRegistry.clear();
};

dc.filterAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].filterAll();
    }
};

dc.renderAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].render();
    }

    if(dc._renderlet !== null)
        dc._renderlet(group);
};

dc.redrawAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].redraw();
    }

    if(dc._renderlet !== null)
        dc._renderlet(group);
};

dc.transition = function(selections, duration, callback) {
    if (duration <= 0 || duration === undefined)
        return selections;

    var s = selections
        .transition()
        .duration(duration);

    if (callback instanceof Function) {
        callback(s);
    }

    return s;
};

dc.units = {};
dc.units.integers = function(s, e) {
    return Math.abs(e - s);
};

dc.units.ordinal = function(s, e, domain){
    return domain;
};
dc.units.fp = {};
dc.units.fp.precision= function(precision){
    var _f = function(s, e, domain){return Math.ceil(Math.abs((e-s)/_f.resolution));};
    _f.resolution = precision;
    return _f;
};

dc.round = {};
dc.round.floor = function(n) {
    return Math.floor(n);
};
dc.round.ceil = function(n) {
    return Math.ceil(n);
};
dc.round.round = function(n) {
    return Math.round(n);
};

dc.override = function(obj, functionName, newFunction) {
    var existingFunction = obj[functionName];
    obj["_" + functionName] = existingFunction;
    obj[functionName] = newFunction;
};

dc.renderlet = function(_){
    if(!arguments.length) return dc._renderlet;
    dc._renderlet = _;
    return dc;
};

dc.instanceOfChart = function (o) {
    return o instanceof Object && o.__dc_flag__;
};
<|endoftext|>


<commit_before>/**
 *  Copyright 2015 Jaime Pajuelo
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

/**
 * @param {Function} parentClass
 * @returns {Function} The instance on which this method was called.
 */
Function.prototype.inherit = function inherit(parentClass) {
    this.prototype = Object.create(parentClass.prototype);
    this.prototype.constructor = this;

    // TODO: think a better way to get the parent class.
    this.prototype.parentClass = parentClass;

    return this;
};

/**
 * @param {String} memberName
 * @param {Function} memberMethod
 * @returns {Function} The instance on which this method was called.
 */
Function.prototype.member = function member(memberName, memberMethod) {
    this.prototype[memberName] = memberMethod;

    return this;
};

/**
 * @namespace
 */
var utils = {

    /**
     * @param {Object} sourceObject
     * @returns {Object} The new object cloned.
     */
    cloneObject: function cloneObject(sourceObject) {
        if (sourceObject == null || typeof sourceObject !== 'object') {
            sourceObject = {};
        }

        return JSON.parse(JSON.stringify(sourceObject))
    },

    formatString: function formatString(sourceString, namedArgs) {
        var name;

        for (name in namedArgs) {
            if (sourceString.indexOf("%(" + name + ")s") != -1) {
                sourceString = sourceString.replace("%(" + name + ")s", namedArgs[name]);
            }
        }

        return sourceString;
    },

    /**
     * @param {Object} sourceObject
     * @param {Object} targetObject
     * @return {Object} The sourceObject merged with targetObject.
     */
    updateObject: function updateObject(sourceObject, targetObject) {
        var name;

        sourceObject = this.cloneObject(sourceObject);
        targetObject = this.cloneObject(targetObject);

        for (name in sourceObject) {
            if (name in targetObject) {
                sourceObject[name] = targetObject[name];
            }
        }

        return sourceObject;
    }

};
<commit_msg>Add the JS docstring for the utils.formatString<commit_after>/**
 *  Copyright 2015 Jaime Pajuelo
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

/**
 * @param {Function} parentClass
 * @returns {Function} The instance on which this method was called.
 */
Function.prototype.inherit = function inherit(parentClass) {
    this.prototype = Object.create(parentClass.prototype);
    this.prototype.constructor = this;

    // TODO: think a better way to get the parent class.
    this.prototype.parentClass = parentClass;

    return this;
};

/**
 * @param {String} memberName
 * @param {Function} memberMethod
 * @returns {Function} The instance on which this method was called.
 */
Function.prototype.member = function member(memberName, memberMethod) {
    this.prototype[memberName] = memberMethod;

    return this;
};

/**
 * @namespace
 */
var utils = {

    /**
     * @param {Object} sourceObject
     * @returns {Object} The new object cloned.
     */
    cloneObject: function cloneObject(sourceObject) {
        if (sourceObject == null || typeof sourceObject !== 'object') {
            sourceObject = {};
        }

        return JSON.parse(JSON.stringify(sourceObject))
    },

    /**
     * @param {String} sourceString
     * @param {Object.<String, *>} namedArgs
     * @returns {String} The new string formatted.
     */
    formatString: function formatString(sourceString, namedArgs) {
        var name;

        for (name in namedArgs) {
            if (sourceString.indexOf("%(" + name + ")s") != -1) {
                sourceString = sourceString.replace("%(" + name + ")s", namedArgs[name]);
            }
        }

        return sourceString;
    },

    /**
     * @param {Object} sourceObject
     * @param {Object} targetObject
     * @return {Object} The sourceObject merged with targetObject.
     */
    updateObject: function updateObject(sourceObject, targetObject) {
        var name;

        sourceObject = this.cloneObject(sourceObject);
        targetObject = this.cloneObject(targetObject);

        for (name in sourceObject) {
            if (name in targetObject) {
                sourceObject[name] = targetObject[name];
            }
        }

        return sourceObject;
    }

};
<|endoftext|>