<commit_before>var _ = require('underscore'),
    async = require('async'),
    handlebars = require('handlebars');

var moduleMapTemplate;

function getModuleMapTemplate(fileUtil) {
  if (!moduleMapTemplate) {
    moduleMapTemplate = handlebars.compile(fileUtil.readFileSync(__dirname + '/module-map.handlebars'));
  }
  return moduleMapTemplate;
};

function loadModuleMap(map, mapper, fileUtil, callback) {
  var moduleMapTemplate = getModuleMapTemplate(fileUtil);
  callback(
    undefined,
    moduleMapTemplate({
      moduleMapper: mapper,
      map: JSON.stringify(map)
    })
  );
};

function buildMap(context, callback) {
  if (context.combined) {
    moduleConfig(context, undefined, function(err, config) {
      callback(err, { base: config });
    });
  } else {
    var attr = context.config.attributes || {},
        app = attr.application || {},
        modules = context.config.moduleList(context.package);

    var map = {modules: {}, routes: {}};

    async.forEach(modules, function(module, callback) {
      moduleConfig(context, module, function(err, config) {
        if (err) {
          return callback(err);
        }

        if (app.module === module) {
          map.base = config;
        } else {
          map.modules[module] = config;

          var routes = context.config.routeList(module);
          if (routes) {
            for (var route in routes) {
              map.routes[route] = module;
            }
          }
        }

        callback();
      });
    },
    function(err) {
      callback(err, map);
    });
  }
}

function stripPrefix(map, prefix) {
  if (!prefix) {
    return;
  }

  function stripModule(module) {
    if (module.js) {
      module.js = stripList(module.js);
    }
    if (module.css) {
      module.css = stripList(module.css);
    }
  }
  function stripList(list) {
    if (_.isArray(list)) {
      return list.map(stripEntry);
    } else {
      return stripEntry(list);
    }
  }
  function stripEntry(entry) {
    if (entry.href) {
      entry.href = entry.href.substring(prefix.length);
      return entry;
    } else {
      return entry.substring(prefix.length);
    }
  }
  if (map.base) {
    stripModule(map.base);
  }
  if (map.modules) {
    _.each(map.modules, stripModule);
  }
}
function moduleConfig(context, module, callback) {
  var ret = {};

  async.forEach([{key: 'js', mode: 'scripts'}, {key: 'css', mode: 'styles'}], function(obj, callback) {
    fileList(context, obj.mode, module, function(err, list) {
      ret[obj.key] = list;
      callback(err);
    });
  },
  function(err) {
    callback(err, ret);
  });
}
function fileList(context, mode, module, callback) {
  // Check to see if we even have this type of resource
  var modules = !context.combined ? [ module ] : context.config.moduleList(context.package);
  async.some(modules, function(module, callback) {
      var resourceContext = context.clone();
      resourceContext.mode = mode;
      resourceContext.module = context.config.module(module);

      resourceContext.plugins.moduleResources(resourceContext, function(err, resources) {
        callback((resources || []).length);
      });
  },
  function(hasResource) {
    if (!hasResource) {
      return callback();
    }

    // Output the config
    context.fileNamesForModule(mode, module, function(err, configs) {
      if (err) {
        return callback(err);
      }

      configs = configs.sort(function(a, b) { return a.pixelDensity - b.pixelDensity; });
      configs = configs.map(function(config, i) {
        var path = config.fileName.path,
            ret = path + '.' + config.fileName.extension;

        if (config.pixelDensity) {
          ret = { href: ret };
          if (0 < i) {
            ret.minRatio = configs[i-1].pixelDensity + (config.pixelDensity - configs[i-1].pixelDensity) / 2;
          }
          if (i < configs.length - 1) {
            ret.maxRatio = config.pixelDensity + (configs[i+1].pixelDensity - config.pixelDensity) / 2;
          }
        }

        // Update the prefix tracker
        var prefix = context.fileCache.commonFilePrefix;
        if (prefix == null) {
          prefix = context.fileCache.commonFilePrefix = path;
        }
        for (var i = 0, len = prefix.length; i < len; i++) {
          if (path.charAt(i) !== prefix.charAt(i)) {
            context.fileCache.commonFilePrefix = prefix.substring(0, i);
            break;
          }
        }

        return ret;
      });

      var ret;
      if (configs.length === 1) {
        ret = configs[0];
      } else if (configs.length) {
        ret = configs;
      }
      callback(undefined, ret);
    });
  });
}

module.exports = {
  mode: 'scripts',
  priority: 50,

  resource: function(context, next, complete) {
    var config = context.config;

    if (context.resource['module-map']) {
      var buildModuleMap = function(context, callback) {
        buildMap(context, function(err, map) {
          if (err) {
            callback(err);
          } else {
            var moduleMap = config.attributes.moduleMap || 'module.exports.moduleMap';
            // TODO : Figure out how we want to handle the commonFilePrefix stuff with the new module map
            stripPrefix(map, context.fileCache.commonFilePrefix);
            loadModuleMap(map, moduleMap, context.fileUtil, function(err, data) {
              callback(err, data && {data: data, noSeparator: true});
            });
          }
        });
      };
      buildModuleMap.sourceFile = undefined;
      complete(undefined, buildModuleMap);
    } else {
      next(complete);
    }
  }
};
<commit_msg>Pass common prefix back from buildMap<commit_after>var _ = require('underscore'),
    async = require('async'),
    handlebars = require('handlebars');

var moduleMapTemplate;

function getModuleMapTemplate(fileUtil) {
  if (!moduleMapTemplate) {
    moduleMapTemplate = handlebars.compile(fileUtil.readFileSync(__dirname + '/module-map.handlebars'));
  }
  return moduleMapTemplate;
};

function loadModuleMap(map, mapper, fileUtil, callback) {
  var moduleMapTemplate = getModuleMapTemplate(fileUtil);
  callback(
    undefined,
    moduleMapTemplate({
      moduleMapper: mapper,
      map: JSON.stringify(map)
    })
  );
};

function buildMap(context, callback) {
  if (context.combined) {
    moduleConfig(context, undefined, function(err, config, prefix) {
      callback(err, { base: config }, prefix);
    });
  } else {
    var attr = context.config.attributes || {},
        app = attr.application || {},
        modules = context.config.moduleList(context.package);

    var map = {modules: {}, routes: {}},
        commonPrefix;

    async.forEach(modules, function(module, callback) {
      moduleConfig(context, module, function(err, config, prefix) {
        if (err) {
          return callback(err);
        }

        if (app.module === module) {
          map.base = config;
        } else {
          map.modules[module] = config;

          var routes = context.config.routeList(module);
          if (routes) {
            for (var route in routes) {
              map.routes[route] = module;
            }
          }
        }
        commonPrefix = findPrefix(prefix, commonPrefix);

        callback();
      });
    },
    function(err) {
      callback(err, map, commonPrefix);
    });
  }
}

function stripPrefix(map, prefix) {
  if (!prefix) {
    return;
  }

  function stripModule(module) {
    if (module.js) {
      module.js = stripList(module.js);
    }
    if (module.css) {
      module.css = stripList(module.css);
    }
  }
  function stripList(list) {
    if (_.isArray(list)) {
      return list.map(stripEntry);
    } else {
      return stripEntry(list);
    }
  }
  function stripEntry(entry) {
    if (entry.href) {
      entry.href = entry.href.substring(prefix.length);
      return entry;
    } else {
      return entry.substring(prefix.length);
    }
  }
  if (map.base) {
    stripModule(map.base);
  }
  if (map.modules) {
    _.each(map.modules, stripModule);
  }
}
function moduleConfig(context, module, callback) {
  var ret = {},
      commonPrefix;

  async.forEach([{key: 'js', mode: 'scripts'}, {key: 'css', mode: 'styles'}], function(obj, callback) {
    fileList(context, obj.mode, module, function(err, list, prefix) {
      ret[obj.key] = list;
      commonPrefix = findPrefix(prefix, commonPrefix);
      callback(err);
    });
  },
  function(err) {
    callback(err, ret, commonPrefix);
  });
}
function fileList(context, mode, module, callback) {
  // Check to see if we even have this type of resource
  var modules = !context.combined ? [ module ] : context.config.moduleList(context.package);
  async.some(modules, function(module, callback) {
      var resourceContext = context.clone();
      resourceContext.mode = mode;
      resourceContext.module = context.config.module(module);

      resourceContext.plugins.moduleResources(resourceContext, function(err, resources) {
        callback((resources || []).length);
      });
  },
  function(hasResource) {
    if (!hasResource) {
      return callback();
    }

    // Output the config
    context.fileNamesForModule(mode, module, function(err, configs) {
      if (err) {
        return callback(err);
      }

      var prefix;
      configs = configs.sort(function(a, b) { return a.pixelDensity - b.pixelDensity; });
      configs = configs.map(function(config, i) {
        var path = config.fileName.path,
            ret = path + '.' + config.fileName.extension;

        if (config.pixelDensity) {
          ret = { href: ret };
          if (0 < i) {
            ret.minRatio = configs[i-1].pixelDensity + (config.pixelDensity - configs[i-1].pixelDensity) / 2;
          }
          if (i < configs.length - 1) {
            ret.maxRatio = config.pixelDensity + (configs[i+1].pixelDensity - config.pixelDensity) / 2;
          }
        }

        // Update the prefix tracker
        prefix = findPrefix(path, prefix)

        return ret;
      });

      var ret;
      if (configs.length === 1) {
        ret = configs[0];
      } else if (configs.length) {
        ret = configs;
      }
      callback(undefined, ret, prefix);
    });
  });
}

function findPrefix(path, prefix) {
  if (path == null) {
    return prefix;
  }
  if (prefix == null) {
    prefix = path;
  }
  for (var i = 0, len = prefix.length; i < len; i++) {
    if (path.charAt(i) !== prefix.charAt(i)) {
      return prefix.substring(0, i);
      break;
    }
  }
  return prefix;
}

module.exports = {
  mode: 'scripts',
  priority: 50,

  buildMap: buildMap,

  resource: function(context, next, complete) {
    var config = context.config;

    if (context.resource['module-map']) {
      var buildModuleMap = function(context, callback) {
        buildMap(context, function(err, map, prefix) {
          if (err) {
            callback(err);
          } else {
            var moduleMap = config.attributes.moduleMap || 'module.exports.moduleMap';
            stripPrefix(map, prefix);
            loadModuleMap(map, moduleMap, context.fileUtil, function(err, data) {
              callback(err, data && {data: data, noSeparator: true});
            });
          }
        });
      };
      buildModuleMap.sourceFile = undefined;
      complete(undefined, buildModuleMap);
    } else {
      next(complete);
    }
  }
};
<|endoftext|>


<commit_before>(function() {

/**
 * create root namespace for all twentyc definitions
 * @module twentyc
 */

twentyc = {};

/**
 * class helper functions
 * @module twentyc
 * @class cls
 * @static
 */

twentyc.cls = {

  /**
   * converts a string into a standardized class name, replacing
   * invalid characters with valid ones.
   *
   *     twentyc.cls.make_name("class-a"); // classA
   *     twentyc.cls.make_name("class a b"); // classAB
   *     twentyc.cls.make_name("Class-A_B"); // ClassA_B
   *
   * @method make_name
   * @param {String} name base name
   * @returns {String} class_name changed name
   */

  make_name : function(name) {
    var i, names = name.split(/[-\s]/);
    for(i = 0; i < names.length; i++) {
      if(i > 0)
        names[i] = names[i].charAt(0).toUpperCase() + names[i].slice(1);
    }
    return names.join("");
  },

  /**
   * create a new class - if you wish to extend a class take a look at
   * {{#crossLink "cls/extend:method"}}twentyc.cls.extend{{/crossLink}}
   * instead
   *
   * you may define a constructor in the definition by using the class
   * name you provide at __name__
   *
   * Note that if the name you provide is not a valid variable name
   * it will be passed through twentyc.cls.make_name to make it valid
   *
   * ##examples
   *
   * * define and instantiate a class: examples/cls.define.js
   *
   * @method define
   * @param {String} name name or unique identifier of the new class
   * @param {Object} definition object literal of properties and functions that you wish define or redefine
   * @returns {Function} dest constructor of new class
   */

  define : function(name, definition) {

    var k;

    name = twentyc.cls.make_name(name);

    if(typeof(definition[name]) == "function") {
      // a constructor has been provided
      var ctor = definition[name]
      delete definition[name]
    } else {
      // no constructor provided, substitute empty constructor
      var ctor = function(){};
    }

    // cycle through definition and copy to class prototype
    for(k in definition) {
      ctor.prototype[k] = definition[k]
    }

    // create meta information
    ctor.prototype._meta = {
      "name" : name
    }

    return ctor

  },

  /**
   * extend an existing class with new properties and functions
   *
   * if a function is defined that already exists on the parent class
   * this function will be overwritten and a reference to the original
   * function will be provided at parentClassName_functionName
   *
   * you may define a constructor in the definition by using the class
   * name you provide at __name__
   *
   * Note that if the name you provide is not a valid variable name
   * it will be passed through twentyc.cls.make_name to make it valid
   *
   * ##examples
   *
   * * extend and instantiate a class: examples/cls.extend.js
   * * handling method override: examples/cls.extend.method-override.js
   *
   * @method extend
   * @param {String} name name or unqiue identifier of the new class
   * @param {Object} definition object literal of properties and functions that you wish define or redefine
   * @param {Function} [parent] constructor of class
   * that you wish to extend, if omitted an empty function will be substituted
   * @returns {Function} dest constructor of new class
   */

  extend : function(name, definition, parent) {

    var k;
    name = twentyc.cls.make_name(name);

    if(typeof(definition[name]) == "function") {
      // a constructor has been provided
      var ctor = definition[name]
      delete definition[name]
    } else {
      // no constructor provided, substitute empty constructor
      var ctor = function(){
        parent.apply(this, arguments)
      };
    }

    // cycle through parent prototype and copy to class prototype
    for(k in parent.prototype) {
      ctor.prototype[k] = parent.prototype[k]
    }

    // cycle through definition and copy to class prototype
    for(k in definition) {
      if(typeof(ctor.prototype[k]) == "function") {
        // function was already defined by parent, store backref
        ctor.prototype[parent.prototype._meta.name+"_"+k] = parent.prototype[k];
      }
      ctor.prototype[k] = definition[k]
    }

    // reference parent constructor
    ctor.prototype[parent.prototype._meta.name] = parent

    // create meta information
    ctor.prototype._meta = {
      "name" : name,
      "parent" : parent
    }

    return ctor

  },

  /**
   * overrides a method on the provided class
   *
   * @method override
   * @param {Function} destClass A class created via __twentyc.cls.define__ or __twentyc.cls.extend__
   * @param {String} methodName name of method that you wish to override
   * @param {Function} method new method
   */

  override : function(destClass, methodName, method) {

    // create reference to old method
    if(destClass.prototype[methodName])
      destClass.prototype[destClass.prototype._meta.name+"_"+methodName] = destClass.prototype[methodName];

    // override
    destClass.prototype[methodName] = method;

  }

}

/**
 * class registry object - allows you to quickly define and extend
 * similar classes
 *
 * @module twentyc
 * @namespace twentyc.cls
 * @class Registry
 * @constructor
 */

twentyc.cls.Registry = twentyc.cls.define(
  "Registry",
  {

    Registry : function() {

      /**
       * holds the classes defined in this registry
       * @property _classes
       * @type Object
       * @private
       */

      this._classes = {}

    },

    /**
     * register a new class - look at twentyc.cls.define and twentyc.cls.extend for param
     * explanation
     * @method register
     * @param {String} name class name
     * @param {Object} definition class definition
     * @param {String} extend if passed, extend this class from this class (needs to exist in the Registry)
     * @returns {Function} class ctor of the newly created class
     */

     register : function(name, definition, extend) {
       if(this._classes[name] != undefined) {
         throw("Class with name '"+name+"' already exists - name must be unique in the Registry");
       }
       if(extend && typeof this._classes[extend] != "function") {
         throw("Trying to extend from class unknown to this Registry: "+name);
       }
       if(extend)
         this._classes[name] = twentyc.cls.extend(name, definition, this._classes[extend]);
       else
         this._classes[name] = twentyc.cls.define(name, definition);
       return this._classes[name];
     },

     /**
      * get a registered class constructor
      * @method get
      * @param {String} name class name
      * @returns {Function} class ctor of registered class
      */

     get : function(name) {
       if(typeof this._classes[name] != "function")
         throw("Trying to retrieve class unknown to this Registry: "+name);
       return this._classes[name];
     }
  }
);

/**
 * utility functions
 * @module twentyc
 * @class util
 * @static
 */

twentyc.util = {

  /**
   * retrieve value from object literal - allows you to pass null or undefined
   * as the object and will return null if you do
   *
   * @method get
   * @param {Object} obj
   * @param {String) key
   * @param {Mixed} [default] return this if obj is null or key does not exist
   * @returns {Mixed} value
   */

  get : function(obj, key, dflt) {
    if(!obj || obj[key] == undefined)
      return dflt;
    return obj[key]
  }

}

/**
 * data retrieval, storage and management
 *
 * assures that data is only retrieved once even when multiple sources
 * are requesting it.
 *
 * data is cached locally for quick retrieval afterwards
 *
 * @module twentyc
 * @class data
 * @static
 */

twentyc.data = {

  /**
   * fires everytime a dataset is retrieved from the server - __*__ is
   * substituted with the data id
   *
   * all handlers bound to this event will be removed after its been
   * triggered - in order to permanently subscribe a load event
   * subscribe to "load"
   *
   * @event load-*
   * @param {String} id data id
   * @param {Object} data object literal of retrieved data
   */

  /**
   * fires everytime a dataset is retrieved from the server
   *
   * @event load
   * @param {String} id data id
   * @param {Object} data object literal of retrieved data
   */

  /**
   * keeps track of current loading status
   * @property _loading
   * @type Object
   * @private
   */

  _loading : {},

  /**
   * _data storage, keyed by data id
   * @property data
   * @type Object
   * @private
   */

  _data : {},

  /**
   * attempts to retrieve and return a data set
   *
   * ##example(s)
   *
   * examples/data.load.js
   *
   * @method get
   * @param {String} id data id
   * @returns {Object} data
   */

  get : function(id) {
    return tc.u.get(this._data, id, {})
  },

  /**
   * retrieve data from server. at this point this expects a json
   * string response, with the actual data keyed at the id you provided
   *
   * ##example(s)
   *
   * examples/data.load.js
   *
   * @method load
   * @param {String} id data identification key
   * @param {Object} [config] object literal holding options
   * @param {Function} [config.callback] called when data is available
   * @param {Boolean} [config.reload] if true data will be re-fetched even if already loaded
   */

  load : function(id, config) {

    var callback = tc.u.get(config, "callback");

    // check if data is already loaded
    if(this._data[id] && !tc.u.get(config, "reload")) {
      var payload = {id:id, data:this._data[id]}
      $(this).trigger("load-"+id, payload);
      if(callback)
        callback(payload)
      return;
    }

    // attach callback to load event
    if(callback) {
      $(this).on("load-"+id, function(ev, payload) { callback(payload) });
    }

    // check if data is currently being loaded
    if(this._loading[id]) {
      console.log("already loading",id,"skipping additional load")
      return;
    }

    // data is not loaded AND not currently loading, attempt to load data

    // in order to load data we need to find a suitable loader for it

    var loader = this.loaders.loader(id, config);
    this._loading[id] = new Date().getTime()
    loader.load(
      {
        success : function(data) {
          twentyc.data._data[id] = data
          twentyc.data._loading[id] = false;
          $(twentyc.data).trigger("load-"+id, { id:id, data:data });
          $(twentyc.data).off("load-"+id);
        }
      }
    );
  },

}

/**
 * create and manage data loaders
 * @module twentyc
 * @namesapce twentyc.data
 * @class loaders
 * @extends twentyc.cls.Registry
 * @static
 */

twentyc.data.LoaderRegistry = twentyc.cls.extend(
  "LoaderRegistry",
  {
    LoaderRegistry : function() {
      this.Registry();

      /**
       * holds data id -> loader assignments, keyed by data id
       * @property _loaders
       * @type Object
       * @private
       */

      this._loaders = {};
    },

    /**
     * assign loader to data id
     * @method assign
     * @param {String} id data id
     * @param {String} loaderName name that you registered the loader under
     */

    assign : function(id, loaderName) {

      // this will error if loaderName is not registered
      var loader = this.get(loaderName);

      // link loader
      this._loaders[id] = loaderName;

    },

    /**
     * get loader linked to data id via __link__
     * @method loader
     * @param {String} id data_id
     * @returns {Object} loader instance of loader
     */

    loader : function(id, config) {
      if(typeof this._loaders[id] == undefined)
        throw("Could not find suitable loader for data id "+id);

      var loader = this.get(this._loaders[id]);
      return new loader(id, config || {});
    }

  },
  twentyc.cls.Registry
);
twentyc.data.loaders = new twentyc.data.LoaderRegistry();

/**
 * any new loader you register should at the very least
 * extend this loader
 *
 * @class Base
 * @module twentyc
 * @namespace twentyc.data.loaders.get
 * @constructor
 * @param {String} id data id
 * @param {Object} [config] object literal holding config attributes
 */
twentyc.data.loaders.register(
  "Base",
  {
    Base : function(id, config) {
      this.dataId = id;
      this.config = config || {};
    },
    retrieve : function(data) {
      var set = tc.u.get(data, this.dataId)
      if(typeof set == undefined)
        return {};
      return set;
    },
    load : function() {
      throw("The load() function needs to be overwritten to do something")
    }
  }
);

/**
 * you may use this loader as a base class for any xhr data retrieval
 * loaders you define. during the ctor you will need to set the url
 * attribute on this.config
 *
 * @class Base
 * @module twentyc
 * @namespace twentyc.data.loaders.get
 * @constructor
 * @param {String} id data id
 * @param {Object} [config] object literal holding config attributes
 * @param {String} [config.url] url of the request
 * @param {Object} [config.data] parameters to send
 */

twentyc.data.loaders.register(
  "XHRGet",
  {
    load : function(callbacks) {
      var url = tc.u.get(this.config, "url");
      var loader = this;
      if(url == undefined)
        throw("XHRGet loader needs url, "+this._meta.name);
      $.ajax(
        {
          url : url,
          data : this.config.data,
          success : function(data) {
            if(typeof callbacks.success == "function")
              callbacks.success(loader.retrieve(data));
          }
        }
      ).fail(function(response) {
        if(callbacks.error)
          callbacks.error(response);
      });
    }
  },
  "Base"
);

/**
 * shortcuts
 */

tc = {
  u : twentyc.util,
  def : twentyc.cls.define,
  ext : twentyc.cls.extend
}

})();
<commit_msg>fix twentyc.data load event<commit_after>(function() {

/**
 * create root namespace for all twentyc definitions
 * @module twentyc
 */

twentyc = {};

/**
 * class helper functions
 * @module twentyc
 * @class cls
 * @static
 */

twentyc.cls = {

  /**
   * converts a string into a standardized class name, replacing
   * invalid characters with valid ones.
   *
   *     twentyc.cls.make_name("class-a"); // classA
   *     twentyc.cls.make_name("class a b"); // classAB
   *     twentyc.cls.make_name("Class-A_B"); // ClassA_B
   *
   * @method make_name
   * @param {String} name base name
   * @returns {String} class_name changed name
   */

  make_name : function(name) {
    var i, names = name.split(/[-\s]/);
    for(i = 0; i < names.length; i++) {
      if(i > 0)
        names[i] = names[i].charAt(0).toUpperCase() + names[i].slice(1);
    }
    return names.join("");
  },

  /**
   * create a new class - if you wish to extend a class take a look at
   * {{#crossLink "cls/extend:method"}}twentyc.cls.extend{{/crossLink}}
   * instead
   *
   * you may define a constructor in the definition by using the class
   * name you provide at __name__
   *
   * Note that if the name you provide is not a valid variable name
   * it will be passed through twentyc.cls.make_name to make it valid
   *
   * ##examples
   *
   * * define and instantiate a class: examples/cls.define.js
   *
   * @method define
   * @param {String} name name or unique identifier of the new class
   * @param {Object} definition object literal of properties and functions that you wish define or redefine
   * @returns {Function} dest constructor of new class
   */

  define : function(name, definition) {

    var k;

    name = twentyc.cls.make_name(name);

    if(typeof(definition[name]) == "function") {
      // a constructor has been provided
      var ctor = definition[name]
      delete definition[name]
    } else {
      // no constructor provided, substitute empty constructor
      var ctor = function(){};
    }

    // cycle through definition and copy to class prototype
    for(k in definition) {
      ctor.prototype[k] = definition[k]
    }

    // create meta information
    ctor.prototype._meta = {
      "name" : name
    }

    return ctor

  },

  /**
   * extend an existing class with new properties and functions
   *
   * if a function is defined that already exists on the parent class
   * this function will be overwritten and a reference to the original
   * function will be provided at parentClassName_functionName
   *
   * you may define a constructor in the definition by using the class
   * name you provide at __name__
   *
   * Note that if the name you provide is not a valid variable name
   * it will be passed through twentyc.cls.make_name to make it valid
   *
   * ##examples
   *
   * * extend and instantiate a class: examples/cls.extend.js
   * * handling method override: examples/cls.extend.method-override.js
   *
   * @method extend
   * @param {String} name name or unqiue identifier of the new class
   * @param {Object} definition object literal of properties and functions that you wish define or redefine
   * @param {Function} [parent] constructor of class
   * that you wish to extend, if omitted an empty function will be substituted
   * @returns {Function} dest constructor of new class
   */

  extend : function(name, definition, parent) {

    var k;
    name = twentyc.cls.make_name(name);

    if(typeof(definition[name]) == "function") {
      // a constructor has been provided
      var ctor = definition[name]
      delete definition[name]
    } else {
      // no constructor provided, substitute empty constructor
      var ctor = function(){
        parent.apply(this, arguments)
      };
    }

    // cycle through parent prototype and copy to class prototype
    for(k in parent.prototype) {
      ctor.prototype[k] = parent.prototype[k]
    }

    // cycle through definition and copy to class prototype
    for(k in definition) {
      if(typeof(ctor.prototype[k]) == "function") {
        // function was already defined by parent, store backref
        ctor.prototype[parent.prototype._meta.name+"_"+k] = parent.prototype[k];
      }
      ctor.prototype[k] = definition[k]
    }

    // reference parent constructor
    ctor.prototype[parent.prototype._meta.name] = parent

    // create meta information
    ctor.prototype._meta = {
      "name" : name,
      "parent" : parent
    }

    return ctor

  },

  /**
   * overrides a method on the provided class
   *
   * @method override
   * @param {Function} destClass A class created via __twentyc.cls.define__ or __twentyc.cls.extend__
   * @param {String} methodName name of method that you wish to override
   * @param {Function} method new method
   */

  override : function(destClass, methodName, method) {

    // create reference to old method
    if(destClass.prototype[methodName])
      destClass.prototype[destClass.prototype._meta.name+"_"+methodName] = destClass.prototype[methodName];

    // override
    destClass.prototype[methodName] = method;

  }

}

/**
 * class registry object - allows you to quickly define and extend
 * similar classes
 *
 * @module twentyc
 * @namespace twentyc.cls
 * @class Registry
 * @constructor
 */

twentyc.cls.Registry = twentyc.cls.define(
  "Registry",
  {

    Registry : function() {

      /**
       * holds the classes defined in this registry
       * @property _classes
       * @type Object
       * @private
       */

      this._classes = {}

    },

    /**
     * register a new class - look at twentyc.cls.define and twentyc.cls.extend for param
     * explanation
     * @method register
     * @param {String} name class name
     * @param {Object} definition class definition
     * @param {String} extend if passed, extend this class from this class (needs to exist in the Registry)
     * @returns {Function} class ctor of the newly created class
     */

     register : function(name, definition, extend) {
       if(this._classes[name] != undefined) {
         throw("Class with name '"+name+"' already exists - name must be unique in the Registry");
       }
       if(extend && typeof this._classes[extend] != "function") {
         throw("Trying to extend from class unknown to this Registry: "+extend);
       }
       if(extend)
         this._classes[name] = twentyc.cls.extend(name, definition, this._classes[extend]);
       else
         this._classes[name] = twentyc.cls.define(name, definition);
       return this._classes[name];
     },

     /**
      * get a registered class constructor
      * @method get
      * @param {String} name class name
      * @returns {Function} class ctor of registered class
      */

     get : function(name) {
       if(typeof this._classes[name] != "function")
         throw("Trying to retrieve class unknown to this Registry: "+name);
       return this._classes[name];
     }
  }
);

/**
 * utility functions
 * @module twentyc
 * @class util
 * @static
 */

twentyc.util = {

  /**
   * retrieve value from object literal - allows you to pass null or undefined
   * as the object and will return null if you do
   *
   * @method get
   * @param {Object} obj
   * @param {String) key
   * @param {Mixed} [default] return this if obj is null or key does not exist
   * @returns {Mixed} value
   */

  get : function(obj, key, dflt) {
    if(!obj || obj[key] == undefined)
      return dflt;
    return obj[key]
  }

}

/**
 * data retrieval, storage and management
 *
 * assures that data is only retrieved once even when multiple sources
 * are requesting it.
 *
 * data is cached locally for quick retrieval afterwards
 *
 * @module twentyc
 * @class data
 * @static
 */

twentyc.data = {

  /**
   * fires everytime a dataset is retrieved from the server - __*__ is
   * substituted with the data id
   *
   * all handlers bound to this event will be removed after its been
   * triggered - in order to permanently subscribe a load event
   * subscribe to "load"
   *
   * @event load-*
   * @param {String} id data id
   * @param {Object} data object literal of retrieved data
   */

  /**
   * fires everytime a dataset is retrieved from the server
   *
   * @event load
   * @param {String} id data id
   * @param {Object} data object literal of retrieved data
   */

  /**
   * keeps track of current loading status
   * @property _loading
   * @type Object
   * @private
   */

  _loading : {},

  /**
   * _data storage, keyed by data id
   * @property data
   * @type Object
   * @private
   */

  _data : {},

  /**
   * attempts to retrieve and return a data set
   *
   * ##example(s)
   *
   * examples/data.load.js
   *
   * @method get
   * @param {String} id data id
   * @returns {Object} data
   */

  get : function(id) {
    return tc.u.get(this._data, id, {})
  },

  /**
   * retrieve data from server. at this point this expects a json
   * string response, with the actual data keyed at the id you provided
   *
   * ##example(s)
   *
   * examples/data.load.js
   *
   * @method load
   * @param {String} id data identification key
   * @param {Object} [config] object literal holding options
   * @param {Function} [config.callback] called when data is available
   * @param {Boolean} [config.reload] if true data will be re-fetched even if already loaded
   */

  load : function(id, config) {

    var callback = tc.u.get(config, "callback");

    // check if data is already loaded
    if(this._data[id] && !tc.u.get(config, "reload")) {
      var payload = {id:id, data:this._data[id]}
      $(this).trigger("load-"+id, payload);
      if(callback)
        callback(payload)
      return;
    }

    // attach callback to load event
    if(callback) {
      $(this).on("load-"+id, function(ev, payload) { callback(payload) });
    }

    // check if data is currently being loaded
    if(this._loading[id]) {
      console.log("already loading",id,"skipping additional load")
      return;
    }

    // data is not loaded AND not currently loading, attempt to load data

    // in order to load data we need to find a suitable loader for it

    var loader = this.loaders.loader(id, config);
    this._loading[id] = new Date().getTime()
    loader.load(
      {
        success : function(data) {
          twentyc.data._data[id] = data
          twentyc.data._loading[id] = false;
          $(twentyc.data).trigger("load", { id:id, data:data} );
          $(twentyc.data).trigger("load-"+id, { id:id, data:data });
          $(twentyc.data).off("load-"+id);
        }
      }
    );
  },

}

/**
 * create and manage data loaders
 * @module twentyc
 * @namesapce twentyc.data
 * @class loaders
 * @extends twentyc.cls.Registry
 * @static
 */

twentyc.data.LoaderRegistry = twentyc.cls.extend(
  "LoaderRegistry",
  {
    LoaderRegistry : function() {
      this.Registry();

      /**
       * holds data id -> loader assignments, keyed by data id
       * @property _loaders
       * @type Object
       * @private
       */

      this._loaders = {};
    },

    /**
     * assign loader to data id
     * @method assign
     * @param {String} id data id
     * @param {String} loaderName name that you registered the loader under
     */

    assign : function(id, loaderName) {

      // this will error if loaderName is not registered
      var loader = this.get(loaderName);

      // link loader
      this._loaders[id] = loaderName;

    },

    /**
     * get loader linked to data id via __link__
     * @method loader
     * @param {String} id data_id
     * @returns {Object} loader instance of loader
     */

    loader : function(id, config) {
      if(!this._loaders[id])
        throw("Could not find suitable loader for data id "+id+", are you certain it's assigned?");

      var loader = this.get(this._loaders[id]);
      return new loader(id, config || {});
    }

  },
  twentyc.cls.Registry
);
twentyc.data.loaders = new twentyc.data.LoaderRegistry();

/**
 * any new loader you register should at the very least
 * extend this loader
 *
 * @class Base
 * @module twentyc
 * @namespace twentyc.data.loaders.get
 * @constructor
 * @param {String} id data id
 * @param {Object} [config] object literal holding config attributes
 */
twentyc.data.loaders.register(
  "Base",
  {
    Base : function(id, config) {
      this.dataId = id;
      this.config = config || {};
    },
    retrieve : function(data) {
      var set = tc.u.get(data, this.dataId)
      if(typeof set == undefined)
        return {};
      return set;
    },
    load : function() {
      throw("The load() function needs to be overwritten to do something")
    }
  }
);

/**
 * you may use this loader as a base class for any xhr data retrieval
 * loaders you define. during the ctor you will need to set the url
 * attribute on this.config
 *
 * @class Base
 * @module twentyc
 * @namespace twentyc.data.loaders.get
 * @constructor
 * @param {String} id data id
 * @param {Object} [config] object literal holding config attributes
 * @param {String} [config.url] url of the request
 * @param {Object} [config.data] parameters to send
 */

twentyc.data.loaders.register(
  "XHRGet",
  {
    load : function(callbacks) {
      var url = tc.u.get(this.config, "url");
      var loader = this;
      if(url == undefined)
        throw("XHRGet loader needs url, "+this._meta.name);
      $.ajax(
        {
          url : url,
          data : this.config.data,
          success : function(data) {
            if(typeof callbacks.success == "function")
              callbacks.success(loader.retrieve(data));
          }
        }
      ).fail(function(response) {
        if(callbacks.error)
          callbacks.error(response);
      });
    }
  },
  "Base"
);

/**
 * shortcuts
 */

tc = {
  u : twentyc.util,
  def : twentyc.cls.define,
  ext : twentyc.cls.extend
}

})();
<|endoftext|>


<commit_before>module.exports = function(neume, _) {
  "use strict";

  /**
   * $(boolean, {
   *   lag  : [number] = 0
   *   curve: [number] = 0
   * } ... inputs)
   *
   * methods:
   *   setValue(t, value)
   *   toggle(t)
   *
   * +--------+      +-------+
   * | inputs |  or  | DC(1) |
   * +--------+      +-------+
   *   ||||||
   * +-----------------------+
   * | GainNode              |
   * | - gain: value ? 0 : 1 |
   * +-----------------------+
   *   |
   */
  neume.register("boolean", function(ugen, spec, inputs) {
    var context = ugen.$context;

    var gain  = context.createGain();
    var data  = !!spec.value;
    var lag   = _.finite(spec.lag);
    var curve = _.finite(spec.curve);

    if (inputs.length === 0) {
      inputs = [ new neume.DC(context, 1) ];
    }

    inputs.forEach(function(node) {
      _.connect({ from: node, to: gain });
    });

    gain.gain.setValueAtTime(data ? 1 : 0, 0);

    function update(t0, v0, v1, nextData) {
      if (lag <= 0 || curve < 0 || 1 <= curve) {
        gain.gain.setValueAtTime(v1, t0);
      } else {
        gain.gain.setTargetAtTime(v1, t0, timeConstant(lag, v0, v1, curve));
      }
      data = nextData;
    }

    return new neume.Unit({
      outlet: gain,
      methods: {
        setValue: function(t, value) {
          if (typeof value === "boolean") {
            context.sched(t, function() {
              var v0 = data  ? 1 : 0;
              var v1 = value ? 1 : 0;
              update(t, v0, v1, value);
            });
          }
        },
        toggle: function(t) {
          context.sched(t, function() {
            var v0 = data ? 1 : 0;
            var v1 = data ? 0 : 1;
            update(t, v0, v1, !data);
          });
        }
      }
    });
  });

  function timeConstant(duration, startValue, endValue, curve) {
    var targetValue = startValue + (endValue - startValue) * (1 - curve);

    return -duration / Math.log((targetValue - endValue) / (startValue - endValue));
  }

};
<commit_msg>fix ugen/boolean: trueVal/falseVal support<commit_after>module.exports = function(neume, _) {
  "use strict";

  /**
   * $(boolean, {
   *   true : [number] = 1
   *   false: [number] = 0
   *   lag  : [number] = 0
   *   curve: [number] = 0
   * } ... inputs)
   *
   * methods:
   *   setValue(t, value)
   *   toggle(t)
   *
   * +--------+      +-------+
   * | inputs |  or  | DC(1) |
   * +--------+      +-------+
   *   ||||||
   * +------------------------------------+
   * | GainNode                           |
   * | - gain: value ? trueVal : falseVal |
   * +------------------------------------+
   *   |
   */
  neume.register("boolean", function(ugen, spec, inputs) {
    var context = ugen.$context;

    var gain  = context.createGain();
    var data  = !!spec.value;

    var trueVal  = _.finite(_.defaults(spec.true , 1));
    var falseVal = _.finite(_.defaults(spec.false, 0));
    var lag   = _.finite(spec.lag);
    var curve = _.finite(spec.curve);

    if (inputs.length === 0) {
      inputs = [ new neume.DC(context, 1) ];
    }

    inputs.forEach(function(node) {
      _.connect({ from: node, to: gain });
    });

    gain.gain.setValueAtTime(data ? trueVal : falseVal, 0);

    function update(t0, v0, v1, nextData) {
      if (lag <= 0 || curve < 0 || 1 <= curve) {
        gain.gain.setValueAtTime(v1, t0);
      } else {
        gain.gain.setTargetAtTime(v1, t0, timeConstant(lag, v0, v1, curve));
      }
      data = nextData;
    }

    return new neume.Unit({
      outlet: gain,
      methods: {
        setValue: function(t, value) {
          if (typeof value === "boolean") {
            context.sched(t, function() {
              var v0 = data  ? trueVal : falseVal;
              var v1 = value ? trueVal : falseVal;
              update(t, v0, v1, value);
            });
          }
        },
        toggle: function(t) {
          context.sched(t, function() {
            var v0 = data ? trueVal : falseVal;
            var v1 = data ? falseVal : trueVal;
            update(t, v0, v1, !data);
          });
        }
      }
    });
  });

  function timeConstant(duration, startValue, endValue, curve) {
    var targetValue = startValue + (endValue - startValue) * (1 - curve);

    return -duration / Math.log((targetValue - endValue) / (startValue - endValue));
  }

};
<|endoftext|>


<commit_before>/*
  jQuery ui.timepickr - 0.2
  http://code.google.com/p/jquery-utils/

  (c) Maxime Haineault <haineault@gmail.com>
  http://haineault.com

  MIT License (http://www.opensource.org/licenses/mit-license.php

*/

$.widget('ui.timepickr', {
    init: function() {
        var self     = this;
        var pos      = self.element.position();
        self.locked  = false;
        self.types   = [];
        self.current = {hour:1, minute:0, second:0, amPm: 'am' };

        if (self.options.showHour)   { self.types.push('hour'); }
        if (self.options.showMinute) { self.types.push('minute'); }
        if (self.options.showSecond) { self.types.push('second'); }
        if (self.options.showAmPm)   { self.types.push('amPm'); }

        self.ui = {
            wrapper: $('
').css({left: pos.left}),
            clear:  function(){ return $('
'); }
        };

        for (var i in self.types) {
            var type = self.types[i];
            self.ui[type] = $($.format('
', type))
                .mousemove(function(e){ self.events.mousemove.apply(this, [e, self]); })
                .appendTo(self.ui.wrapper);
            self.ui.wrapper.append(self.ui.clear());
            self.populateList(type);
        }

        self.element
            .addClass('ui-timepickr-field ')
            .blur(function(){  self.hide(); })
            .focus(function(){
                   self.locked = false;
                   self.show(); });

        $(self.options.trigger)
            .bind(self.options.triggerEvent, function(){
                  self.locked = false; });

        if (self.options.val && !self.element.val()) {
             self.element.val(self.options.val)
        }

        $(self.ui.wrapper)
            .insertAfter(self.element);
    },
    populateList: function(type) {
        var self   = this;
        var range  = self.getRange(type);
        for (var i in range) {
            $($.format('
', type))
                .mouseover(function(e){ self.events.mouseover.apply(this, [e, self]); })
                .click(function(e){ self.select(); })
                .appendTo(self.ui[type])
                .text($.format(self.options.formats[type] || '', range[i]));
        }
    },
    hover: function() {
        var self = this;
        if (arguments.length < 3 && typeof(arguments[0]) == 'string') { // type, value
            self.current[arguments[0]] = arguments[1];
        }
        else { // hour, min, sec
            self.current['hour']   = arguments[0];
            self.current['minute'] = arguments[1];
            self.current['second'] = arguments[2];
            self.current['amPm']   = (arguments[3] && arguments[3] == 'pm') ? 'pm' : 'am';
        }
        self.update();
    },
    update: function() {
        var self = this;
        self.element.val($.format(self.options.formats['field'], {
                    hour:parseInt(self.current.hour, 10),
                    min: parseInt(self.current.minute || 0, 10),
                    sec: parseInt(self.current.second || 0, 10),
                    amPm: self.current.amPm || 'am'}));
    },
    events: {
        mousemove: function(e, timepickr) {
            var type = $(this).attr('class').match(/ui-timepickr-(hour|minute|second|amPm)/)[1];
            var idx  = timepickr.types.indexOf(type);
            if (timepickr.types[idx+1]) {
                timepickr.reposition.apply(timepickr, [timepickr.types[idx+1]]);
            }
        },
        mouseover: function(e, timepickr) {
            if (!timepickr.locked) {
                var type = $(this).parent().attr('class').match(/ui-timepickr-(hour|minute|second|amPm)/)[1];
                var idx  = timepickr.types.indexOf(type);
                $(this).parent().find('li').removeClass('hover');
                $(this).addClass('hover');
                timepickr.hover(type, $(this).text());
                if (timepickr.types[idx+1]) {
                    timepickr.show(timepickr.types[idx+1]);
                }
            }
        }
    },
    propagate: function(func, args) {
        var self = this;
        for (i in self.types) {
            var type = self.types[i];
            func.apply(self.ui[type], args || []);
        }
    },
    reposition: function(pickr) {
        var self   = this;
        var prevLI = false;
        var prevOL = false;
        var nextOL = false;
        var method = self.options.repSpeed > 10 && 'animate' || 'css';
        var offset = 0;
        self.ui.wrapper.find('ol').each(function(){
            prevOL = $(this).prevAll('ol:visible:first');
            if (prevOL.get(0)) {
                prevLI = prevOL.find('li.hover, li:first').eq(0);
                $(this).css({left: prevLI.position().left + offset});
                offset = offset + prevLI.position().left;
            }
        });
    },
    select: function() {
        var self = this;
        self.locked = true;
        self.hide();
        self.update();
    },
    show: function(pickr) {
        var self  = this;
        var pickr = pickr || 'hour';
        setTimeout(function(){
            self.signals('onOpen');
            self.options.show.apply(self.ui[pickr], [self.options.speed])
            self.reposition.apply(self, [pickr]);
            self.signals('onOpened');
        }, self.options.showDelay * 1000);
    },
    hide: function() {
        var self = this;
        setTimeout(function(){
            self.signals('onClose');
            self.propagate(self.options.hide, [self.options.speed]);
            self.signals('onClosed');
        }, self.options.hideDelay * 1000);
    },
    signals: function(type, args) {
        var self = this;
        if (self.options[type] && $.isFunction(self.options[type])) {
            self.options[type].apply(self, args || []);
        }
    },
    getRange: function(type) {
        var self = this;
        if (typeof(self.options[type]) ==  'string') {
            var r = self.options[type].split('-');
            return $.range(r[0], r[1]);
        }
        return self.options[type];
    }
});

$.ui.timepickr.defaults = {
    hour:         [1,2,3,4,5,6,7,8,9,10,11,12], // available hours to pick
    minute:       [0, 15, 30, 45],  // available minutes to pick
    second:       [0, 15, 30, 45],  // available seconds to pick
    amPm:         ['am', 'pm'],     // AM/PM labels
    showHour:     true,
    showMinute:   true,
    showSecond:   false,
    showAmPm:     true,
	showDelay:    0,                // delay before showing (seconds)
	hideDelay:    0.3,              // delay before hide (seconds)
	timeout:      0,                // time before automatically hiding (seconds, 0 == never)
	speed:        'fast',           // animations speed
	onClose:      false,            // callback before closing
	onClosed:     false,            // callback after closing
	onOpen:       false,            // callback before opening
	onOpened:     false,            // callback after opening
	onHide:       false,            // callback when closed by user
	show:	      $.fn.slideDown,   // showing effect
	hide:	      $.fn.fadeOut,     // closing effect (by user)
    repSpeed:     0,                // reposition speed
    repDelay:     0,                // reposition delay
    val:          false,            // default value
    trigger:      false,            // specify an element which will open the picker upon triggerEvent (click)
    triggerEvent: 'click',          // trigger's event
    formats: {
        field:  '{hour:02d}:{min:02d} {amPm:s}',
        hour:   '{0:02d}',
        minute: '{0:02d}',
        second: '{0:02d}',
        amPm:   '{0}'
    }
};
<commit_msg>- ui.timepickr.js: fixed trigger<commit_after>/*
  jQuery ui.timepickr - 0.2
  http://code.google.com/p/jquery-utils/

  (c) Maxime Haineault <haineault@gmail.com>
  http://haineault.com

  MIT License (http://www.opensource.org/licenses/mit-license.php

*/

$.widget('ui.timepickr', {
    init: function() {
        var self     = this;
        var pos      = self.element.position();
        self.locked  = false;
        self.types   = [];
        self.current = {hour:1, minute:0, second:0, amPm: 'am' };

        if (self.options.showHour)   { self.types.push('hour'); }
        if (self.options.showMinute) { self.types.push('minute'); }
        if (self.options.showSecond) { self.types.push('second'); }
        if (self.options.showAmPm)   { self.types.push('amPm'); }

        self.ui = {
            wrapper: $('
').css({left: pos.left}),
            clear:  function(){ return $('
'); }
        };

        for (var i in self.types) {
            var type = self.types[i];
            self.ui[type] = $($.format('
', type))
                .mousemove(function(e){ self.events.mousemove.apply(this, [e, self]); })
                .appendTo(self.ui.wrapper);
            self.ui.wrapper.append(self.ui.clear());
            self.populateList(type);
        }

        self.element
            .addClass('ui-timepickr-field ')
            .blur(function(){  self.hide(); })
            .focus(function(){
                   self.locked = false;
                   self.show(); });

        $(self.options.trigger)
            .bind(self.options.triggerEvent, function(){
                   self.locked = false;
                   self.show(); });

        if (self.options.val && !self.element.val()) {
             self.element.val(self.options.val)
        }

        $(self.ui.wrapper)
            .insertAfter(self.element);
    },
    populateList: function(type) {
        var self   = this;
        var range  = self.getRange(type);
        for (var i in range) {
            $($.format('
', type))
                .mouseover(function(e){ self.events.mouseover.apply(this, [e, self]); })
                .click(function(e){ self.select(); })
                .appendTo(self.ui[type])
                .text($.format(self.options.formats[type] || '', range[i]));
        }
    },
    hover: function() {
        var self = this;
        if (arguments.length < 3 && typeof(arguments[0]) == 'string') { // type, value
            self.current[arguments[0]] = arguments[1];
        }
        else { // hour, min, sec
            self.current['hour']   = arguments[0];
            self.current['minute'] = arguments[1];
            self.current['second'] = arguments[2];
            self.current['amPm']   = (arguments[3] && arguments[3] == 'pm') ? 'pm' : 'am';
        }
        self.update();
    },
    update: function() {
        var self = this;
        self.element.val($.format(self.options.formats['field'], {
                    hour:parseInt(self.current.hour, 10),
                    min: parseInt(self.current.minute || 0, 10),
                    sec: parseInt(self.current.second || 0, 10),
                    amPm: self.current.amPm || 'am'}));
    },
    events: {
        mousemove: function(e, timepickr) {
            var type = $(this).attr('class').match(/ui-timepickr-(hour|minute|second|amPm)/)[1];
            var idx  = timepickr.types.indexOf(type);
            if (timepickr.types[idx+1]) {
                timepickr.reposition.apply(timepickr, [timepickr.types[idx+1]]);
            }
        },
        mouseover: function(e, timepickr) {
            if (!timepickr.locked) {
                var type = $(this).parent().attr('class').match(/ui-timepickr-(hour|minute|second|amPm)/)[1];
                var idx  = timepickr.types.indexOf(type);
                $(this).parent().find('li').removeClass('hover');
                $(this).addClass('hover');
                timepickr.hover(type, $(this).text());
                if (timepickr.types[idx+1]) {
                    timepickr.show(timepickr.types[idx+1]);
                }
            }
        }
    },
    propagate: function(func, args) {
        var self = this;
        for (i in self.types) {
            var type = self.types[i];
            func.apply(self.ui[type], args || []);
        }
    },
    reposition: function(pickr) {
        var self   = this;
        var prevLI = false;
        var prevOL = false;
        var nextOL = false;
        var method = self.options.repSpeed > 10 && 'animate' || 'css';
        var offset = 0;
        self.ui.wrapper.find('ol').each(function(){
            prevOL = $(this).prevAll('ol:visible:first');
            if (prevOL.get(0)) {
                prevLI = prevOL.find('li.hover, li:first').eq(0);
                $(this).css({left: prevLI.position().left + offset});
                offset = offset + prevLI.position().left;
            }
        });
    },
    select: function() {
        var self = this;
        self.locked = true;
        self.hide();
        self.update();
    },
    show: function(pickr) {
        var self  = this;
        var pickr = pickr || 'hour';
        setTimeout(function(){
            self.signals('onOpen');
            self.options.show.apply(self.ui[pickr], [self.options.speed])
            self.reposition.apply(self, [pickr]);
            self.signals('onOpened');
        }, self.options.showDelay * 1000);
    },
    hide: function() {
        var self = this;
        setTimeout(function(){
            self.signals('onClose');
            self.propagate(self.options.hide, [self.options.speed]);
            self.signals('onClosed');
        }, self.options.hideDelay * 1000);
    },
    signals: function(type, args) {
        var self = this;
        if (self.options[type] && $.isFunction(self.options[type])) {
            self.options[type].apply(self, args || []);
        }
    },
    getRange: function(type) {
        var self = this;
        if (typeof(self.options[type]) ==  'string') {
            var r = self.options[type].split('-');
            return $.range(r[0], r[1]);
        }
        return self.options[type];
    }
});

$.ui.timepickr.defaults = {
    hour:         [1,2,3,4,5,6,7,8,9,10,11,12], // available hours to pick
    minute:       [0, 15, 30, 45],  // available minutes to pick
    second:       [0, 15, 30, 45],  // available seconds to pick
    amPm:         ['am', 'pm'],     // AM/PM labels
    showHour:     true,
    showMinute:   true,
    showSecond:   false,
    showAmPm:     true,
	showDelay:    0,                // delay before showing (seconds)
	hideDelay:    0.3,              // delay before hide (seconds)
	timeout:      0,                // time before automatically hiding (seconds, 0 == never)
	speed:        'fast',           // animations speed
	onClose:      false,            // callback before closing
	onClosed:     false,            // callback after closing
	onOpen:       false,            // callback before opening
	onOpened:     false,            // callback after opening
	onHide:       false,            // callback when closed by user
	show:	      $.fn.slideDown,   // showing effect
	hide:	      $.fn.fadeOut,     // closing effect (by user)
    repSpeed:     0,                // reposition speed
    repDelay:     0,                // reposition delay
    val:          false,            // default value
    trigger:      false,            // specify an element which will open the picker upon triggerEvent (click)
    triggerEvent: 'click',          // trigger's event
    formats: {
        field:  '{hour:02d}:{min:02d} {amPm:s}',
        hour:   '{0:02d}',
        minute: '{0:02d}',
        second: '{0:02d}',
        amPm:   '{0}'
    }
};
<|endoftext|>


<commit_before>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

var Component = this.Component = Base.extend(Callback, /** @lends Component# */{
	_events: [ 'onChange', 'onClick' ],

	_types: {
		'boolean': {
			type: 'checkbox',
			value: 'checked'
		},

		string: {
			type: 'text'
		},

		number: {
			type: 'number',
			number: true
		},

		button: {
			type: 'button'
		},

		text: {
			tag: 'div',
			value: 'text'
		},

		slider: {
			type: 'range',
			number: true
		},

		list: {
			tag: 'select',

			options: function() {
				DomElement.removeChildren(this._inputItem);
				DomElement.create(Base.each(this._options, function(option) {
					this.push('option', { value: option, text: option });
				}, []), this._inputItem);
			}
		}
	},

	initialize: function(obj) {
		this._type = obj.type
			|| ('options' in obj
				? 'list'
				: 'onClick' in obj
					? 'button'
					: typeof value);
		this._info = this._types[this._type] || { type: this._type };
		var that = this,
			fireChange = false;
		this._inputItem = DomElement.create(this._info.tag || 'input', {
			type: this._info.type,
			events: {
				change: function() {
					that.setValue(
						DomElement.get(this, that._info.value || 'value'));
					if (fireChange) {
						that._palette.fire('change', that, that.name, value);
						that.fire('change', value);
					}
				},
				click: function() {
					that.fire('click');
				}
			}
		});
		this._element = DomElement.create('tr', [
			this._labelItem = DomElement.create('td'),
			'td', this._inputItem
		]);
		Base.each(obj, function(value, key) {
			this[key] = value;
		}, this);
		this._defaultValue = this._value;
		// Only fire change events after we have initalized
		fireChange = true;
	},

	getType: function() {
		return this._type;
	},

	getLabel: function() {
		return this._label;
	},

	setLabel: function(label) {
		this._label = label;
		DomElement.set(this._labelItem, 'text', label + ':');
	},

	getOptions: function() {
		return this._options;
	},

	setOptions: function(options) {
		this._options = options;
		if (this._info.options)
			this._info.options.call(this);
	},

	getValue: function() {
		return this._value;
	},

	setValue: function(value) {
		var key = this._info.value || 'value';
		DomElement.set(this._inputItem, key, value);
		// Read back and convert from input again, to make sure we're in sync
		value = DomElement.get(this._inputItem, key);
		this._value = this._info.number ? Base.toFloat(value) : value;
	},

	getRange: function() {
		return [toFloat(DomElement.get(this._inputItem, 'min')),
				toFloat(DomElement.get(this._inputItem, 'max'))];
	},

	setRange: function(min, max) {
		var range = Array.isArray(min) ? min : [min, max];
		DomElement.set(this._inputItem, { min: range[0], max: range[1] });
	},

	getMin: function() {
		return getRange()[0];
	},

	setMin: function(min) {
		this.setRange(min, getMax());
	},

	getMax: function() {
		return getRange()[1];
	},

	setMax: function(max) {
		this.setRange(getMin(), max);
	},

	getStep: function() {
		return toFloat(DomElement.get(this._inputItem, 'step'));
	},

	setStep: function(step) {
		DomElement.set(this._inputItem, 'step', step);
	},

	reset: function() {
		this.setValue(this._defaultValue);
	}
});<commit_msg>Fix small newly introduced bug.<commit_after>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

var Component = this.Component = Base.extend(Callback, /** @lends Component# */{
	_events: [ 'onChange', 'onClick' ],

	_types: {
		'boolean': {
			type: 'checkbox',
			value: 'checked'
		},

		string: {
			type: 'text'
		},

		number: {
			type: 'number',
			number: true
		},

		button: {
			type: 'button'
		},

		text: {
			tag: 'div',
			value: 'text'
		},

		slider: {
			type: 'range',
			number: true
		},

		list: {
			tag: 'select',

			options: function() {
				DomElement.removeChildren(this._inputItem);
				DomElement.create(Base.each(this._options, function(option) {
					this.push('option', { value: option, text: option });
				}, []), this._inputItem);
			}
		}
	},

	initialize: function(obj) {
		this._type = obj.type
			|| ('options' in obj
				? 'list'
				: 'onClick' in obj
					? 'button'
					: typeof value);
		this._info = this._types[this._type] || { type: this._type };
		var that = this,
			fireChange = false;
		this._inputItem = DomElement.create(this._info.tag || 'input', {
			type: this._info.type,
			events: {
				change: function() {
					that.setValue(
						DomElement.get(this, that._info.value || 'value'));
					if (fireChange) {
						that._palette.fire('change', that, that.name, that._value);
						that.fire('change', that._value);
					}
				},
				click: function() {
					that.fire('click');
				}
			}
		});
		this._element = DomElement.create('tr', [
			this._labelItem = DomElement.create('td'),
			'td', this._inputItem
		]);
		Base.each(obj, function(value, key) {
			this[key] = value;
		}, this);
		this._defaultValue = this._value;
		// Only fire change events after we have initalized
		fireChange = true;
	},

	getType: function() {
		return this._type;
	},

	getLabel: function() {
		return this._label;
	},

	setLabel: function(label) {
		this._label = label;
		DomElement.set(this._labelItem, 'text', label + ':');
	},

	getOptions: function() {
		return this._options;
	},

	setOptions: function(options) {
		this._options = options;
		if (this._info.options)
			this._info.options.call(this);
	},

	getValue: function() {
		return this._value;
	},

	setValue: function(value) {
		var key = this._info.value || 'value';
		DomElement.set(this._inputItem, key, value);
		// Read back and convert from input again, to make sure we're in sync
		value = DomElement.get(this._inputItem, key);
		this._value = this._info.number ? Base.toFloat(value) : value;
	},

	getRange: function() {
		return [toFloat(DomElement.get(this._inputItem, 'min')),
				toFloat(DomElement.get(this._inputItem, 'max'))];
	},

	setRange: function(min, max) {
		var range = Array.isArray(min) ? min : [min, max];
		DomElement.set(this._inputItem, { min: range[0], max: range[1] });
	},

	getMin: function() {
		return getRange()[0];
	},

	setMin: function(min) {
		this.setRange(min, getMax());
	},

	getMax: function() {
		return getRange()[1];
	},

	setMax: function(max) {
		this.setRange(getMin(), max);
	},

	getStep: function() {
		return toFloat(DomElement.get(this._inputItem, 'step'));
	},

	setStep: function(step) {
		DomElement.set(this._inputItem, 'step', step);
	},

	reset: function() {
		this.setValue(this._defaultValue);
	}
});<|endoftext|>


<commit_before>  /* eslint-env browser */

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

  Firepack - Index

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

import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router, browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import noop from 'lodash/noop';

import createReducer from './reducer';
import createStore from './store';

/**
 *  Firepack
 */
export default class extends Component {
  static displayName = 'Firepack';

  static propTypes = {
    appTitle: PropTypes.node.isRequired,
    appDescription: PropTypes.node.isRequired,
    routes: PropTypes.object.isRequired,
    reducer: PropTypes.func.isRequired,
    firebaseConfig: PropTypes.object.isRequired,
    firebaseAuthProviders: PropTypes.arrayOf(
      PropTypes.string.isRequired
    ).isRequired,
  };

  static defaultProps = {
    appTitle: 'Firepack',
    appDescription: 'Firebase application wrapper',
    routes: {},
    reducer: noop,
    firebaseConfig: {},
    firebaseAuthProviders: ['Google'],
  };

  static childContextTypes = {
    appTitle: PropTypes.node,
    appDescription: PropTypes.node,
    firebaseConfig: PropTypes.object,
    firebaseAuthProviders: PropTypes.array,
  };

  getChildContext() {
    const { appTitle, appDescription, firebaseConfig, firebaseAuthProviders } = this.props;

    return {
      appTitle,
      appDescription,
      firebaseConfig,
      firebaseAuthProviders,
    };
  }

  render() {
    const { routes, reducer } = this.props;

    const store = createStore(createReducer(reducer), {});
    const history = syncHistoryWithStore(browserHistory, store);

    return (
      <Provider store={store}>
        <Router history={history} routes={routes} />
      </Provider>
    );
  }
}
<commit_msg>refactor(firepack): update firepack default description<commit_after>  /* eslint-env browser */

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

  Firepack - Index

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

import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router, browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import noop from 'lodash/noop';

import createReducer from './reducer';
import createStore from './store';

/**
 *  Firepack
 */
export default class extends Component {
  static displayName = 'Firepack';

  static propTypes = {
    appTitle: PropTypes.node.isRequired,
    appDescription: PropTypes.node.isRequired,
    routes: PropTypes.object.isRequired,
    reducer: PropTypes.func.isRequired,
    firebaseConfig: PropTypes.object.isRequired,
    firebaseAuthProviders: PropTypes.arrayOf(
      PropTypes.string.isRequired
    ).isRequired,
  };

  static defaultProps = {
    appTitle: 'Firepack',
    appDescription: 'Auth wrapper for Firebase applications built with React and Redux',
    routes: {},
    reducer: noop,
    firebaseConfig: {},
    firebaseAuthProviders: ['Google'],
  };

  static childContextTypes = {
    appTitle: PropTypes.node,
    appDescription: PropTypes.node,
    firebaseConfig: PropTypes.object,
    firebaseAuthProviders: PropTypes.array,
  };

  getChildContext() {
    const { appTitle, appDescription, firebaseConfig, firebaseAuthProviders } = this.props;

    return {
      appTitle,
      appDescription,
      firebaseConfig,
      firebaseAuthProviders,
    };
  }

  render() {
    const { routes, reducer } = this.props;

    const store = createStore(createReducer(reducer), {});
    const history = syncHistoryWithStore(browserHistory, store);

    return (
      <Provider store={store}>
        <Router history={history} routes={routes} />
      </Provider>
    );
  }
}
<|endoftext|>


<commit_before>export const defaultColorBy = "region";
export const date_select = true;
export const file_prefix = "Zika_";
export const branchLabels = false;
export const restrictTo = {"region": "all"};
export const time_window = 3.0;
export const fullDataTimeWindow = 1.5;
export const time_ticks = [2013.0, 2013.5, 2014.0, 2014.5, 2015.0, 2015.5, 2016.0];
export const dfreq_dn = 2;
export const reallySmallNumber = -100000000;
export const reallyBigNumber = 10000000;
export const LBItime_window = 0.5;
export const LBItau = 0.0005;
export const mutType = "nuc";
export const default_gene = "nuc";
export const plot_frequencies = false;
export const genericDomain = [ 0, 0.111, 0.222, 0.333, 0.444, 0.555, 0.666, 0.777, 0.888, 1.0 ];
export const epiColorDomain = genericDomain;
export const nonEpiColorDomain = genericDomain;
export const rbsColorDomain = genericDomain;
export const dateColorDomain = genericDomain;
export const legendRectSize = 15;
export const legendSpacing = 4;
export const nonTipNodeRadius = 0;
export const tipRadius = 4;
export const tipRadiusOnLegendMatchMultiplier = 1.7;
export const HIColorDomain = genericDomain.map((d) => {
  return Math.round(100 * (d * 3.6)) / 100;
});
export const dfreqColorDomain = genericDomain.map((d) => {
  return Math.round(100 * (0.2 + d * 1.8)) / 100;
});
export const fitnessColorDomain = genericDomain.map((d) => {
  return Math.round(100 * ((d - 0.5) * 16.0)) / 100;
});
export const colors = [
  [],
  ["#8EBC66"],
  ["#4D92BF", "#E4662E"],
  ["#4B8FC1", "#AABD52", "#E3612D"],
  ["#4A8BC3", "#82BA72", "#CFB541", "#E25B2C"],
  ["#4988C5", "#6EB389", "#AABD52", "#DEA73C", "#E2562B"],
  ["#4785C7", "#64AD99", "#90BC65", "#C3BA46", "#E39A39", "#E1512A"],
  ["#4682C9", "#5CA7A4", "#7FB975", "#AABD52", "#D2B340", "#E68F36", "#E04C29"],
  ["#457FCB", "#57A1AD", "#73B584", "#96BD5F", "#BDBB49", "#DBAC3D", "#E68334", "#DF4628"],
  ["#447BCD", "#539CB4", "#6AB090", "#88BB6C", "#AABD52", "#CBB842", "#E0A23A", "#E67A32", "#DF4127"],
  ["#4377CD", "#5097BA", "#63AC9A", "#7CB879", "#9ABE5C", "#B9BC4A", "#D4B13F", "#E49938", "#E67030", "#DE3C26"],
  ["#4273CE", "#4D93BE", "#5DA8A3", "#73B584", "#8DBC68", "#AABD52", "#C6B945", "#DBAC3D", "#E69036", "#E4672E", "#DD3725"],
  ["#426FCE", "#4B8DC2", "#59A3AA", "#6BB18D", "#82BA71", "#9CBE5B", "#B7BD4B", "#CFB541", "#DFA43B", "#E68735", "#E35E2D", "#DD3124"]
];
export const genotypeColors = [
  "#60AA9E",
  "#D9AD3D",
  "#5097BA",
  "#E67030",
  "#8EBC66",
  "#E59637",
  "#AABD52",
  "#DF4327",
  "#C4B945",
  "#75B681"
];
export const regions = [
  ["french_polynesia", "#3E58CF"],
  ["american_samoa", "#426FCE"],
  ["china", "#4784C8"],
  ["brazil", "#72B485"],
  ["colombia", "#81BA72"],
  ["venezuela", "#92BC63"],
  ["suriname", "#A4BE56"],
  ["guatemala", "#B6BD4C"],
  ["haiti", "#C6B944"],
  ["martinique", "#D4B13F"],
  ["puerto_rico", "#DEA63B"],
  ["mexico", "#E59637"],
  ["dominican_republic", "#E67E33"],
  ["panama", "#E4632E"]
];
<commit_msg>add constant scales to globals<commit_after>export const defaultColorBy = "region";
export const date_select = true;
export const file_prefix = "Zika_";
export const branchLabels = false;
export const restrictTo = {"region": "all"};
export const time_window = 3.0;
export const fullDataTimeWindow = 1.5;
export const time_ticks = [2013.0, 2013.5, 2014.0, 2014.5, 2015.0, 2015.5, 2016.0];
export const dfreq_dn = 2;
export const reallySmallNumber = -100000000;
export const reallyBigNumber = 10000000;
export const LBItime_window = 0.5;
export const LBItau = 0.0005;
export const mutType = "nuc";
export const default_gene = "nuc";
export const plot_frequencies = false;
export const genericDomain = [ 0, 0.111, 0.222, 0.333, 0.444, 0.555, 0.666, 0.777, 0.888, 1.0 ];
export const epiColorDomain = genericDomain;
export const nonEpiColorDomain = genericDomain;
export const rbsColorDomain = genericDomain;
export const dateColorDomain = genericDomain;
export const legendRectSize = 15;
export const legendSpacing = 4;
export const nonTipNodeRadius = 0;
export const tipRadius = 4;
export const tipRadiusOnLegendMatchMultiplier = 1.7;
export const HIColorDomain = genericDomain.map((d) => {
  return Math.round(100 * (d * 3.6)) / 100;
});
export const dfreqColorDomain = genericDomain.map((d) => {
  return Math.round(100 * (0.2 + d * 1.8)) / 100;
});
export const fitnessColorDomain = genericDomain.map((d) => {
  return Math.round(100 * ((d - 0.5) * 16.0)) / 100;
});
export const dHIScale = d3.scale.linear()
  .domain([0, 1])
  .range([2.0, 4.5]);

export const freqScale = d3.scale.sqrt()
  .domain([0, 1])
  .range([1, 10]);

export const distanceScale = d3.scale.sqrt()
  .domain([3, 20])
  .range([9, 3])
  .clamp([true]);

export const colors = [
  [],
  ["#8EBC66"],
  ["#4D92BF", "#E4662E"],
  ["#4B8FC1", "#AABD52", "#E3612D"],
  ["#4A8BC3", "#82BA72", "#CFB541", "#E25B2C"],
  ["#4988C5", "#6EB389", "#AABD52", "#DEA73C", "#E2562B"],
  ["#4785C7", "#64AD99", "#90BC65", "#C3BA46", "#E39A39", "#E1512A"],
  ["#4682C9", "#5CA7A4", "#7FB975", "#AABD52", "#D2B340", "#E68F36", "#E04C29"],
  ["#457FCB", "#57A1AD", "#73B584", "#96BD5F", "#BDBB49", "#DBAC3D", "#E68334", "#DF4628"],
  ["#447BCD", "#539CB4", "#6AB090", "#88BB6C", "#AABD52", "#CBB842", "#E0A23A", "#E67A32", "#DF4127"],
  ["#4377CD", "#5097BA", "#63AC9A", "#7CB879", "#9ABE5C", "#B9BC4A", "#D4B13F", "#E49938", "#E67030", "#DE3C26"],
  ["#4273CE", "#4D93BE", "#5DA8A3", "#73B584", "#8DBC68", "#AABD52", "#C6B945", "#DBAC3D", "#E69036", "#E4672E", "#DD3725"],
  ["#426FCE", "#4B8DC2", "#59A3AA", "#6BB18D", "#82BA71", "#9CBE5B", "#B7BD4B", "#CFB541", "#DFA43B", "#E68735", "#E35E2D", "#DD3124"]
];
export const genotypeColors = [
  "#60AA9E",
  "#D9AD3D",
  "#5097BA",
  "#E67030",
  "#8EBC66",
  "#E59637",
  "#AABD52",
  "#DF4327",
  "#C4B945",
  "#75B681"
];
export const regions = [
  ["french_polynesia", "#3E58CF"],
  ["american_samoa", "#426FCE"],
  ["china", "#4784C8"],
  ["brazil", "#72B485"],
  ["colombia", "#81BA72"],
  ["venezuela", "#92BC63"],
  ["suriname", "#A4BE56"],
  ["guatemala", "#B6BD4C"],
  ["haiti", "#C6B944"],
  ["martinique", "#D4B13F"],
  ["puerto_rico", "#DEA63B"],
  ["mexico", "#E59637"],
  ["dominican_republic", "#E67E33"],
  ["panama", "#E4632E"]
];
<|endoftext|>