<commit_before>/*
 * Instantiate registry extension
 *
 * Supports Traceur System.register 'instantiate' output for loading ES6 as ES5.
 *
 * - Creates the loader.register function
 * - Also supports metadata.format = 'register' in instantiate for anonymous register modules
 * - Also supports metadata.deps, metadata.execute and metadata.executingRequire
 *     for handling dynamic modules alongside register-transformed ES6 modules
 *
 * Works as a standalone extension, but benefits from having a more
 * advanced __eval defined like in SystemJS polyfill-wrapper-end.js
 *
 * The code here replicates the ES6 linking groups algorithm to ensure that
 * circular ES6 compiled into System.register can work alongside circular AMD
 * and CommonJS, identically to the actual ES6 loader.
 *
 */
function register(loader) {
  if (typeof indexOf == 'undefined')
    indexOf = Array.prototype.indexOf;
  if (typeof __eval == 'undefined')
    __eval = 0 || eval; // uglify breaks without the 0 ||

  // define exec for easy evaluation of a load record (load.name, load.source, load.address)
  // main feature is source maps support handling
  var curSystem;
  function exec(load) {
    var loader = this;
    if (load.name == '@traceur') {
      curSystem = System;
    }
    // support sourceMappingURL (efficiently)
    var sourceMappingURL;
    var lastLineIndex = load.source.lastIndexOf('\n');
    if (lastLineIndex != -1) {
      if (load.source.substr(lastLineIndex + 1, 21) == '//# sourceMappingURL=') {
        sourceMappingURL = load.source.substr(lastLineIndex + 22, load.source.length - lastLineIndex - 22);
        if (typeof toAbsoluteURL != 'undefined')
          sourceMappingURL = toAbsoluteURL(load.address, sourceMappingURL);
      }
    }

    __eval(load.source, loader.global, load.address, sourceMappingURL);

    // traceur overwrites System and Module - write them back
    if (load.name == '@traceur') {
      loader.global.traceurSystem = loader.global.System;
      loader.global.System = curSystem;
    }
  }
  loader.__exec = exec;

  function dedupe(deps) {
    var newDeps = [];
    for (var i = 0; i < deps.length; i++)
      if (indexOf.call(newDeps, deps[i]) == -1)
        newDeps.push(deps[i])
    return newDeps;
  }

  // There are two variations of System.register:
  // 1. System.register for ES6 conversion (2-3 params) - System.register([name, ]deps, declare)
  //    see https://github.com/ModuleLoader/es6-module-loader/wiki/System.register-Explained
  //
  // 2. System.register for dynamic modules (3-4 params) - System.register([name, ]deps, executingRequire, execute)
  // the true or false statement

  // this extension implements the linking algorithm for the two variations identical to the spec
  // allowing compiled ES6 circular references to work alongside AMD and CJS circular references.

  // loader.register sets loader.defined for declarative modules
  var anonRegister;
  var calledRegister;
  function register(name, deps, declare, execute) {
    if (typeof name != 'string') {
      execute = declare;
      declare = deps;
      deps = name;
      name = null;
    }

    calledRegister = true;

    var register;

    // dynamic
    if (typeof declare == 'boolean') {
      register = {
        declarative: false,
        deps: deps,
        execute: execute,
        executingRequire: declare
      };
    }
    else {
      // ES6 declarative
      if (deps.length > 0 && declare.length != 1)
        throw 'Invalid System.register form for ' + name + '. Declare function must take one argument.';
      register = {
        declarative: true,
        deps: deps,
        declare: declare
      };
    }

    // named register
    if (name) {
      // we never overwrite an existing define
      if (!loader.defined[name])
        loader.defined[name] = register;
    }
    // anonymous register
    else if (register.declarative) {
      if (anonRegister)
        throw 'Multiple anonymous System.register calls in the same module file.';
      anonRegister = register;
    }
  }

  // Registry side table - loader.defined
  // Registry Entry Contains:
  //    - deps
  //    - declare for register modules
  //    - execute for dynamic modules, also after declare for declarative modules
  //    - executingRequire indicates require drives execution for circularity of dynamic modules
  //    - declarative optional boolean indicating which of the above
  //
  // Can preload modules directly on System.defined['my/module'] = { deps, execute, executingRequire }
  //
  // Then the entry gets populated with derived information during processing:
  //    - normalizedDeps derived from deps, created in instantiate
  //    - depMap array derived from deps, populated gradually in link
  //    - groupIndex used by group linking algorithm
  //    - module a raw module exports object with no wrapper
  //    - evaluated indiciating whether evaluation has happend for declarative modules
  // After linked and evaluated, entries are removed

  function defineRegister(loader) {
    if (loader.register)
      return;

    loader.register = register;

    if (!loader.defined)
      loader.defined = {};

    // script injection mode calls this function synchronously on load
    var onScriptLoad = loader.onScriptLoad;
    loader.onScriptLoad = function(load) {
      onScriptLoad(load);
      // anonymous define
      if (anonRegister)
        load.metadata.entry = anonRegister;

      if (anonRegister || calledRegister)
        load.metadata.format = load.metadata.format || 'register';
      if (calledRegister)
        load.metadata.registered = true;
    }
  }

  defineRegister(loader);

  function buildGroups(entry, loader, groups) {
    groups[entry.groupIndex] = groups[entry.groupIndex] || [];

    if (indexOf.call(groups[entry.groupIndex], entry) != -1)
      return;

    groups[entry.groupIndex].push(entry);

    for (var i = 0; i < entry.normalizedDeps.length; i++) {
      var depName = entry.normalizedDeps[i];
      var depEntry = loader.defined[depName];

      // not in the registry means already linked / ES6
      if (!depEntry || depEntry.evaluated)
        continue;

      // now we know the entry is in our unlinked linkage group
      var depGroupIndex = entry.groupIndex + (depEntry.declarative != entry.declarative);

      // the group index of an entry is always the maximum
      if (depEntry.groupIndex === undefined || depEntry.groupIndex < depGroupIndex) {

        // if already in a group, remove from the old group
        if (depEntry.groupIndex) {
          groups[depEntry.groupIndex].splice(groups[depEntry.groupIndex].indexOf(depEntry), 1);

          // if the old group is empty, then we have a mixed depndency cycle
          if (groups[depEntry.groupIndex].length == 0)
            throw new TypeError("Mixed dependency cycle detected");
        }

        depEntry.groupIndex = depGroupIndex;
      }

      buildGroups(depEntry, loader, groups);
    }
  }

  function link(name, loader) {
    var startEntry = loader.defined[name];

    startEntry.groupIndex = 0;

    var groups = [];

    buildGroups(startEntry, loader, groups);

    var curGroupDeclarative = !!startEntry.declarative == groups.length % 2;
    for (var i = groups.length - 1; i >= 0; i--) {
      var group = groups[i];
      for (var j = 0; j < group.length; j++) {
        var entry = group[j];

        // link each group
        if (curGroupDeclarative)
          linkDeclarativeModule(entry, loader);
        else
          linkDynamicModule(entry, loader);
      }
      curGroupDeclarative = !curGroupDeclarative;
    }
  }

  function linkDeclarativeModule(entry, loader) {
    // only link if already not already started linking (stops at circular)
    if (entry.module)
      return;

    // declare the module with an empty depMap
    var depMap = [];

    var declaration = entry.declare.call(loader.global, depMap);

    entry.module = declaration.exports;
    entry.exportStar = declaration.exportStar;
    entry.execute = declaration.execute;

    var module = entry.module;

    // now link all the module dependencies
    // amending the depMap as we go
    for (var i = 0; i < entry.normalizedDeps.length; i++) {
      var depName = entry.normalizedDeps[i];
      var depEntry = loader.defined[depName];

      // part of another linking group - use loader.get
      if (!depEntry) {
        depModule = loader.get(depName);
      }
      // if dependency already linked, use that
      else if (depEntry.module) {
        depModule = depEntry.module;
      }
      // otherwise we need to link the dependency
      else {
        linkDeclarativeModule(depEntry, loader);
        depModule = depEntry.module;
      }

      if (entry.exportStar && indexOf.call(entry.exportStar, entry.normalizedDeps[i]) != -1) {
        // we are exporting * from this dependency
        (function(depModule) {
          for (var p in depModule) (function(p) {
            // if the property is already defined throw?
            Object.defineProperty(module, p, {
              enumerable: true,
              get: function() {
                return depModule[p];
              },
              set: function(value) {
                depModule[p] = value;
              }
            });
          })(p);
        })(depModule);
      }

      depMap[i] = depModule;
    }
  }

  // An analog to loader.get covering execution of all three layers (real declarative, simulated declarative, simulated dynamic)
  function getModule(name, loader) {
    var module;
    var entry = loader.defined[name];

    if (!entry) {
      module = loader.get(name);
      if (!module)
        throw "System Register: The module requested " + name + " but this was not declared as a dependency";
    }

    else {
      if (entry.declarative)
        ensureEvaluated(name, [], loader);

      else if (!entry.evaluated)
        linkDynamicModule(entry, loader);

      module = entry.module;
    }

    if (!module)
      return '';

    return module.__useDefault ? module['default'] : module;
  }

  function linkDynamicModule(entry, loader) {
    if (entry.module)
      return;

    entry.module = { 'default': {}, __useDefault: true };

    // AMD requires execute the tree first
    if (!entry.executingRequire) {
      for (var i = 0; i < entry.normalizedDeps.length; i++) {
        var depName = entry.normalizedDeps[i];
        var depEntry = loader.defined[depName];
        if (depEntry)
          linkDynamicModule(depEntry, loader);
      }
    }

    // lookup the module name if it is in the registry
    var moduleName;
    for (var d in loader.defined) {
      if (loader.defined[d] != entry)
        continue;
      moduleName = d;
      break;
    }

    // now execute
    entry.evaluated = true;
    var output = entry.execute.call(loader.global, function(name) {
      for (var i = 0; i < entry.deps.length; i++) {
        if (entry.deps[i] != name)
          continue;
        return getModule(entry.normalizedDeps[i], loader);
      }
    }, entry.module['default'], moduleName);

    if (output)
      entry.module['default'] = output;
  }

  // given a module, and the list of modules for this current branch,
  // ensure that each of the dependencies of this module is evaluated
  //  (unless one is a circular dependency already in the list of seen
  //   modules, in which case we execute it)
  // then evaluate the module itself
  // depth-first left to right execution to match ES6 modules
  function ensureEvaluated(moduleName, seen, loader) {
    var entry = loader.defined[moduleName];

    // if already seen, that means it's an already-evaluated non circular dependency
    if (entry.evaluated || !entry.declarative)
      return;

    seen.push(moduleName);

    for (var i = 0; i < entry.normalizedDeps.length; i++) {
      var depName = entry.normalizedDeps[i];
      if (indexOf.call(seen, depName) == -1) {
        if (!loader.defined[depName])
          loader.get(depName);
        else
          ensureEvaluated(depName, seen, loader);
      }
    }

    if (entry.evaluated)
      return;

    entry.evaluated = true;
    entry.execute.call(loader.global);
  }

  var registerRegEx = /System\.register/;

  var loaderFetch = loader.fetch;
  loader.fetch = function(load) {
    var loader = this;
    defineRegister(loader);
    if (loader.defined[load.name]) {
      load.metadata.format = 'defined';
      return '';
    }
    anonRegister = null;
    calledRegister = false;
    // the above get picked up by onScriptLoad
    return loaderFetch.call(loader, load);
  }

  var loaderTranslate = loader.translate;
  loader.translate = function(load) {
    this.register = register;

    this.__exec = exec;

    load.metadata.deps = load.metadata.deps || [];

    // we run the meta detection here (register is after meta)
    return Promise.resolve(loaderTranslate.call(this, load)).then(function(source) {

      // dont run format detection for globals shimmed
      // ideally this should be in the global extension, but there is
      // currently no neat way to separate it
      if (load.metadata.init || load.metadata.exports)
        load.metadata.format = load.metadata.format || 'global';

      // run detection for register format
      if (load.metadata.format == 'register' || !load.metadata.format && load.source.match(registerRegEx))
        load.metadata.format = 'register';
      return source;
    });
  }

  var loaderInstantiate = loader.instantiate;
  loader.instantiate = function(load) {
    var loader = this;

    var entry;

    // first we check if this module has already been defined in the registry
    if (loader.defined[load.name])
      entry = loader.defined[load.name];

    // picked up already by a script injection
    else if (load.metadata.entry)
      entry = load.metadata.entry;

    // otherwise check if it is dynamic
    else if (load.metadata.execute) {
      entry = {
        declarative: false,
        deps: load.metadata.deps || [],
        execute: load.metadata.execute,
        executingRequire: load.metadata.executingRequire // NodeJS-style requires or not
      };
    }

    // Contains System.register calls
    else if (load.metadata.format == 'register') {
      anonRegister = null;
      calledRegister = false;

      loader.__exec(load);

      if (anonRegister)
        entry = anonRegister;

      if (!calledRegister && !load.metadata.registered)
        throw load.name + " detected as System.register but didn't execute.";
    }

    // named bundles are just an empty module
    if (!entry && load.metadata.format != 'es6')
      return {
        deps: [],
        execute: function() {
          return loader.newModule({});
        }
      };

    // place this module onto defined for circular references
    if (entry)
      loader.defined[load.name] = entry;

    // no entry -> treat as ES6
    else
      return loaderInstantiate.call(this, load);

    entry.deps = dedupe(entry.deps);

    // first, normalize all dependencies
    var normalizePromises = [];
    for (var i = 0; i < entry.deps.length; i++)
      normalizePromises.push(Promise.resolve(loader.normalize(entry.deps[i], load.name)));

    return Promise.all(normalizePromises).then(function(normalizedDeps) {

      entry.normalizedDeps = normalizedDeps;

      // create the empty dep map - this is our key deferred dependency binding object passed into declare
      entry.depMap = [];

      return {
        deps: entry.deps,
        execute: function() {
          // this avoids double duplication allowing a bundle to equal its last defined module
          if (entry.esmodule) {
            loader.defined[load.name] = undefined;
            return entry.esmodule;
          }

          // recursively ensure that the module and all its
          // dependencies are linked (with dependency group handling)
          link(load.name, loader);

          // now handle dependency execution in correct order
          ensureEvaluated(load.name, [], loader);

          // remove from the registry
          loader.defined[load.name] = undefined;

          var module = loader.newModule(entry.module);

          // if the entry is an alias, set the alias too
          for (var name in loader.defined) {
            if (!loader.defined[name])
              continue;
            if (entry.declarative && loader.defined[name].execute != entry.execute)
              continue;
            if (!entry.declarative && loader.defined[name].declare != entry.declare);
              continue;
            loader.defined[name].esmodule = module;
          }
          // return the defined module object
          return module;
        }
      };
    });
  }
}
<commit_msg>ensure System.register implementation<commit_after>/*
 * Instantiate registry extension
 *
 * Supports Traceur System.register 'instantiate' output for loading ES6 as ES5.
 *
 * - Creates the loader.register function
 * - Also supports metadata.format = 'register' in instantiate for anonymous register modules
 * - Also supports metadata.deps, metadata.execute and metadata.executingRequire
 *     for handling dynamic modules alongside register-transformed ES6 modules
 *
 * Works as a standalone extension, but benefits from having a more
 * advanced __eval defined like in SystemJS polyfill-wrapper-end.js
 *
 * The code here replicates the ES6 linking groups algorithm to ensure that
 * circular ES6 compiled into System.register can work alongside circular AMD
 * and CommonJS, identically to the actual ES6 loader.
 *
 */
function register(loader) {
  if (typeof indexOf == 'undefined')
    indexOf = Array.prototype.indexOf;
  if (typeof __eval == 'undefined')
    __eval = 0 || eval; // uglify breaks without the 0 ||

  // define exec for easy evaluation of a load record (load.name, load.source, load.address)
  // main feature is source maps support handling
  var curSystem;
  function exec(load) {
    var loader = this;
    if (load.name == '@traceur') {
      curSystem = System;
    }
    // support sourceMappingURL (efficiently)
    var sourceMappingURL;
    var lastLineIndex = load.source.lastIndexOf('\n');
    if (lastLineIndex != -1) {
      if (load.source.substr(lastLineIndex + 1, 21) == '//# sourceMappingURL=') {
        sourceMappingURL = load.source.substr(lastLineIndex + 22, load.source.length - lastLineIndex - 22);
        if (typeof toAbsoluteURL != 'undefined')
          sourceMappingURL = toAbsoluteURL(load.address, sourceMappingURL);
      }
    }

    __eval(load.source, loader.global, load.address, sourceMappingURL);

    // traceur overwrites System and Module - write them back
    if (load.name == '@traceur') {
      loader.global.traceurSystem = loader.global.System;
      loader.global.System = curSystem;
    }
  }
  loader.__exec = exec;

  function dedupe(deps) {
    var newDeps = [];
    for (var i = 0; i < deps.length; i++)
      if (indexOf.call(newDeps, deps[i]) == -1)
        newDeps.push(deps[i])
    return newDeps;
  }

  // There are two variations of System.register:
  // 1. System.register for ES6 conversion (2-3 params) - System.register([name, ]deps, declare)
  //    see https://github.com/ModuleLoader/es6-module-loader/wiki/System.register-Explained
  //
  // 2. System.register for dynamic modules (3-4 params) - System.register([name, ]deps, executingRequire, execute)
  // the true or false statement

  // this extension implements the linking algorithm for the two variations identical to the spec
  // allowing compiled ES6 circular references to work alongside AMD and CJS circular references.

  // loader.register sets loader.defined for declarative modules
  var anonRegister;
  var calledRegister;
  function register(name, deps, declare, execute) {
    if (typeof name != 'string') {
      execute = declare;
      declare = deps;
      deps = name;
      name = null;
    }

    calledRegister = true;

    var register;

    // dynamic
    if (typeof declare == 'boolean') {
      register = {
        declarative: false,
        deps: deps,
        execute: execute,
        executingRequire: declare
      };
    }
    else {
      // ES6 declarative
      if (deps.length > 0 && declare.length != 1)
        throw 'Invalid System.register form for ' + name + '. Declare function must take one argument.';
      register = {
        declarative: true,
        deps: deps,
        declare: declare
      };
    }

    // named register
    if (name) {
      // we never overwrite an existing define
      if (!loader.defined[name])
        loader.defined[name] = register;
    }
    // anonymous register
    else if (register.declarative) {
      if (anonRegister)
        throw 'Multiple anonymous System.register calls in the same module file.';
      anonRegister = register;
    }
  }

  // Registry side table - loader.defined
  // Registry Entry Contains:
  //    - deps
  //    - declare for register modules
  //    - execute for dynamic modules, also after declare for declarative modules
  //    - executingRequire indicates require drives execution for circularity of dynamic modules
  //    - declarative optional boolean indicating which of the above
  //
  // Can preload modules directly on System.defined['my/module'] = { deps, execute, executingRequire }
  //
  // Then the entry gets populated with derived information during processing:
  //    - normalizedDeps derived from deps, created in instantiate
  //    - depMap array derived from deps, populated gradually in link
  //    - groupIndex used by group linking algorithm
  //    - module a raw module exports object with no wrapper
  //    - evaluated indiciating whether evaluation has happend for declarative modules
  // After linked and evaluated, entries are removed

  function defineRegister(loader) {
    if (loader.register)
      return;

    loader.register = register;

    if (!loader.defined)
      loader.defined = {};

    // script injection mode calls this function synchronously on load
    var onScriptLoad = loader.onScriptLoad;
    loader.onScriptLoad = function(load) {
      onScriptLoad(load);
      // anonymous define
      if (anonRegister)
        load.metadata.entry = anonRegister;

      if (anonRegister || calledRegister)
        load.metadata.format = load.metadata.format || 'register';
      if (calledRegister)
        load.metadata.registered = true;
    }
  }

  defineRegister(loader);

  function buildGroups(entry, loader, groups) {
    groups[entry.groupIndex] = groups[entry.groupIndex] || [];

    if (indexOf.call(groups[entry.groupIndex], entry) != -1)
      return;

    groups[entry.groupIndex].push(entry);

    for (var i = 0; i < entry.normalizedDeps.length; i++) {
      var depName = entry.normalizedDeps[i];
      var depEntry = loader.defined[depName];

      // not in the registry means already linked / ES6
      if (!depEntry || depEntry.evaluated)
        continue;

      // now we know the entry is in our unlinked linkage group
      var depGroupIndex = entry.groupIndex + (depEntry.declarative != entry.declarative);

      // the group index of an entry is always the maximum
      if (depEntry.groupIndex === undefined || depEntry.groupIndex < depGroupIndex) {

        // if already in a group, remove from the old group
        if (depEntry.groupIndex) {
          groups[depEntry.groupIndex].splice(groups[depEntry.groupIndex].indexOf(depEntry), 1);

          // if the old group is empty, then we have a mixed depndency cycle
          if (groups[depEntry.groupIndex].length == 0)
            throw new TypeError("Mixed dependency cycle detected");
        }

        depEntry.groupIndex = depGroupIndex;
      }

      buildGroups(depEntry, loader, groups);
    }
  }

  function link(name, loader) {
    var startEntry = loader.defined[name];

    startEntry.groupIndex = 0;

    var groups = [];

    buildGroups(startEntry, loader, groups);

    var curGroupDeclarative = !!startEntry.declarative == groups.length % 2;
    for (var i = groups.length - 1; i >= 0; i--) {
      var group = groups[i];
      for (var j = 0; j < group.length; j++) {
        var entry = group[j];

        // link each group
        if (curGroupDeclarative)
          linkDeclarativeModule(entry, loader);
        else
          linkDynamicModule(entry, loader);
      }
      curGroupDeclarative = !curGroupDeclarative;
    }
  }

  function linkDeclarativeModule(entry, loader) {
    // only link if already not already started linking (stops at circular)
    if (entry.module)
      return;

    // declare the module with an empty depMap
    var depMap = [];

    var declaration = entry.declare.call(loader.global, depMap);

    entry.module = declaration.exports;
    entry.exportStar = declaration.exportStar;
    entry.execute = declaration.execute;

    var module = entry.module;

    // now link all the module dependencies
    // amending the depMap as we go
    for (var i = 0; i < entry.normalizedDeps.length; i++) {
      var depName = entry.normalizedDeps[i];
      var depEntry = loader.defined[depName];

      // part of another linking group - use loader.get
      if (!depEntry) {
        depModule = loader.get(depName);
      }
      // if dependency already linked, use that
      else if (depEntry.module) {
        depModule = depEntry.module;
      }
      // otherwise we need to link the dependency
      else {
        linkDeclarativeModule(depEntry, loader);
        depModule = depEntry.module;
      }

      if (entry.exportStar && indexOf.call(entry.exportStar, entry.normalizedDeps[i]) != -1) {
        // we are exporting * from this dependency
        (function(depModule) {
          for (var p in depModule) (function(p) {
            // if the property is already defined throw?
            Object.defineProperty(module, p, {
              enumerable: true,
              get: function() {
                return depModule[p];
              },
              set: function(value) {
                depModule[p] = value;
              }
            });
          })(p);
        })(depModule);
      }

      depMap[i] = depModule;
    }
  }

  // An analog to loader.get covering execution of all three layers (real declarative, simulated declarative, simulated dynamic)
  function getModule(name, loader) {
    var module;
    var entry = loader.defined[name];

    if (!entry) {
      module = loader.get(name);
      if (!module)
        throw "System Register: The module requested " + name + " but this was not declared as a dependency";
    }

    else {
      if (entry.declarative)
        ensureEvaluated(name, [], loader);

      else if (!entry.evaluated)
        linkDynamicModule(entry, loader);

      module = entry.module;
    }

    if (!module)
      return '';

    return module.__useDefault ? module['default'] : module;
  }

  function linkDynamicModule(entry, loader) {
    if (entry.module)
      return;

    entry.module = { 'default': {}, __useDefault: true };

    // AMD requires execute the tree first
    if (!entry.executingRequire) {
      for (var i = 0; i < entry.normalizedDeps.length; i++) {
        var depName = entry.normalizedDeps[i];
        var depEntry = loader.defined[depName];
        if (depEntry)
          linkDynamicModule(depEntry, loader);
      }
    }

    // lookup the module name if it is in the registry
    var moduleName;
    for (var d in loader.defined) {
      if (loader.defined[d] != entry)
        continue;
      moduleName = d;
      break;
    }

    // now execute
    entry.evaluated = true;
    var output = entry.execute.call(loader.global, function(name) {
      for (var i = 0; i < entry.deps.length; i++) {
        if (entry.deps[i] != name)
          continue;
        return getModule(entry.normalizedDeps[i], loader);
      }
    }, entry.module['default'], moduleName);

    if (output)
      entry.module['default'] = output;
  }

  // given a module, and the list of modules for this current branch,
  // ensure that each of the dependencies of this module is evaluated
  //  (unless one is a circular dependency already in the list of seen
  //   modules, in which case we execute it)
  // then evaluate the module itself
  // depth-first left to right execution to match ES6 modules
  function ensureEvaluated(moduleName, seen, loader) {
    var entry = loader.defined[moduleName];

    // if already seen, that means it's an already-evaluated non circular dependency
    if (entry.evaluated || !entry.declarative)
      return;

    seen.push(moduleName);

    for (var i = 0; i < entry.normalizedDeps.length; i++) {
      var depName = entry.normalizedDeps[i];
      if (indexOf.call(seen, depName) == -1) {
        if (!loader.defined[depName])
          loader.get(depName);
        else
          ensureEvaluated(depName, seen, loader);
      }
    }

    if (entry.evaluated)
      return;

    entry.evaluated = true;
    entry.execute.call(loader.global);
  }

  var registerRegEx = /System\.register/;

  var loaderFetch = loader.fetch;
  loader.fetch = function(load) {
    var loader = this;
    defineRegister(loader);
    if (loader.defined[load.name]) {
      load.metadata.format = 'defined';
      return '';
    }
    anonRegister = null;
    calledRegister = false;
    // the above get picked up by onScriptLoad
    return loaderFetch.call(loader, load);
  }

  var loaderTranslate = loader.translate;
  loader.translate = function(load) {
    this.register = register;

    this.__exec = exec;

    load.metadata.deps = load.metadata.deps || [];

    // we run the meta detection here (register is after meta)
    return Promise.resolve(loaderTranslate.call(this, load)).then(function(source) {

      // dont run format detection for globals shimmed
      // ideally this should be in the global extension, but there is
      // currently no neat way to separate it
      if (load.metadata.init || load.metadata.exports)
        load.metadata.format = load.metadata.format || 'global';

      // run detection for register format
      if (load.metadata.format == 'register' || !load.metadata.format && load.source.match(registerRegEx))
        load.metadata.format = 'register';
      return source;
    });
  }

  var loaderInstantiate = loader.instantiate;
  loader.instantiate = function(load) {
    var loader = this;

    var entry;

    // first we check if this module has already been defined in the registry
    if (loader.defined[load.name])
      entry = loader.defined[load.name];

    // picked up already by a script injection
    else if (load.metadata.entry)
      entry = load.metadata.entry;

    // otherwise check if it is dynamic
    else if (load.metadata.execute) {
      entry = {
        declarative: false,
        deps: load.metadata.deps || [],
        execute: load.metadata.execute,
        executingRequire: load.metadata.executingRequire // NodeJS-style requires or not
      };
    }

    // Contains System.register calls
    else if (load.metadata.format == 'register') {
      anonRegister = null;
      calledRegister = false;

      var System = loader.global.System = loader.global.System || loader;

      var curRegister = System.register;
      System.register = register;

      loader.__exec(load);

      System.register = curRegister;

      if (anonRegister)
        entry = anonRegister;

      if (!calledRegister && !load.metadata.registered)
        throw load.name + " detected as System.register but didn't execute.";
    }

    // named bundles are just an empty module
    if (!entry && load.metadata.format != 'es6')
      return {
        deps: [],
        execute: function() {
          return loader.newModule({});
        }
      };

    // place this module onto defined for circular references
    if (entry)
      loader.defined[load.name] = entry;

    // no entry -> treat as ES6
    else
      return loaderInstantiate.call(this, load);

    entry.deps = dedupe(entry.deps);

    // first, normalize all dependencies
    var normalizePromises = [];
    for (var i = 0; i < entry.deps.length; i++)
      normalizePromises.push(Promise.resolve(loader.normalize(entry.deps[i], load.name)));

    return Promise.all(normalizePromises).then(function(normalizedDeps) {

      entry.normalizedDeps = normalizedDeps;

      // create the empty dep map - this is our key deferred dependency binding object passed into declare
      entry.depMap = [];

      return {
        deps: entry.deps,
        execute: function() {
          // this avoids double duplication allowing a bundle to equal its last defined module
          if (entry.esmodule) {
            loader.defined[load.name] = undefined;
            return entry.esmodule;
          }

          // recursively ensure that the module and all its
          // dependencies are linked (with dependency group handling)
          link(load.name, loader);

          // now handle dependency execution in correct order
          ensureEvaluated(load.name, [], loader);

          // remove from the registry
          loader.defined[load.name] = undefined;

          var module = loader.newModule(entry.module);

          // if the entry is an alias, set the alias too
          for (var name in loader.defined) {
            if (!loader.defined[name])
              continue;
            if (entry.declarative && loader.defined[name].execute != entry.execute)
              continue;
            if (!entry.declarative && loader.defined[name].declare != entry.declare);
              continue;
            loader.defined[name].esmodule = module;
          }
          // return the defined module object
          return module;
        }
      };
    });
  }
}
<|endoftext|>


<commit_before>/* ===================================================
 * bootstrap-transition.js v2.0.4
 * http://twitter.github.com/bootstrap/javascript.html#transitions
 * ===================================================
 * Copyright 2012 Twitter, Inc.
 *
 * 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.
 * ========================================================== */

!function ($) {

  $(function () {

    "use strict"; // jshint ;_;

    /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
     * ======================================================= */

    $.support.transition = (function () {

      var transitionEnd = (function () {

        var el = document.createElement('bootstrap')
          , transEndEventNames = {
               'WebkitTransition' : 'webkitTransitionEnd'
            ,  'MozTransition'    : 'transitionend'
            ,  'OTransition'      : 'oTransitionEnd'
            ,  'msTransition'     : 'MSTransitionEnd'
            ,  'transition'       : 'transitionend'
            }
          , name

        for (name in transEndEventNames){
          if (el.style[name] !== undefined) {
            return transEndEventNames[name]
          }
        }

      }())

      return transitionEnd && {
        end: transitionEnd
      }

    })()

  })

}(window.jQuery);<commit_msg>Bugfix for modal popup in Opera12<commit_after>/* ===================================================
 * bootstrap-transition.js v2.0.4
 * http://twitter.github.com/bootstrap/javascript.html#transitions
 * ===================================================
 * Copyright 2012 Twitter, Inc.
 *
 * 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.
 * ========================================================== */

!function ($) {

  $(function () {

    "use strict"; // jshint ;_;

    /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
     * ======================================================= */

    $.support.transition = (function () {

      var transitionEnd = (function () {

        var el = document.createElement('bootstrap')
          , transEndEventNames = {
               'WebkitTransition' : 'webkitTransitionEnd'
            ,  'MozTransition'    : 'transitionend'
            ,  'OTransition'      : 'otransitionend'
            ,  'msTransition'     : 'MSTransitionEnd'
            ,  'transition'       : 'transitionend'
            }
          , name

        for (name in transEndEventNames){
          if (el.style[name] !== undefined) {
            return transEndEventNames[name]
          }
        }

      }())

      return transitionEnd && {
        end: transitionEnd
      }

    })()

  })

}(window.jQuery);<|endoftext|>


<commit_before>/*
 *  Copyright 2017 TWO SIGMA OPEN SOURCE, LLC
 *
 *  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.
 */

define([
  'underscore',
  './../std/plotarea',
  './../plotSampler',
  './../lod/plotLodRiver'
], function(
  _,
  PlotArea,
  PlotSampler,
  PlotLodRiver
) {
  const PlotUtils = require("../utils/PlotUtils").default;
  const PlotColorUtils = require("../utils/PlotColorUtils").default;
  const CommonUtils = require("beakerx_shared/lib/utils/CommonUtils").default;

  var PlotAreaLodLoader = function(data, lodthresh){
    this.datacopy = {};
    _.extend(this.datacopy, data);  // save for later use
    _.extend(this, data); // copy properties to itself
    this.lodthresh = lodthresh;
    this.format(lodthresh);
  };
  // class constants
  PlotAreaLodLoader.prototype.lodTypes = ["river"];
  PlotAreaLodLoader.prototype.lodSteps = [3];

  PlotAreaLodLoader.prototype.format = function() {
    // create plot type index
    this.lodTypeIndex =  (this.datacopy.lod_filter) ? this.lodTypes.indexOf(this.datacopy.lod_filter) : 0;
    this.lodType = this.lodTypes[this.lodTypeIndex]; // line, box

    // create the plotters
    this.zoomHash = CommonUtils.randomString(3);
    this.plotter = new PlotArea(this.datacopy);
    this.createLodPlotter();

    // a few switches and constants
    this.isLodItem = true;
    this.lodOn = false;
    this.lodAuto = true;
    this.sampleStep = -1;
    if (this.color != null) {
      this.tip_color = PlotColorUtils.createColor(this.color, this.color_opacity);
    } else {
      this.tip_color = "gray";
    }

    this.itemProps = {
      "id" : this.id,
      "st" : this.color,
      "st_op" : this.color_opacity,
      "st_w" : this.width,
      "st_da" : this.stroke_dasharray,
      "d" : ""
    };
    this.elementProps = [];
  };

  PlotAreaLodLoader.prototype.zoomLevelChanged = function(scope) {
    this.sampleStep = -1;
    this.zoomHash = CommonUtils.randomString(3);
    if (this.lodOn === false) { return; }
    if (this.lodType === "area") {
      this.lodplotter.setZoomHash(this.zoomHash);
      this.lodplotter.hideTips(scope);
    } else if (this.lodType === "river"){
      this.lodplotter.setZoomHash(this.zoomHash);
      this.lodplotter2.setZoomHash(this.zoomHash);
      this.lodplotter.hideTips(scope);
      this.lodplotter2.hideTips(scope);
    }
  };

  PlotAreaLodLoader.prototype.applyZoomHash = function(hash) {
    this.zoomHash = hash;
    if (this.lodType === "area") {
      this.lodplotter.setZoomHash(hash);
    } else if (this.lodType === "river") {
      this.lodplotter.setZoomHash(hash);
      this.lodplotter2.setZoomHash(hash);
    }
  };

  PlotAreaLodLoader.prototype.switchLodType = function(scope) {
    this.clear(scope);
    this.lodTypeIndex = (this.lodTypeIndex + 1) % this.lodTypes.length;
    this.lodType = this.lodTypes[this.lodTypeIndex];
    this.createLodPlotter();
  };

  PlotAreaLodLoader.prototype.applyLodType = function(type) {
    this.lodTypeIndex = this.lodTypes.indexOf(type);  // maybe -1
    if (this.lodTypeIndex === -1) {
      this.lodTypeIndex = 0;
    }
    this.lodType = this.lodTypes[this.lodTypeIndex];
    this.createLodPlotter();
  };

  PlotAreaLodLoader.prototype.createLodPlotter = function() {
    var data = {};
    _.extend(data, this.datacopy);
    if (this.lodType === "area") {
      this.lodplotter = new PlotLodRiver(data);
      this.lodplotter.setZoomHash(this.zoomHash);
    } else if (this.lodType === "river") {
      data.stroke = data.color;  // assume the user has no way to set outline for area
      data.color_opacity *= .25;
      data.stroke_opacity = 1.0;
      this.lodplotter = new PlotLodRiver(data);
      this.lodplotter2 = new PlotLodRiver(data);
      this.lodplotter.setZoomHash(this.zoomHash);
      this.lodplotter2.setZoomHash(this.zoomHash);

      _.extend(data, this.datacopy);
      this.auxplotter = new PlotAuxRiver(data);
    }
  };

  PlotAreaLodLoader.prototype.toggleLodAuto = function(scope) {
    this.lodAuto = !this.lodAuto;
    this.clear(scope);
  };

  PlotAreaLodLoader.prototype.applyLodAuto = function(auto) {
    this.lodAuto = auto;
  };

  PlotAreaLodLoader.prototype.toggleLod = function(scope) {
    if (this.lodType === "off") {
      this.lodType = this.lodTypes[this.lodTypeIndex];
    } else {
      this.lodType = "off";
    }
    this.clear(scope);
  };

  PlotAreaLodLoader.prototype.render = function(scope){
    if (this.showItem === false) {
      this.clear(scope);
      return;
    }

    this.filter(scope);

    var lod = false;
    if (this.lodType !== "off") {
      if ( (this.lodAuto === true && this.vlength > this.lodthresh) || this.lodAuto === false) {
        lod = true;
      }
    }

    if (this.lodOn != lod) {
      scope.legendDone = false;
      this.clear(scope);
    }
    this.lodOn = lod;

    if (this.lodOn === false) {
      this.plotter.render(scope);
      return;
    }

    this.sample(scope);
    if (this.lodType === "area") {
      this.lodplotter.render(scope, this.elementSamples);
    } else if (this.lodType === "river") {
      this.auxplotter.render(scope, this.elementAuxes, "a");
      this.lodplotter.render(scope, this.elementSamples, "yBtm");
      this.lodplotter2.render(scope, this.elementSamples2, "yTop");
    }
  };

  PlotAreaLodLoader.prototype.setHighlighted = function(scope, highlighted) {
    if (this.lodOn === true) {
      if (this.lodType === "area") {
        this.lodplotter.setHighlighted(scope, highlighted);
      } else if (this.lodType === "river") {
        this.auxplotter.setHighlighted(scope, highlighted, "a");
        this.lodplotter.setHighlighted(scope, highlighted, "yBtm");
        this.lodplotter2.setHighlighted(scope, highlighted, "yTop");
      }
    } else {
      this.plotter.setHighlighted(scope, highlighted);
    }
  };

  PlotAreaLodLoader.prototype.getRange = function(){
    return this.plotter.getRange();
  };

  PlotAreaLodLoader.prototype.applyAxis = function(xAxis, yAxis) {
    this.xAxis = xAxis;
    this.yAxis = yAxis;
    this.plotter.applyAxis(xAxis, yAxis);
    // sampler is created AFTER coordinate axis remapping
    this.createSampler();
  };

  PlotAreaLodLoader.prototype.createSampler = function() {
    var xs = [], ys = [], y2s = [], _ys = [], _y2s = [];
    for (var i = 0; i < this.elements.length; i++) {
      var ele = this.elements[i];
      xs.push(ele.x);
      ys.push(ele.y);
      y2s.push(ele.y2);
      _ys.push(ele._y);
      _y2s.push(ele._y2);
    }
    this.sampler = new PlotSampler(xs, ys, _ys);
    this.sampler2 = new PlotSampler(xs, y2s, _y2s);
  };

  PlotAreaLodLoader.prototype.filter = function(scope) {
    this.plotter.filter(scope);
    this.vindexL = this.plotter.vindexL;
    this.vindexR = this.plotter.vindexR;
    this.vlength = this.plotter.vlength;
  };

  PlotAreaLodLoader.prototype.sample = function(scope) {
    var xAxis = this.xAxis,
      yAxis = this.yAxis;
    var xl = scope.plotFocus.focus.xl, xr = scope.plotFocus.focus.xr;

    if (this.sampleStep === -1) {
      var pixelWidth = scope.layout.plotSize.width;
      var count = Math.ceil(pixelWidth / this.lodSteps[this.lodTypeIndex]);
      var s = (xr - xl) / count;
      this.sampleStep = s;
    }

    var step = this.sampleStep;
    xl = Math.floor(xl / step) * step;
    xr = Math.ceil(xr / step) * step;

    this.elementSamples = this.sampler.sample(xl, xr, this.sampleStep);
    this.elementSamples2 = this.sampler2.sample(xl, xr, this.sampleStep);
    var count = this.elementSamples.length;

    if (this.lodType === "area") {
      var elements = [];
      for (var i = 0; i < count; i++) {
        elements.push({
          x : this.elementSamples[i].x,
          min : this.elementSamples[i].avg,
          max : this.elementSamples2[i].avg,
          hash : this.elementSamples[i].hash,
          xl : this.elementSamples[i].xl,
          xr : this.elementSamples[i].xr
        });
      }
      this.elementSamples = elements;
    } else if (this.lodType === "river") {
      this.elementAuxes = [];
      // prepare the aux river in between
      for (var i = 0; i < count; i++) {
        this.elementAuxes.push({
          x : this.elementSamples[i].x,
          y : this.elementSamples[i].max,
          y2 : this.elementSamples2[i].min
        });
      }
    }

  };

  PlotAreaLodLoader.prototype.clear = function(scope) {
    scope.maing.select("#" + this.id).selectAll("*").remove();
    this.hideTips(scope);
  };

  PlotAreaLodLoader.prototype.hideTips = function(scope, hidden) {
    if (this.lodOn === false) {
      this.plotter.hideTips(scope);
      return;
    }
    if (this.lodType === "area") {
      this.lodplotter.hideTips(scope, hidden);
    } else if (this.lodType === "river") {
      this.lodplotter.hideTips(scope, hidden);
      this.lodplotter2.hideTips(scope, hidden);
    }
  };

  PlotAreaLodLoader.prototype.createTip = function(ele, g) {
    if (this.lodOn === false) {
      return this.plotter.createTip(ele);
    }
    var xAxis = this.xAxis,
      yAxis = this.yAxis;
    var tip = {};
    var sub = "sample" + (g !== "" ? (" " + g) : "");
    if (this.legend != null) {
      tip.title = this.legend + " (" + sub + ")";
    }
    var eles = this.elements;
    tip.xl = PlotUtils.getTipStringPercent(ele.xl, xAxis, 6);
    tip.xr = PlotUtils.getTipStringPercent(ele.xr, xAxis, 6);
    if (this.lodType === "area") {
      tip.avg_yTop = PlotUtils.getTipStringPercent(ele.max, yAxis, 6);
      tip.avg_yBtm = PlotUtils.getTipStringPercent(ele.min, yAxis, 6);
    } else if (this.lodType === "river") {
      tip.max = PlotUtils.getTipString(ele._max, yAxis, true);
      tip.min = PlotUtils.getTipString(ele._min, yAxis, true);
      tip.avg = PlotUtils.getTipStringPercent(ele.avg, yAxis, 6);
      tip.count = PlotUtils.getTipString(ele.count, yAxis, true);
    }
    return PlotUtils.createTipString(tip);
  };

  return PlotAreaLodLoader;

});
<commit_msg>#8001: fix plotting a long time series (#8223)<commit_after>/*
 *  Copyright 2017 TWO SIGMA OPEN SOURCE, LLC
 *
 *  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.
 */

define([
  'underscore',
  './../std/plotarea',
  './../plotSampler',
  './../lod/plotLodRiver',
  './../auxes/plotAuxRiver'
], function(
  _,
  PlotArea,
  PlotSampler,
  PlotLodRiver,
  PlotAuxRiver
) {
  const PlotUtils = require("../utils/PlotUtils").default;
  const PlotColorUtils = require("../utils/PlotColorUtils").default;
  const CommonUtils = require("beakerx_shared/lib/utils/CommonUtils").default;

  var PlotAreaLodLoader = function(data, lodthresh){
    this.datacopy = {};
    _.extend(this.datacopy, data);  // save for later use
    _.extend(this, data); // copy properties to itself
    this.lodthresh = lodthresh;
    this.format(lodthresh);
  };
  // class constants
  PlotAreaLodLoader.prototype.lodTypes = ["river"];
  PlotAreaLodLoader.prototype.lodSteps = [3];

  PlotAreaLodLoader.prototype.format = function() {
    // create plot type index
    this.lodTypeIndex =  (this.datacopy.lod_filter) ? this.lodTypes.indexOf(this.datacopy.lod_filter) : 0;
    this.lodType = this.lodTypes[this.lodTypeIndex]; // line, box

    // create the plotters
    this.zoomHash = CommonUtils.randomString(3);
    this.plotter = new PlotArea(this.datacopy);
    this.createLodPlotter();

    // a few switches and constants
    this.isLodItem = true;
    this.lodOn = false;
    this.lodAuto = true;
    this.sampleStep = -1;
    if (this.color != null) {
      this.tip_color = PlotColorUtils.createColor(this.color, this.color_opacity);
    } else {
      this.tip_color = "gray";
    }

    this.itemProps = {
      "id" : this.id,
      "st" : this.color,
      "st_op" : this.color_opacity,
      "st_w" : this.width,
      "st_da" : this.stroke_dasharray,
      "d" : ""
    };
    this.elementProps = [];
  };

  PlotAreaLodLoader.prototype.zoomLevelChanged = function(scope) {
    this.sampleStep = -1;
    this.zoomHash = CommonUtils.randomString(3);
    if (this.lodOn === false) { return; }
    if (this.lodType === "area") {
      this.lodplotter.setZoomHash(this.zoomHash);
      this.lodplotter.hideTips(scope);
    } else if (this.lodType === "river"){
      this.lodplotter.setZoomHash(this.zoomHash);
      this.lodplotter2.setZoomHash(this.zoomHash);
      this.lodplotter.hideTips(scope);
      this.lodplotter2.hideTips(scope);
    }
  };

  PlotAreaLodLoader.prototype.applyZoomHash = function(hash) {
    this.zoomHash = hash;
    if (this.lodType === "area") {
      this.lodplotter.setZoomHash(hash);
    } else if (this.lodType === "river") {
      this.lodplotter.setZoomHash(hash);
      this.lodplotter2.setZoomHash(hash);
    }
  };

  PlotAreaLodLoader.prototype.switchLodType = function(scope) {
    this.clear(scope);
    this.lodTypeIndex = (this.lodTypeIndex + 1) % this.lodTypes.length;
    this.lodType = this.lodTypes[this.lodTypeIndex];
    this.createLodPlotter();
  };

  PlotAreaLodLoader.prototype.applyLodType = function(type) {
    this.lodTypeIndex = this.lodTypes.indexOf(type);  // maybe -1
    if (this.lodTypeIndex === -1) {
      this.lodTypeIndex = 0;
    }
    this.lodType = this.lodTypes[this.lodTypeIndex];
    this.createLodPlotter();
  };

  PlotAreaLodLoader.prototype.createLodPlotter = function() {
    var data = {};
    _.extend(data, this.datacopy);
    if (this.lodType === "area") {
      this.lodplotter = new PlotLodRiver(data);
      this.lodplotter.setZoomHash(this.zoomHash);
    } else if (this.lodType === "river") {
      data.stroke = data.color;  // assume the user has no way to set outline for area
      data.color_opacity *= .25;
      data.stroke_opacity = 1.0;
      this.lodplotter = new PlotLodRiver(data);
      this.lodplotter2 = new PlotLodRiver(data);
      this.lodplotter.setZoomHash(this.zoomHash);
      this.lodplotter2.setZoomHash(this.zoomHash);

      _.extend(data, this.datacopy);
      this.auxplotter = new PlotAuxRiver(data);
    }
  };

  PlotAreaLodLoader.prototype.toggleLodAuto = function(scope) {
    this.lodAuto = !this.lodAuto;
    this.clear(scope);
  };

  PlotAreaLodLoader.prototype.applyLodAuto = function(auto) {
    this.lodAuto = auto;
  };

  PlotAreaLodLoader.prototype.toggleLod = function(scope) {
    if (this.lodType === "off") {
      this.lodType = this.lodTypes[this.lodTypeIndex];
    } else {
      this.lodType = "off";
    }
    this.clear(scope);
  };

  PlotAreaLodLoader.prototype.render = function(scope){
    if (this.showItem === false) {
      this.clear(scope);
      return;
    }

    this.filter(scope);

    var lod = false;
    if (this.lodType !== "off") {
      if ( (this.lodAuto === true && this.vlength > this.lodthresh) || this.lodAuto === false) {
        lod = true;
      }
    }

    if (this.lodOn != lod) {
      scope.legendDone = false;
      this.clear(scope);
    }
    this.lodOn = lod;

    if (this.lodOn === false) {
      this.plotter.render(scope);
      return;
    }

    this.sample(scope);
    if (this.lodType === "area") {
      this.lodplotter.render(scope, this.elementSamples);
    } else if (this.lodType === "river") {
      this.auxplotter.render(scope, this.elementAuxes, "a");
      this.lodplotter.render(scope, this.elementSamples, "yBtm");
      this.lodplotter2.render(scope, this.elementSamples2, "yTop");
    }
  };

  PlotAreaLodLoader.prototype.setHighlighted = function(scope, highlighted) {
    if (this.lodOn === true) {
      if (this.lodType === "area") {
        this.lodplotter.setHighlighted(scope, highlighted);
      } else if (this.lodType === "river") {
        this.auxplotter.setHighlighted(scope, highlighted, "a");
        this.lodplotter.setHighlighted(scope, highlighted, "yBtm");
        this.lodplotter2.setHighlighted(scope, highlighted, "yTop");
      }
    } else {
      this.plotter.setHighlighted(scope, highlighted);
    }
  };

  PlotAreaLodLoader.prototype.getRange = function(){
    return this.plotter.getRange();
  };

  PlotAreaLodLoader.prototype.applyAxis = function(xAxis, yAxis) {
    this.xAxis = xAxis;
    this.yAxis = yAxis;
    this.plotter.applyAxis(xAxis, yAxis);
    // sampler is created AFTER coordinate axis remapping
    this.createSampler();
  };

  PlotAreaLodLoader.prototype.createSampler = function() {
    var xs = [], ys = [], y2s = [], _ys = [], _y2s = [];
    for (var i = 0; i < this.elements.length; i++) {
      var ele = this.elements[i];
      xs.push(ele.x);
      ys.push(ele.y);
      y2s.push(ele.y2);
      _ys.push(ele._y);
      _y2s.push(ele._y2);
    }
    this.sampler = new PlotSampler(xs, ys, _ys);
    this.sampler2 = new PlotSampler(xs, y2s, _y2s);
  };

  PlotAreaLodLoader.prototype.filter = function(scope) {
    this.plotter.filter(scope);
    this.vindexL = this.plotter.vindexL;
    this.vindexR = this.plotter.vindexR;
    this.vlength = this.plotter.vlength;
  };

  PlotAreaLodLoader.prototype.sample = function(scope) {
    var xAxis = this.xAxis,
      yAxis = this.yAxis;
    var xl = scope.plotFocus.focus.xl, xr = scope.plotFocus.focus.xr;

    if (this.sampleStep === -1) {
      var pixelWidth = scope.layout.plotSize.width;
      var count = Math.ceil(pixelWidth / this.lodSteps[this.lodTypeIndex]);
      var s = (xr - xl) / count;
      this.sampleStep = s;
    }

    var step = this.sampleStep;
    xl = Math.floor(xl / step) * step;
    xr = Math.ceil(xr / step) * step;

    this.elementSamples = this.sampler.sample(xl, xr, this.sampleStep);
    this.elementSamples2 = this.sampler2.sample(xl, xr, this.sampleStep);
    var count = this.elementSamples.length;

    if (this.lodType === "area") {
      var elements = [];
      for (var i = 0; i < count; i++) {
        elements.push({
          x : this.elementSamples[i].x,
          min : this.elementSamples[i].avg,
          max : this.elementSamples2[i].avg,
          hash : this.elementSamples[i].hash,
          xl : this.elementSamples[i].xl,
          xr : this.elementSamples[i].xr
        });
      }
      this.elementSamples = elements;
    } else if (this.lodType === "river") {
      this.elementAuxes = [];
      // prepare the aux river in between
      for (var i = 0; i < count; i++) {
        this.elementAuxes.push({
          x : this.elementSamples[i].x,
          y : this.elementSamples[i].max,
          y2 : this.elementSamples2[i].min
        });
      }
    }

  };

  PlotAreaLodLoader.prototype.clear = function(scope) {
    scope.maing.select("#" + this.id).selectAll("*").remove();
    this.hideTips(scope);
  };

  PlotAreaLodLoader.prototype.hideTips = function(scope, hidden) {
    if (this.lodOn === false) {
      this.plotter.hideTips(scope);
      return;
    }
    if (this.lodType === "area") {
      this.lodplotter.hideTips(scope, hidden);
    } else if (this.lodType === "river") {
      this.lodplotter.hideTips(scope, hidden);
      this.lodplotter2.hideTips(scope, hidden);
    }
  };

  PlotAreaLodLoader.prototype.createTip = function(ele, g) {
    if (this.lodOn === false) {
      return this.plotter.createTip(ele);
    }
    var xAxis = this.xAxis,
      yAxis = this.yAxis;
    var tip = {};
    var sub = "sample" + (g !== "" ? (" " + g) : "");
    if (this.legend != null) {
      tip.title = this.legend + " (" + sub + ")";
    }
    var eles = this.elements;
    tip.xl = PlotUtils.getTipStringPercent(ele.xl, xAxis, 6);
    tip.xr = PlotUtils.getTipStringPercent(ele.xr, xAxis, 6);
    if (this.lodType === "area") {
      tip.avg_yTop = PlotUtils.getTipStringPercent(ele.max, yAxis, 6);
      tip.avg_yBtm = PlotUtils.getTipStringPercent(ele.min, yAxis, 6);
    } else if (this.lodType === "river") {
      tip.max = PlotUtils.getTipString(ele._max, yAxis, true);
      tip.min = PlotUtils.getTipString(ele._min, yAxis, true);
      tip.avg = PlotUtils.getTipStringPercent(ele.avg, yAxis, 6);
      tip.count = PlotUtils.getTipString(ele.count, yAxis, true);
    }
    return PlotUtils.createTipString(tip);
  };

  return PlotAreaLodLoader;

});
<|endoftext|>


<commit_before>// Amara, universalsubtitles.org
//
// Copyright (C) 2012 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

var DFXP = function(DFXP) {
    /*
     * A utility for working with DFXP subs.
     */

    var that = this;

    this.init = function(xml) {

        // Store the original XML for comparison later.
        this.$originalXml = $(xml.documentElement).clone();

        // Store the working XML for local edits.
        this.$xml = $(xml.documentElement).clone();

    };

    // Helper methods.
    this.utils = {

        xmlToString: function(xml) {
            /*
             * Convert an XML document to a string.
             * Accepts: document object (XML tree)
             * Returns: string
             */

            var xmlString;

            // For Internet Explorer.
            if (window.ActiveXObject) {
                xmlString = xml.xml;

            // Everyone else.
            } else {
                xmlString = (new XMLSerializer()).serializeToString(xml);
            }

            return xmlString;
        }

    };

    this.addSubtitle = function(after, newAttrs) {
        /*
         * For adding a new subtitle to this set.
         *
         * If `after` is provided, we'll place the new subtitle directly
         * after that one. Otherwise, we'll place the new subtitle at the
         * end.
         *
         * `newAttrs` is an optional JSON object specifying the attributes to
         * be applied to the new element.
         *
         * Returns: new subtitle element
         */

        if (!after) {
            after = this.getLastSubtitle();
        }

        // Create the new element and any specified attributes.
        var newSubtitle = $('

').attr(newAttrs || {});

        // Finally, place the new subtitle.
        $(after).after(newSubtitle);

        return newSubtitle.get(0);
    };
    this.changesMade = function() {
        /*
         * Check to see if any changes have been made to the working XML.
         *
         * Returns: true || false
         */

        var originalString = that.utils.xmlToString(that.$originalXml.get(0));
        var xmlString = that.utils.xmlToString(that.$xml.get(0));

        return originalString != xmlString;
    };
    this.removeSubtitle = function(index) {
        /*
         * Given the zero-index of the subtitle to be removed,
         * remove it from the node tree.
         *
         * Returns: true || false
         */

        // If an index is not provided, throw an error.
        if (!index) {
            throw new Error('DFXP: You must supply an index to removeSubtitle()');
        }

        var subtitle = this.getSubtitles().get(index);

        if (subtitle) {
            $(subtitle).remove();
            return true;
        } else {
            throw new Error('DFXP: No subtitle exists with that index.');
        }
    };
    this.getLastSubtitle = function() {
        /*
         * Retrieve the last subtitle in this set.
         *
         * Returns: last subtitle element
         */

        // Cache the selection.
        var $subtitles = this.getSubtitles();

        return $subtitles[$subtitles.length - 1];
    };
    this.getSubtitles = function() {
        /*
         * Retrieve the current set of subtitles.
         *
         * Returns: jQuery selection of nodes.
         */

        return $('div > p', this.$xml);
    };
    this.needsSyncing = function(indexOrElement) {
        /*
         * Given the zero-index or the element of the subtitle to be
         * checked, determine whether the subtitle needs to be synced.
         *
         * In most cases, if a subtitle has either no start time,
         * or no end time, it needs to be synced. However, if the
         * subtitle is the last in the list, the end time may be
         * omitted.
         *
         * Returns: true || false
         */

        // If an index or an object is not provided, throw an error.
        if (typeof indexOrElement !== 'number' && typeof indexOrElement !== 'object') {
            throw new Error('DFXP: You must supply either an index or an element to needsSyncing()');
        }

        var subtitle;

        // If indexOrElement is a number, we'll need to query the DOM to
        // get the element.
        //
        // Note: you should only use this approach for checking one-off
        // subtitles. If you're checking more than one subtitle, it's much
        // faster to pass along pre-selected elements instead.
        if (typeof indexOrElement === 'number') {
            subtitle = this.getSubtitles().get(indexOrElement);

        // Otherwise, just use the element.
        } else {
            subtitle = indexOrElement;
        }

        if (subtitle) {

            var $subtitle = $(subtitle);

            var startTime = $subtitle.attr('begin');
            var endTime = $subtitle.attr('end');

            // If start time is empty, it always needs to be synced.
            if (startTime === '') {
                return true;
            }

            // If the end time is empty and this is not the last subtitle,
            // it needs to be synced.
            if (endTime === '' && (subtitle !== this.getLastSubtitle())) {
                return true;
            }

            // Otherwise, we're good.
            return false;

        } else {
            throw new Error('DFXP: No subtitle exists with that index.');
        }
    };
    this.needsAnySynced = function() {
        /*
         * Determine whether any of the subtitles in the set need
         * to be synced.
         *
         * Returns: true || false
         */

        var needsAnySynced = false;

        // Caching the current subtitle set drastically cuts down on processing
        // time for iterating through large subtitle sets.
        var $subtitles = this.getSubtitles();

        for (var i = 0; i < $subtitles.length; i++) {

            // We're going to pass the actual element instead of an integer. This
            // means needsSyncing doesn't need to hit the DOM to find the element.
            if (this.needsSyncing($subtitles.get(i))) {
                needsAnySynced = true;
            }
        }

        return needsAnySynced;
    };
    this.setEndTime = function(index, endTime) {
        /*
         * Given the zero-index of the subtitle to be updated,
         * set the end time.
         *
         * Returns: true
         */

        var subtitle = this.getSubtitles().get(index);

        if (subtitle) {
            $(subtitle).attr('end', endTime);
            return true;
        } else {
            throw new Error('DFXP: No subtitle exists with that index.');
        }
    };
    this.setStartTime = function(index, startTime) {
        /*
         * Given the zero-index of the subtitle to be updated,
         * set the start time.
         *
         * Returns: true
         */

        var subtitle = this.getSubtitles().get(index);

        if (subtitle) {
            $(subtitle).attr('begin', startTime);
            return true;
        } else {
            throw new Error('DFXP: No subtitle exists with that index.');
        }
    };
    this.subtitlesCount = function() {
        /*
         * Retrieve the current number of subtitles.
         *
         * Returns: integer
         */

        return this.getSubtitles().length;
    };
};

$(function() {
    $.ajax({
        type: 'get',
        url: '/site_media/src/js/dfxp/sample.dfxp.xml',
        dataType: 'xml',
        success: function(resp) {
            window.unisubs = window.unisubs || [];
            window.unisubs.DFXP = DFXP;

            // Create an instance of the DFXP wrapper with this XML.
            window.x = new window.unisubs.DFXP();
            window.x.init(resp);
        }
    });
});
<commit_msg>Make setStartTime and setEndTime be setters and getters.<commit_after>// Amara, universalsubtitles.org
//
// Copyright (C) 2012 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

var DFXP = function(DFXP) {
    /*
     * A utility for working with DFXP subs.
     */

    var that = this;

    this.init = function(xml) {

        // Store the original XML for comparison later.
        this.$originalXml = $(xml.documentElement).clone();

        // Store the working XML for local edits.
        this.$xml = $(xml.documentElement).clone();

    };

    // Helper methods.
    this.utils = {

        xmlToString: function(xml) {
            /*
             * Convert an XML document to a string.
             * Accepts: document object (XML tree)
             * Returns: string
             */

            var xmlString;

            // For Internet Explorer.
            if (window.ActiveXObject) {
                xmlString = xml.xml;

            // Everyone else.
            } else {
                xmlString = (new XMLSerializer()).serializeToString(xml);
            }

            return xmlString;
        }

    };

    this.addSubtitle = function(after, newAttrs) {
        /*
         * For adding a new subtitle to this set.
         *
         * If `after` is provided, we'll place the new subtitle directly
         * after that one. Otherwise, we'll place the new subtitle at the
         * end.
         *
         * `newAttrs` is an optional JSON object specifying the attributes to
         * be applied to the new element.
         *
         * Returns: new subtitle element
         */

        if (!after) {
            after = this.getLastSubtitle();
        }

        // Create the new element and any specified attributes.
        var newSubtitle = $('

').attr(newAttrs || {});

        // Finally, place the new subtitle.
        $(after).after(newSubtitle);

        return newSubtitle.get(0);
    };
    this.changesMade = function() {
        /*
         * Check to see if any changes have been made to the working XML.
         *
         * Returns: true || false
         */

        var originalString = that.utils.xmlToString(that.$originalXml.get(0));
        var xmlString = that.utils.xmlToString(that.$xml.get(0));

        return originalString != xmlString;
    };
    this.endTime = function(index, endTime) {
        /*
         * Given the zero-index of the subtitle to be updated,
         * set the end time.
         *
         * If no endTime is provided, simply return the current
         * end time.
         *
         * Returns: current end time (string)
         */

        var subtitle = this.getSubtitles().get(index);

        if (subtitle) {

            var $subtitle = $(subtitle);

            if (endTime) {
                $subtitle.attr('end', endTime);
            }

            return $subtitle.attr('end');

        } else {
            throw new Error('DFXP: No subtitle exists with that index.');
        }
    };
    this.removeSubtitle = function(index) {
        /*
         * Given the zero-index of the subtitle to be removed,
         * remove it from the node tree.
         *
         * Returns: true || false
         */

        // If an index is not provided, throw an error.
        if (!index) {
            throw new Error('DFXP: You must supply an index to removeSubtitle()');
        }

        var subtitle = this.getSubtitles().get(index);

        if (subtitle) {
            $(subtitle).remove();
            return true;
        } else {
            throw new Error('DFXP: No subtitle exists with that index.');
        }
    };
    this.getLastSubtitle = function() {
        /*
         * Retrieve the last subtitle in this set.
         *
         * Returns: last subtitle element
         */

        // Cache the selection.
        var $subtitles = this.getSubtitles();

        return $subtitles[$subtitles.length - 1];
    };
    this.getSubtitles = function() {
        /*
         * Retrieve the current set of subtitles.
         *
         * Returns: jQuery selection of nodes.
         */

        return $('div > p', this.$xml);
    };
    this.needsSyncing = function(indexOrElement) {
        /*
         * Given the zero-index or the element of the subtitle to be
         * checked, determine whether the subtitle needs to be synced.
         *
         * In most cases, if a subtitle has either no start time,
         * or no end time, it needs to be synced. However, if the
         * subtitle is the last in the list, the end time may be
         * omitted.
         *
         * Returns: true || false
         */

        // If an index or an object is not provided, throw an error.
        if (typeof indexOrElement !== 'number' && typeof indexOrElement !== 'object') {
            throw new Error('DFXP: You must supply either an index or an element to needsSyncing()');
        }

        var subtitle;

        // If indexOrElement is a number, we'll need to query the DOM to
        // get the element.
        //
        // Note: you should only use this approach for checking one-off
        // subtitles. If you're checking more than one subtitle, it's much
        // faster to pass along pre-selected elements instead.
        if (typeof indexOrElement === 'number') {
            subtitle = this.getSubtitles().get(indexOrElement);

        // Otherwise, just use the element.
        } else {
            subtitle = indexOrElement;
        }

        if (subtitle) {

            var $subtitle = $(subtitle);

            var startTime = $subtitle.attr('begin');
            var endTime = $subtitle.attr('end');

            // If start time is empty, it always needs to be synced.
            if (startTime === '') {
                return true;
            }

            // If the end time is empty and this is not the last subtitle,
            // it needs to be synced.
            if (endTime === '' && (subtitle !== this.getLastSubtitle())) {
                return true;
            }

            // Otherwise, we're good.
            return false;

        } else {
            throw new Error('DFXP: No subtitle exists with that index.');
        }
    };
    this.needsAnySynced = function() {
        /*
         * Determine whether any of the subtitles in the set need
         * to be synced.
         *
         * Returns: true || false
         */

        var needsAnySynced = false;

        // Caching the current subtitle set drastically cuts down on processing
        // time for iterating through large subtitle sets.
        var $subtitles = this.getSubtitles();

        for (var i = 0; i < $subtitles.length; i++) {

            // We're going to pass the actual element instead of an integer. This
            // means needsSyncing doesn't need to hit the DOM to find the element.
            if (this.needsSyncing($subtitles.get(i))) {
                needsAnySynced = true;
            }
        }

        return needsAnySynced;
    };
    this.startTime = function(index, startTime) {
        /*
         * Given the zero-index of the subtitle to be updated,
         * set the start time.
         *
         * If no startTime is provided, simply return the current
         * start time.
         *
         * Returns: current start time (string)
         */

        var subtitle = this.getSubtitles().get(index);

        if (subtitle) {

            var $subtitle = $(subtitle);

            if (startTime) {
                $subtitle.attr('begin', startTime);
            }

            return $subtitle.attr('begin');

        } else {
            throw new Error('DFXP: No subtitle exists with that index.');
        }
    };
    this.subtitlesCount = function() {
        /*
         * Retrieve the current number of subtitles.
         *
         * Returns: integer
         */

        return this.getSubtitles().length;
    };
};

$(function() {
    $.ajax({
        type: 'get',
        url: '/site_media/src/js/dfxp/sample.dfxp.xml',
        dataType: 'xml',
        success: function(resp) {
            window.unisubs = window.unisubs || [];
            window.unisubs.DFXP = DFXP;

            // Create an instance of the DFXP wrapper with this XML.
            window.x = new window.unisubs.DFXP();
            window.x.init(resp);
        }
    });
});
<|endoftext|>


<commit_before>/**
 * Created by wayne on 2/14/15.
 */

var Schedule = require('../models/scheduleModelMongo');

var makeSchedule = function(start, end, minutes) {
  var result = [];

  start = nextTime(start, 0);

  while (Number(start) < Number(end)) {
    result.push({
      time: start,
      reserved: false,
      reservedBy: null,
      numPlayers: 4,
      players: []
    });
    start = nextTime(start, minutes);
  }

  return result;

};

var nextTime = function(timeIn, timeInc) {

  // must hae 4 dude
  timeIn = ('000' + timeIn).slice(-4);
  // snag hours mins from string
  var hours = Number(timeIn.slice(0,2));
  var minutes = Number(timeIn.slice(2));
  // add timeInc for next teetime
  minutes += +timeInc;
  if (minutes > 59) {     // wrap hours
    minutes -= 60;
    hours += 1;
  }
  // return: hours to 2 char + min to 2 char
  return ('0' + hours).slice(-2) + ('0' + minutes).slice(-2);

};

var addSchedule = function(data, callback) {

  // get a schedule for the whole day
  var teetimes = makeSchedule(data.start, data.end, data.interval);
  // prep data to save
  var scheduleData = {
    courseId: data.courseId,
    date: data.date,
    teetimes: teetimes
  };

  var schedule = new Schedule(scheduleData);

  schedule.save(function(error, schedule){
    if (error) {
      return callback && callback(error, null);
    }
    return callback && callback(null, schedule);
  });
};

var findSchedule = function(data, callback) {
  Schedule.findOne(data, function(error, schedule){
    if (error) {
      return callback && callback(error, null);
    }
    return callback && callback(null, schedule);
  });
};

var findSchedules = function(data, callback) {
  Schedule.find(data, function(error, schedules){
    if (error) {
      return callback && callback(error, null);
    }
    return callback && callback(null, schedules);
  });
};

// id = courseId
// date = 'MMDDYYYY' style date
// start = 'HHMM' start time
// end = 'HHMM' end time
var hasTeeTime = function(data, callback) {
  Schedule.findOne({ courseId: data.courseId, date: data.date }, function(error, schedule){
    if (error) {
      return callback && callback(error, null);
    }
    // This is stupid but required. messing with the array live changes it's length causing endless grief.
    // Instead, we build a new 'avail' array and attach it after the scan ...
    var availableTeeTimes = [];
    if (schedule === null) return callback(null, null);
    for (var i = 0; i < schedule.teetimes.length; i++) {
      if (schedule.teetimes[i].reserved === false && schedule.teetimes[i].time > data.start && schedule.teetimes[i].time < data.end) {
        availableTeeTimes.push(schedule.teetimes[i]);
      }
    }
    schedule.teetimes = availableTeeTimes;
    return callback && callback(null, schedule);
  });
};

// userId
// teetimeId
var bookTeeTime = function(data, callback) {
  console.log("data input to bookTeeTime:", data);
  Schedule.findOne({ "teetimes._id": data.teetimeId }, function(error, schedule){
    if (error) {
      return callback && callback(error, null);
    }
    if (schedule == null) {
      return callback && callback("Tee time not available", null);
    }

    for (var i = 0; i < schedule.teetimes.length; i++) {
      if (schedule.teetimes[i]._id.toString() === data.teetimeId) {
        schedule.teetimes[i].reserved = true;
        schedule.teetimes[i].reservedBy = data.userId;

        schedule.save(function(error, data){
          if (error) {
            console.log(error);
            return callback && callback(error, null);
          }
          //console.log("Tee time saved", data);

          return callback && callback(null, data);

        });
      }
    }

    // hahahahahahaha -- did u feel the async burn?
    // vvvvvvvvvvvvvv - bad dog!
    //return callback && callback('Could not update tee time.', null);

});

  //Schedule.update({ courseId: data.courseId, date: data.date, time: data.time}, function(error, schedule) {
  //  if (error) {
  //    return callback && callback(error, null);
  //  }
  //});
};

module.exports = {
  addSchedule: addSchedule,
  findSchedule: findSchedule,
  findSchedules: findSchedules,
  hasTeeTime: hasTeeTime,
  bookTeeTime: bookTeeTime
};
<commit_msg>Changed book tee time to accept user cell number<commit_after>/**
 * Created by wayne on 2/14/15.
 */

var Schedule = require('../models/scheduleModelMongo');

var makeSchedule = function(start, end, minutes) {
  var result = [];

  start = nextTime(start, 0);

  while (Number(start) < Number(end)) {
    result.push({
      time: start,
      reserved: false,
      reservedBy: null,
      numPlayers: 4,
      players: []
    });
    start = nextTime(start, minutes);
  }

  return result;

};

var nextTime = function(timeIn, timeInc) {

  // must hae 4 dude
  timeIn = ('000' + timeIn).slice(-4);
  // snag hours mins from string
  var hours = Number(timeIn.slice(0,2));
  var minutes = Number(timeIn.slice(2));
  // add timeInc for next teetime
  minutes += +timeInc;
  if (minutes > 59) {     // wrap hours
    minutes -= 60;
    hours += 1;
  }
  // return: hours to 2 char + min to 2 char
  return ('0' + hours).slice(-2) + ('0' + minutes).slice(-2);

};

var addSchedule = function(data, callback) {

  // get a schedule for the whole day
  var teetimes = makeSchedule(data.start, data.end, data.interval);
  // prep data to save
  var scheduleData = {
    courseId: data.courseId,
    date: data.date,
    teetimes: teetimes
  };

  var schedule = new Schedule(scheduleData);

  schedule.save(function(error, schedule){
    if (error) {
      return callback && callback(error, null);
    }
    return callback && callback(null, schedule);
  });
};

var findSchedule = function(data, callback) {
  Schedule.findOne(data, function(error, schedule){
    if (error) {
      return callback && callback(error, null);
    }
    return callback && callback(null, schedule);
  });
};

var findSchedules = function(data, callback) {
  Schedule.find(data, function(error, schedules){
    if (error) {
      return callback && callback(error, null);
    }
    return callback && callback(null, schedules);
  });
};

// id = courseId
// date = 'MMDDYYYY' style date
// start = 'HHMM' start time
// end = 'HHMM' end time
var hasTeeTime = function(data, callback) {
  Schedule.findOne({ courseId: data.courseId, date: data.date }, function(error, schedule){
    if (error) {
      return callback && callback(error, null);
    }
    // This is stupid but required. messing with the array live changes it's length causing endless grief.
    // Instead, we build a new 'avail' array and attach it after the scan ...
    var availableTeeTimes = [];
    if (schedule === null) return callback(null, null);
    for (var i = 0; i < schedule.teetimes.length; i++) {
      if (schedule.teetimes[i].reserved === false && schedule.teetimes[i].time > data.start && schedule.teetimes[i].time < data.end) {
        availableTeeTimes.push(schedule.teetimes[i]);
      }
    }
    schedule.teetimes = availableTeeTimes;
    return callback && callback(null, schedule);
  });
};

// userId
// teetimeId
var bookTeeTime = function(data, callback) {
  console.log("data input to bookTeeTime:", data);
  Schedule.findOne({ "teetimes._id": data.teetimeId }, function(error, schedule){
    if (error) {
      return callback && callback(error, null);
    }
    if (schedule == null) {
      return callback && callback("Tee time not available", null);
    }

    for (var i = 0; i < schedule.teetimes.length; i++) {
      if (schedule.teetimes[i]._id.toString() === data.teetimeId) {
        schedule.teetimes[i].reserved = true;
        schedule.teetimes[i].reservedBy = data.cell;

        schedule.save(function(error, data){
          if (error) {
            console.log(error);
            return callback && callback(error, null);
          }
          //console.log("Tee time saved", data);

          return callback && callback(null, data);

        });
      }
    }

    // hahahahahahaha -- did u feel the async burn?
    // vvvvvvvvvvvvvv - bad dog!
    //return callback && callback('Could not update tee time.', null);

});

  //Schedule.update({ courseId: data.courseId, date: data.date, time: data.time}, function(error, schedule) {
  //  if (error) {
  //    return callback && callback(error, null);
  //  }
  //});
};

module.exports = {
  addSchedule: addSchedule,
  findSchedule: findSchedule,
  findSchedules: findSchedules,
  hasTeeTime: hasTeeTime,
  bookTeeTime: bookTeeTime
};
<|endoftext|>


<commit_before>var path = require('path')
var config = require('../config')
var utils = require('./utils')
var webpack = require('webpack')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var env = process.env.NODE_ENV === 'testing'
  ? require('../config/test.env')
  : require('../config/prod.env')

var argv = require('yargs').argv

var webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  devtool: false, // config.build.productionSourceMap ? '#source-map' : false,
  output: {
    path: config.build.assetsRoot,
    publicPath: argv.cdn ? 'https://static.vux.li/demos/v2/' : './',
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),
    // extract css into its own file
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: process.env.NODE_ENV === 'testing'
        ? 'index.html'
        : config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    })
  ]
})

if (config.build.productionGzip) {
  var CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig
<commit_msg>doc: switch to upyun cdn<commit_after>var path = require('path')
var config = require('../config')
var utils = require('./utils')
var webpack = require('webpack')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var env = process.env.NODE_ENV === 'testing'
  ? require('../config/test.env')
  : require('../config/prod.env')

var argv = require('yargs').argv

var webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  devtool: false, // config.build.productionSourceMap ? '#source-map' : false,
  output: {
    path: config.build.assetsRoot,
    publicPath: argv.cdn ? 'https://upcdn.vux.li/demos/v2/' : './',
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),
    // extract css into its own file
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: process.env.NODE_ENV === 'testing'
        ? 'index.html'
        : config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    })
  ]
})

if (config.build.productionGzip) {
  var CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig
<|endoftext|>


<commit_before>/*
Copyright (c) 2011, Chris Umbel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

var util = require('util'),
    SingularPluralInflector = require('./singular_plural_inflector'),
    FormSet = require('./form_set');

function attach() {
    var inflector = this;

    String.prototype.singularizePresentVerb = function() {
        return inflector.singularize(this);
    }

    String.prototype.pluralizePresentVerb = function() {
        return inflector.pluralize(this);
    }
}

var VerbInflector = function() {
    this.ambiguous = [
        'will'
    ];

    this.attach = attach;

    this.customPluralForms = [];
    this.customSingularForms = [];
    this.singularForms = new FormSet();
    this.pluralForms = new FormSet();

    this.addIrregular("am", "are");
    this.addIrregular("is", "are");
    this.addIrregular("was", "were");

    this.singularForms.regularForms.push([/ed$/i, 'ed']);
    this.singularForms.regularForms.push([/ss$/i, 'sses']);
    this.singularForms.regularForms.push([/x$/i, 'xes']);
    this.singularForms.regularForms.push([/(h|z|o)$/i, '$1es']);
    this.singularForms.regularForms.push([/$zz/i, 'zzes']);
    this.singularForms.regularForms.push([/$/i, 's']);

    this.pluralForms.regularForms.push([/sses$/i, 'ss']);
    this.pluralForms.regularForms.push([/xes$/i, 'x']);
    this.pluralForms.regularForms.push([/([cs])hes$/i, '$1h']);
    this.pluralForms.regularForms.push([/zzes$/i, 'zz']);
    this.pluralForms.regularForms.push([/([^h|z|o])es$/i, '$1e']);
    this.pluralForms.regularForms.push([/e?s$/i, '']);
};

util.inherits(VerbInflector, SingularPluralInflector);

module.exports = VerbInflector;
<commit_msg>'ies' finishing verbs' plural form to 'y'<commit_after>/*
Copyright (c) 2011, Chris Umbel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

var util = require('util'),
    SingularPluralInflector = require('./singular_plural_inflector'),
    FormSet = require('./form_set');

function attach() {
    var inflector = this;

    String.prototype.singularizePresentVerb = function() {
        return inflector.singularize(this);
    }

    String.prototype.pluralizePresentVerb = function() {
        return inflector.pluralize(this);
    }
}

var VerbInflector = function() {
    this.ambiguous = [
        'will'
    ];

    this.attach = attach;

    this.customPluralForms = [];
    this.customSingularForms = [];
    this.singularForms = new FormSet();
    this.pluralForms = new FormSet();

    this.addIrregular("am", "are");
    this.addIrregular("is", "are");
    this.addIrregular("was", "were");

    this.singularForms.regularForms.push([/ed$/i, 'ed']);
    this.singularForms.regularForms.push([/ss$/i, 'sses']);
    this.singularForms.regularForms.push([/x$/i, 'xes']);
    this.singularForms.regularForms.push([/(h|z|o)$/i, '$1es']);
    this.singularForms.regularForms.push([/$zz/i, 'zzes']);
    this.singularForms.regularForms.push([/$/i, 's']);

    this.pluralForms.regularForms.push([/sses$/i, 'ss']);
    this.pluralForms.regularForms.push([/xes$/i, 'x']);
    this.pluralForms.regularForms.push([/([cs])hes$/i, '$1h']);
    this.pluralForms.regularForms.push([/zzes$/i, 'zz']);
    this.pluralForms.regularForms.push([/([^h|z|o|i])es$/i, '$1e']);
    this.pluralForms.regularForms.push([/ies$/i, 'y']);//flies->fly
    this.pluralForms.regularForms.push([/e?s$/i, '']);
};

util.inherits(VerbInflector, SingularPluralInflector);

module.exports = VerbInflector;
<|endoftext|>