<commit_before>import * as core from 'core-js';
import * as LogManager from 'aurelia-logging';
import {Origin} from 'aurelia-metadata';
import {Loader,TemplateRegistryEntry} from 'aurelia-loader';
import {Container} from 'aurelia-dependency-injection';
import {ViewCompiler} from './view-compiler';
import {ViewResources} from './view-resources';
import {ModuleAnalyzer, ResourceDescription} from './module-analyzer';
import {ViewFactory} from './view-factory';
import {ResourceLoadContext, ViewCompileInstruction} from './instructions';

var logger = LogManager.getLogger('templating');

function ensureRegistryEntry(loader, urlOrRegistryEntry){
  if(urlOrRegistryEntry instanceof TemplateRegistryEntry){
    return Promise.resolve(urlOrRegistryEntry);
  }

  return loader.loadTemplate(urlOrRegistryEntry);
}

class ProxyViewFactory {
  constructor(promise){
    promise.then(x => this.absorb(x));
  }

  absorb(factory){
    this.create = factory.create.bind(factory);
  }
}

export class ViewEngine {
  static inject() { return [Loader, Container, ViewCompiler, ModuleAnalyzer, ViewResources]; }
  constructor(loader:Loader, container:Container, viewCompiler:ViewCompiler, moduleAnalyzer:ModuleAnalyzer, appResources:ViewResources){
    this.loader = loader;
    this.container = container;
    this.viewCompiler = viewCompiler;
    this.moduleAnalyzer = moduleAnalyzer;
    this.appResources = appResources;
    this._pluginMap = {};
  }

  addResourcePlugin(extension: string, implementation: string){
     let name = extension.replace('.', '') + '-resource-plugin';
     this._pluginMap[extension] = name;
     this.loader.addPlugin(name, implementation);
  }

  enhance(container:Container, element:Element, resources:ViewResources, bindingContext?:Object):View{
    let instructions = {};
    this.viewCompiler.compileNode(element, resources, instructions, element.parentNode, 'root', true);

    let factory = new ViewFactory(element, instructions, resources);
    return factory.create(container, bindingContext, { enhance:true });
  }

  loadViewFactory(urlOrRegistryEntry:string|TemplateRegistryEntry, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise<ViewFactory>{
    loadContext = loadContext || new ResourceLoadContext();

    return ensureRegistryEntry(this.loader, urlOrRegistryEntry).then(viewRegistryEntry => {
      if(viewRegistryEntry.onReady){
        if(loadContext.doesNotHaveDependency(urlOrRegistryEntry)){
          loadContext.addDependency(urlOrRegistryEntry);
          return viewRegistryEntry.onReady;
        }

        return Promise.resolve(new ProxyViewFactory(viewRegistryEntry.onReady));
      }

      loadContext.addDependency(urlOrRegistryEntry);

      return viewRegistryEntry.onReady = this.loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext).then(resources => {
        viewRegistryEntry.setResources(resources);
        var viewFactory = this.viewCompiler.compile(viewRegistryEntry.template, resources, compileInstruction);
        viewRegistryEntry.setFactory(viewFactory);
        return viewFactory;
      });
    });
  }

  loadTemplateResources(viewRegistryEntry:TemplateRegistryEntry, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise<ViewResources>{
    var resources = new ViewResources(this.appResources, viewRegistryEntry.address),
        dependencies = viewRegistryEntry.dependencies,
        importIds, names;

    compileInstruction = compileInstruction || ViewCompileInstruction.normal;

    if(dependencies.length === 0 && !compileInstruction.associatedModuleId){
      return Promise.resolve(resources);
    }

    importIds = dependencies.map(x => x.src);
    names = dependencies.map(x => x.name);
    logger.debug(`importing resources for ${viewRegistryEntry.address}`, importIds);

    return this.importViewResources(importIds, names, resources, compileInstruction, loadContext);
  }

  importViewModelResource(moduleImport:string, moduleMember:string):Promise<ResourceDescription>{
    return this.loader.loadModule(moduleImport).then(viewModelModule => {
      var normalizedId = Origin.get(viewModelModule).moduleId,
          resourceModule = this.moduleAnalyzer.analyze(normalizedId, viewModelModule, moduleMember);

      if(!resourceModule.mainResource){
        throw new Error(`No view model found in module "${moduleImport}".`);
      }

      resourceModule.analyze(this.container);

      return resourceModule.mainResource;
    });
  }

  importViewResources(moduleIds:string[], names:string[], resources:ViewResources, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise<ViewResources>{
    loadContext = loadContext || new ResourceLoadContext();
    compileInstruction = compileInstruction || ViewCompileInstruction.normal;

    moduleIds = moduleIds.map(x => this._applyLoaderPlugin(x));

    return this.loader.loadAllModules(moduleIds).then(imports => {
      var i, ii, analysis, normalizedId, current, associatedModule,
          container = this.container,
          moduleAnalyzer = this.moduleAnalyzer,
          allAnalysis = new Array(imports.length);

      //analyze and register all resources first
      //this enables circular references for global refs
      //and enables order independence
      for(i = 0, ii = imports.length; i < ii; ++i){
        current = imports[i];
        normalizedId = Origin.get(current).moduleId;

        analysis = moduleAnalyzer.analyze(normalizedId, current);
        analysis.analyze(container);
        analysis.register(resources, names[i]);

        allAnalysis[i] = analysis;
      }

      if(compileInstruction.associatedModuleId){
        associatedModule = moduleAnalyzer.getAnalysis(compileInstruction.associatedModuleId);

        if(associatedModule){
          associatedModule.register(resources);
        }
      }

      //cause compile/load of any associated views second
      //as a result all globals have access to all other globals during compilation
      for(i = 0, ii = allAnalysis.length; i < ii; ++i){
        allAnalysis[i] = allAnalysis[i].load(container, loadContext);
      }

      return Promise.all(allAnalysis).then(() => resources);
    });
  }

  _applyLoaderPlugin(id){
    let index = id.lastIndexOf('.');
    if(index !== -1){
      let ext = id.substring(index);
      let pluginName = this._pluginMap[ext];

      if(pluginName === undefined){
        return id;
      }

      return this.loader.applyPluginToUrl(id, pluginName);
    }

    return id;
  }
}
<commit_msg>fix(view-engine): proxy factories missing cache api<commit_after>import * as core from 'core-js';
import * as LogManager from 'aurelia-logging';
import {Origin} from 'aurelia-metadata';
import {Loader,TemplateRegistryEntry} from 'aurelia-loader';
import {Container} from 'aurelia-dependency-injection';
import {ViewCompiler} from './view-compiler';
import {ViewResources} from './view-resources';
import {ModuleAnalyzer, ResourceDescription} from './module-analyzer';
import {ViewFactory} from './view-factory';
import {ResourceLoadContext, ViewCompileInstruction} from './instructions';

var logger = LogManager.getLogger('templating');

function ensureRegistryEntry(loader, urlOrRegistryEntry){
  if(urlOrRegistryEntry instanceof TemplateRegistryEntry){
    return Promise.resolve(urlOrRegistryEntry);
  }

  return loader.loadTemplate(urlOrRegistryEntry);
}

class ProxyViewFactory {
  constructor(promise){
    promise.then(x => this.viewFactory = x);
  }

  create(container: Container, bindingContext?: Object, createInstruction?: ViewCreateInstruction, element?: Element): View {
    return this.viewFactory.create(container, bindingContext, createInstruction, element);
  }

  get isCaching(){
    return this.viewFactory.isCaching;
  }

  setCacheSize(size: number | string, doNotOverrideIfAlreadySet: boolean): void {
    this.viewFactory.setCacheSize(size, doNotOverrideIfAlreadySet);
  }

  getCachedView(): View {
    return this.viewFactory.getCachedView();
  }

  returnViewToCache(view: View): void {
    this.viewFactory.returnViewToCache(view);
  }
}

export class ViewEngine {
  static inject() { return [Loader, Container, ViewCompiler, ModuleAnalyzer, ViewResources]; }
  constructor(loader:Loader, container:Container, viewCompiler:ViewCompiler, moduleAnalyzer:ModuleAnalyzer, appResources:ViewResources){
    this.loader = loader;
    this.container = container;
    this.viewCompiler = viewCompiler;
    this.moduleAnalyzer = moduleAnalyzer;
    this.appResources = appResources;
    this._pluginMap = {};
  }

  addResourcePlugin(extension: string, implementation: string){
     let name = extension.replace('.', '') + '-resource-plugin';
     this._pluginMap[extension] = name;
     this.loader.addPlugin(name, implementation);
  }

  enhance(container:Container, element:Element, resources:ViewResources, bindingContext?:Object):View{
    let instructions = {};
    this.viewCompiler.compileNode(element, resources, instructions, element.parentNode, 'root', true);

    let factory = new ViewFactory(element, instructions, resources);
    return factory.create(container, bindingContext, { enhance:true });
  }

  loadViewFactory(urlOrRegistryEntry:string|TemplateRegistryEntry, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise<ViewFactory>{
    loadContext = loadContext || new ResourceLoadContext();

    return ensureRegistryEntry(this.loader, urlOrRegistryEntry).then(viewRegistryEntry => {
      if(viewRegistryEntry.onReady){
        if(loadContext.doesNotHaveDependency(urlOrRegistryEntry)){
          loadContext.addDependency(urlOrRegistryEntry);
          return viewRegistryEntry.onReady;
        }

        return Promise.resolve(new ProxyViewFactory(viewRegistryEntry.onReady));
      }

      loadContext.addDependency(urlOrRegistryEntry);

      return viewRegistryEntry.onReady = this.loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext).then(resources => {
        viewRegistryEntry.setResources(resources);
        var viewFactory = this.viewCompiler.compile(viewRegistryEntry.template, resources, compileInstruction);
        viewRegistryEntry.setFactory(viewFactory);
        return viewFactory;
      });
    });
  }

  loadTemplateResources(viewRegistryEntry:TemplateRegistryEntry, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise<ViewResources>{
    var resources = new ViewResources(this.appResources, viewRegistryEntry.address),
        dependencies = viewRegistryEntry.dependencies,
        importIds, names;

    compileInstruction = compileInstruction || ViewCompileInstruction.normal;

    if(dependencies.length === 0 && !compileInstruction.associatedModuleId){
      return Promise.resolve(resources);
    }

    importIds = dependencies.map(x => x.src);
    names = dependencies.map(x => x.name);
    logger.debug(`importing resources for ${viewRegistryEntry.address}`, importIds);

    return this.importViewResources(importIds, names, resources, compileInstruction, loadContext);
  }

  importViewModelResource(moduleImport:string, moduleMember:string):Promise<ResourceDescription>{
    return this.loader.loadModule(moduleImport).then(viewModelModule => {
      var normalizedId = Origin.get(viewModelModule).moduleId,
          resourceModule = this.moduleAnalyzer.analyze(normalizedId, viewModelModule, moduleMember);

      if(!resourceModule.mainResource){
        throw new Error(`No view model found in module "${moduleImport}".`);
      }

      resourceModule.analyze(this.container);

      return resourceModule.mainResource;
    });
  }

  importViewResources(moduleIds:string[], names:string[], resources:ViewResources, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise<ViewResources>{
    loadContext = loadContext || new ResourceLoadContext();
    compileInstruction = compileInstruction || ViewCompileInstruction.normal;

    moduleIds = moduleIds.map(x => this._applyLoaderPlugin(x));

    return this.loader.loadAllModules(moduleIds).then(imports => {
      var i, ii, analysis, normalizedId, current, associatedModule,
          container = this.container,
          moduleAnalyzer = this.moduleAnalyzer,
          allAnalysis = new Array(imports.length);

      //analyze and register all resources first
      //this enables circular references for global refs
      //and enables order independence
      for(i = 0, ii = imports.length; i < ii; ++i){
        current = imports[i];
        normalizedId = Origin.get(current).moduleId;

        analysis = moduleAnalyzer.analyze(normalizedId, current);
        analysis.analyze(container);
        analysis.register(resources, names[i]);

        allAnalysis[i] = analysis;
      }

      if(compileInstruction.associatedModuleId){
        associatedModule = moduleAnalyzer.getAnalysis(compileInstruction.associatedModuleId);

        if(associatedModule){
          associatedModule.register(resources);
        }
      }

      //cause compile/load of any associated views second
      //as a result all globals have access to all other globals during compilation
      for(i = 0, ii = allAnalysis.length; i < ii; ++i){
        allAnalysis[i] = allAnalysis[i].load(container, loadContext);
      }

      return Promise.all(allAnalysis).then(() => resources);
    });
  }

  _applyLoaderPlugin(id){
    let index = id.lastIndexOf('.');
    if(index !== -1){
      let ext = id.substring(index);
      let pluginName = this._pluginMap[ext];

      if(pluginName === undefined){
        return id;
      }

      return this.loader.applyPluginToUrl(id, pluginName);
    }

    return id;
  }
}
<|endoftext|>


<commit_before>var _ = require('lodash'),
    Chance = require('chance'),
    jsonPath = require('jsonpath')

var hazy = {}

hazy.config = {
  seed: null,
  matchers: {
    use: true
  }
}

hazy.meta = {
  types: {
    basic  : ['bool', 'character', 'integer', 'natural', 'string'],
    text   : ['paragraph', 'sentence', 'syllable', 'word'],
    person : ['age', 'birthday', 'cpf', 'first', 'gender', 'last', 'name', 'prefix', 'ssn', 'suffix'],
    mobile : ['android_id', 'apple_token', 'bb_pin', 'wp7_anid', 'wp8_anid2'],
    web    : ['color', 'domain', 'email', 'fbid', 'google_analytics', 'hashtag', 'ip', 'ipv6', 'klout', 'tld', 'twitter', 'url'],
    geo    : ['address', 'altitude', 'areacode', 'city', 'coordinates', 'country', 'depth', 'geohash', 'latitude', 'longitude', 'phone', 'postal', 'province', 'state', 'street', 'zip'],
    time   : ['ampm', 'date', 'hammertime', 'hour', 'millisecond', 'minute', 'month', 'second', 'timestamp', 'year'],
    misc   : ['guid', 'hash', 'hidden', 'n', 'normal', 'radio', 'rpg', 'tv', 'unique', 'weighted']

    // aliases
    // '?' : 'bool',
    // '#' : 'number',
    // '_' : 'string',
    // '$' : this.finance,
  }
}

hazy.lang = {
  // expression: /\|(:|~|@)(.*?)?\|/g,
  expression: {
    first : /\|(:|~|@)(.*?)?\|/,
    all   : /\|(:|~|@)(.*?)?\|/g
  },

  tokens: {
    "|": function(prev, next) { // expression start/end
      var isPrevToken    = this.validate(prev),
          isNextTokenEnd = /\|/.test(next)

      if (isPrevToken || isNextTokenEnd) {
        throw hazy.lang.exception('Cannot define an empty expression')
      }

      if (!next) {
        // return true
        // TODO - return a special value saying that this is the end of the token expression sequence. currenlty not technically needed
      }
    },

    ":": function(prev, next) { // property accessor
      if (!prev) {
        throw 'Syntax error, : requires a left operand'
      }

      return prev[next]
    },

    "~": function(prev, next, rest) { // random data
      var randProp   = next.split(':')[0] // match text to next : or |
          randVal    = next.split(':')[1]
          canUseProp = hazy.random.hasOwnProperty(randProp)

      if (canUseProp) {
        var randObjByProp  = hazy.random[randProp]
            randObjSubType = randVal // get property of random operator following ":"

        if (!randObjByProp || !randObjByProp[randObjSubType]) {
          throw hazy.lang.exception('Invalid random data type "' + randObjSubType + '". Supported:', hazy.meta.types[randProp])
        }

        return randObjByProp[randObjSubType]()
      } else {
        throw hazy.lang.exception('Invalid random data category "' + randProp + '". Supported', hazy.meta.types)
      }
    },

    "@": function(prev, next) { // link to stub
      return hazy.stub.get(next)
    },

    validate: function(token) {
      return this.hasOwnProperty(token)
    },

    process: function(token, prev, next, rest) {
      return _.bindKey(hazy.lang.tokens, token, prev, next, rest)()
    }
  },

  process: function(str) {
    var matches = str.split(this.expression.all)//str.match(this.expression)
    var tokens = []

    _.forEach(matches, function(match, i) {
      var isToken = hazy.lang.tokens.validate(match)

      if (isToken) {
        var prevMatch   = matches[i - 1],
            nextMatch   = matches[i + 1],
            restMatches = _.drop(matches, i + 1),
            tokenResult = this.tokens.process(match, prevMatch, nextMatch, restMatches)

        if (tokenResult) {
          // if processed token result is a string, substitute in original string as we iterate
          if (_.isString(tokenResult)) {
            str = str.replace(hazy.lang.expression.first, tokenResult)
          } else {
            tokens.push(tokenResult)
          }
        }
      }
    }, this)

    if (_.isString(tokens)) {
      return str
    }

    // // essentially detokenization. original str is returned if no reducing can be performed
    return _.reduce(tokens, function(total, n) { return total + n }) || str
  },

  exception: function(msg) {
    return '[Hazy syntax error] ' + msg
  }
}

hazy.random = _.mapValues(hazy.meta.types, function(value, key) {
  var hazyRandObj = {}

  _.forEach(value, function(v) {
     hazyRandObj[v] = function() { return new Chance()[v]() }
  })

  return hazyRandObj
})

hazy.stub = {
  pool: {},

  get: function(key) {
    return this.pool[key]
  },

  // FIXME - allow for optional non-lazy override. by defult this should return a function
  register: function(name, stub) {
    this.pool[name] = this.process(stub)
  },

  process: function(stub) { // dynamically process stub values by type (object, string, array, or function)
    var processedStub = {}

    if (_.isPlainObject(stub)) {
      _.mapKeys(stub, function(value, key) {
        var processedKey = hazy.lang.process(key),
            nextStub     = value

        processedStub[processedKey] = this.process(nextStub)
      }, this)
    }

    if (_.isArray(stub)) {
      return _.map(stub, hazy.lang.process)
    }

    if (_.isString(stub)) {
      return hazy.lang.process(stub)
    }

    if (_.isFunction(stub)) {
      return stub(null, hazy.config.seed) // TODO - provide/support per-instance seed and the object key
    }

    // TODO - determine if current stub matches a regex or name
    // hazy.stub.
    if (hazy.config.matchers.use && hazy.matcher.hasMatch(stub)) {
      console.log('MATCHED ', stub)
    }

    return processedStub
  },

  load: function(file) { // TODO - load from FS
    if (_.isArray(file)) {
      _.forEach(file, function() {

      })
    } else {

    }
  },

  write: function() {
    // TODO - write to FS
  }
}

// Matching filters which can be injected into your application before stubs are allocated to the stub pool

hazy.matcher = {
  pool: {},

  register: function(path, value) {
    this.pool[path] = value
  },

  addConfig: function(config) {
    if (!_.isEmpty(hazy.stub.pool))
      throw 'Matches can only be added before stubs are in the stub pool'

    var stubName       = config.stub,
        matcherPath    = config.path,
        matcherHandler = config.handler,
        matcherKey     = stubName || matcherPath

    this.pool[matcherKey] = {name: stubName, path: matcherPath, handler: matcherHandler}
  },

  hasMatch: function(stub) { // determines if a pattern applies to the provided stub (TODO - clearly optimize, madhax)
    var inPool      = _.isString(stub) && this.pool.hasOwnProperty(stub)
        matchExists = inPool || _.every(_.mapKeys(hazy.matcher.pool, function(v,pattern) {
          return _.isString(stub) && !_.isUndefined(
            jsonPath.query(pattern, stub)
          )
        }), true)

    return matchExists
  },
}

// ------------------------------------------------------------ kitchen sink

hazy.matcher.addConfig({
  stub: 'someDog',
  handler: function() {
    // do something to the stub
    console.log('derp')
  }
})

hazy.stub.register('someDude', {
  name: '|~person:name|',
  ssn: '|~person:ssn| (not really)',
  id: '|~misc:guid|'
})

hazy.stub.register('someDog', {
  name: ' !!Letter |~basic:character| --- |~basic:character|',
  owner: '|@someDude|'
})

console.log('HAZY SEED POOL ', hazy.stub.get('someDog'))<commit_msg>array parsing<commit_after>var _ = require('lodash'),
    Chance = require('chance'),
    jsonPath = require('jsonpath')

var hazy = {}

hazy.config = {
  seed: null,
  matchers: {
    use: true
  }
}

hazy.meta = {
  types: {
    basic  : ['bool', 'character', 'integer', 'natural', 'string'],
    text   : ['paragraph', 'sentence', 'syllable', 'word'],
    person : ['age', 'birthday', 'cpf', 'first', 'gender', 'last', 'name', 'prefix', 'ssn', 'suffix'],
    mobile : ['android_id', 'apple_token', 'bb_pin', 'wp7_anid', 'wp8_anid2'],
    web    : ['color', 'domain', 'email', 'fbid', 'google_analytics', 'hashtag', 'ip', 'ipv6', 'klout', 'tld', 'twitter', 'url'],
    geo    : ['address', 'altitude', 'areacode', 'city', 'coordinates', 'country', 'depth', 'geohash', 'latitude', 'longitude', 'phone', 'postal', 'province', 'state', 'street', 'zip'],
    time   : ['ampm', 'date', 'hammertime', 'hour', 'millisecond', 'minute', 'month', 'second', 'timestamp', 'year'],
    misc   : ['guid', 'hash', 'hidden', 'n', 'normal', 'radio', 'rpg', 'tv', 'unique', 'weighted']

    // aliases
    // '?' : 'bool',
    // '#' : 'number',
    // '_' : 'string',
    // '$' : this.finance,
  }
}

hazy.lang = {
  expression: {
    first : /\|(:|~|@)(.*?)?\|/,
    all   : /\|(:|~|@)(.*?)?\|/g
  },

  tokens: {
    "|": function(prev, next) { // expression start/end
      var isPrevToken    = this.validate(prev),
          isNextTokenEnd = /\|/.test(next)

      if (isPrevToken || isNextTokenEnd) {
        throw hazy.lang.exception('Cannot define an empty expression')
      }

      if (!next) {
        // return true
        // TODO - return a special value saying that this is the end of the token expression sequence. currenlty not technically needed
      }
    },

    ":": function(prev, next) { // property accessor
      if (!prev) {
        throw 'Syntax error, : requires a left operand'
      }

      return prev[next]
    },

    "~": function(prev, next, rest) { // random data
      var randProp   = next.split(':')[0] // match text to next : or |
          randVal    = next.split(':')[1]
          canUseProp = hazy.random.hasOwnProperty(randProp)

      if (canUseProp) {
        var randObjByProp  = hazy.random[randProp]
            randObjSubType = randVal // get property of random operator following ":"

        if (!randObjByProp || !randObjByProp[randObjSubType]) {
          throw hazy.lang.exception('Invalid random data type "' + randObjSubType + '". Supported:', hazy.meta.types[randProp])
        }

        return randObjByProp[randObjSubType]()
      } else {
        throw hazy.lang.exception('Invalid random data category "' + randProp + '". Supported', hazy.meta.types)
      }
    },

    "@": function(prev, next) { // link to stub
      return hazy.stub.get(next)
    },

    validate: function(token) {
      return this.hasOwnProperty(token)
    },

    process: function(token, prev, next, rest) {
      return _.bindKey(hazy.lang.tokens, token, prev, next, rest)()
    }
  },

  process: function(str) {
    var matches = str.split(hazy.lang.expression.all)
    var tokens = []

    _.forEach(matches, function(match, i) {
      var isToken = hazy.lang.tokens.validate(match)

      if (isToken) {
        var prevMatch   = matches[i - 1],
            nextMatch   = matches[i + 1],
            restMatches = _.drop(matches, i + 1),
            tokenResult = this.tokens.process(match, prevMatch, nextMatch, restMatches)

        if (tokenResult) {
          // if processed token result is a string, substitute in original string as we iterate
          if (_.isString(tokenResult)) {
            str = str.replace(hazy.lang.expression.first, tokenResult)
          } else {
            tokens.push(tokenResult)
          }
        }
      }
    }, this)

    // essentially detokenization. original str is returned if no reducing can be performed
    return _.reduce(tokens, function(total, n) { return total + n }) || str
  },

  exception: function(msg) {
    return '[Hazy syntax error] ' + msg
  }
}

hazy.random = _.mapValues(hazy.meta.types, function(value, key) {
  var hazyRandObj = {}

  _.forEach(value, function(v) {
     hazyRandObj[v] = function() { return new Chance()[v]() }
  })

  return hazyRandObj
})

hazy.stub = {
  pool: {},

  get: function(key) {
    return this.pool[key]
  },

  // FIXME - allow for optional non-lazy override. by defult this should return a function
  register: function(name, stub) {
    this.pool[name] = this.process(stub)
  },

  process: function(stub) { // dynamically process stub values by type (object, string, array, or function)
    var processedStub = stub

    if (_.isPlainObject(stub)) {
      _.mapKeys(stub, function(value, key) {
        var processedKey = hazy.lang.process(key),
            nextStub     = value

        processedStub[processedKey] = hazy.stub.process(nextStub)
      })
    }

    if (_.isString(stub)) {
      return hazy.lang.process(stub)
    }

    if (_.isArray(stub)) {
      return _.map(stub, hazy.stub.process)
    }

    if (_.isFunction(stub)) {
      return stub(null, hazy.config.seed) // TODO - provide/support per-instance seed and the object key
    }

    // TODO - determine if current stub matches a regex or name
    // hazy.stub.
    // if (hazy.config.matchers.use && hazy.matcher.hasMatch(stub)) {
    //   console.log('MATCHED ', stub)
    // }

    return processedStub
  },

  load: function(file) { // TODO - load from FS
    if (_.isArray(file)) {
      _.forEach(file, function() {

      })
    } else {

    }
  },

  write: function() {
    // TODO - write to FS
  }
}

// Matching filters which can be injected into your application before stubs are allocated to the stub pool

hazy.matcher = {
  pool: {},

  register: function(path, value) {
    this.pool[path] = value
  },

  addConfig: function(config) {
    if (!_.isEmpty(hazy.stub.pool))
      throw 'Matches can only be added before stubs are in the stub pool'

    var stubName       = config.stub,
        matcherPath    = config.path,
        matcherHandler = config.handler,
        matcherKey     = stubName || matcherPath

    this.pool[matcherKey] = {name: stubName, path: matcherPath, handler: matcherHandler}
  },

  hasMatch: function(stub) { // determines if a pattern applies to the provided stub (TODO - clearly optimize, madhax)
    var inPool      = _.isString(stub) && this.pool.hasOwnProperty(stub)
        matchExists = inPool || _.every(_.mapKeys(hazy.matcher.pool, function(v,pattern) {
          return _.isString(stub) && !_.isUndefined(
            jsonPath.query(pattern, stub)
          )
        }), true)

    return matchExists
  },
}
<|endoftext|>


<commit_before>'use strict'

// import material components
import {
  View,
  Component,
  Container,
  Checkbox,
  Button,
  Text
} from 'material'

import Layout from 'material/src/layout'
import css from 'material/src/module/css'

import iconStar from '../icon/star.svg'
import iconAccessibility from '../icon/accessibility.svg'
import iconPhone from '../icon/phone.svg'
import iconHappy from '../icon/happy.svg'
import iconLink from '../icon/link.svg'

/**
 * [initTest description]
 * @return {[type]} [description]
 */
export default function (body) {
  var layout = new Layout([View, 'button', {},
    [Container, 'hero', {},
      [Button, 'first', { text: 'Flat' }],
      [Button, 'second', { text: 'Raised', type: 'raised', color: 'primary' }],
      [Button, 'third', { icon: iconStar, type: 'action' }],
      [Button, 'fourth', { icon: iconStar, text: 'text' }],
      [Button, 'fifth', { icon: iconStar, type: 'floating', color: 'secondary' }]
    ],
    [Container, 'containerbutton', {},
      [Container, 'options', {},
        [Checkbox, 'darktheme', { label: 'Dark Theme' }]
      ],
      [View, 'button-default', {},
        [Text, 'standard-button', { text: 'Standard Button', type: 'subheading2' }],
        [View, 'buttons-container', {},
          [Button, 'default', { text: 'default' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense' }],
          [Button, 'default-link', { text: 'Link', tag: 'a' }]
        ],
        [View, 'buttons-container', {},
          [Button, 'default', { text: 'default', color: 'primary' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text', color: 'primary' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact', color: 'primary' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense', color: 'primary' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense', color: 'primary' }],
          [Button, 'default-link', { text: 'Link', color: 'primary', tag: 'a' }]
        ],
        [View, 'buttons-container', {},
          [Button, 'default', { text: 'default', color: 'secondary' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text', color: 'secondary' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact', color: 'secondary' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense', color: 'secondary' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense', color: 'secondary' }],
          [Button, 'default-link', { text: 'Link', color: 'secondary', tag: 'a' }]
        ],
        [Text, 'raised-button', { text: 'Raised Button', type: 'subheading2' }],
        [View, 'buttons-raised', {},
          [Button, 'raised', { text: 'raised', type: 'raised' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact' }],
          [Button, 'raised-dense', { text: 'Dense', type: 'raised', style: 'dense' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', type: 'raised', style: 'compact dense' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised' }],
          [Button, 'raised-link', { icon: iconStar, type: 'raised' }]
        ],
        [View, 'buttons-raised-primary', {},
          [Button, 'raised', { text: 'raised primary', type: 'raised', color: 'primary' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text', color: 'primary' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact', color: 'primary' }],
          [Button, 'raised-dense', { text: 'Dense', style: 'dense', type: 'raised', color: 'primary' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', style: 'dense compact', type: 'raised', color: 'primary' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised', color: 'primary' }],
          [Button, 'raised-link', { icon: iconStar, type: 'raised', color: 'primary' }]
        ],
        [View, 'buttons-raised-secondary', {},
          [Button, 'raised', { text: 'raised secondary', type: 'raised', color: 'secondary' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text', color: 'secondary' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact', color: 'secondary' }],
          [Button, 'raised-dense', { text: 'Dense', type: 'raised', style: 'dense', color: 'secondary' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', type: 'raised', style: 'compact dense', color: 'secondary' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised', color: 'secondary' }]
        ],
        [Text, 'action-button', { text: 'Action Button', type: 'subheading2' }],
        [View, 'buttons-action', {},
          [Button, 'action', { icon: iconStar, type: 'action' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense' }],
          [Button, 'action-link', { icon: iconLink, type: 'action' }]
        ],
        [View, 'buttons-action', {},
          [Button, 'action', { icon: iconStar, type: 'action', color: 'primary' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact', color: 'primary' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense', color: 'primary' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense', color: 'primary' }],
          [Button, 'action-link', { icon: iconLink, type: 'action', color: 'primary' }]
        ],
        [View, 'buttons-action-secondary', {},
          [Button, 'action', { icon: iconStar, type: 'action', color: 'secondary' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact', color: 'secondary' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense', color: 'secondary' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense', color: 'secondary' }],
          [Button, 'action-link', { icon: iconLink, type: 'action', color: 'secondary' }]
        ],
        [Text, 'floating-button', { text: 'Floating Button', type: 'subheading2' }],
        [View, 'buttons-floating', {},
          [Button, 'floating', { icon: iconStar, type: 'floating' }],
          [Button, 'floating-compact', { icon: iconHappy, type: 'floating', style: 'compact' }],
          [Button, 'floating-dense', { icon: iconPhone, type: 'floating', style: 'dense' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', tag: 'a' }]
        ],
        [View, 'buttons-floating', {},
          [Button, 'floating', { icon: iconStar, type: 'floating', color: 'primary' }],
          [Button, 'floating-compact', { icon: iconHappy, type: 'floating', style: 'compact', color: 'primary' }],
          [Button, 'floating-dense', { icon: iconPhone, type: 'floating', style: 'dense', color: 'primary' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense', color: 'primary' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', color: 'primary' }]
        ],
        [View, 'buttons-floating-secondary', {},
          [Button, 'floating', { icon: iconStar, text: 'floating secondary', type: 'floating', color: 'secondary' }],
          [Button, 'floating-compact', { icon: iconHappy, text: 'Compact', type: 'floating', style: 'compact', color: 'secondary' }],
          [Button, 'floating-dense', { icon: iconPhone, text: 'Dense', type: 'floating', style: 'dense', color: 'secondary' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense', color: 'secondary' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', color: 'secondary' }]
        ]
      ]
    ]
  ], body)

  var component = layout.get()

  layout.get('default').on('click', (e) => {
    console.log('click', e, layout.get('default'))
  })

  layout.get('darktheme').on('change', function (checked) {
    console.log('darktheme', checked, layout.get('containerbutton'))
    if (checked) {
      css.add(layout.get('containerbutton').wrapper, 'dark-theme')
    } else {
      css.remove(layout.get('containerbutton').wrapper, 'dark-theme')
    }
  })
}
<commit_msg>update button view<commit_after>'use strict'

// import material components
import {
  View,
  Component,
  Container,
  Checkbox,
  Button,
  Text
} from 'material'

import Layout from 'material/src/layout'
import css from 'material/src/module/css'

import iconStar from '../icon/star.svg'
import iconAccessibility from '../icon/accessibility.svg'
import iconPhone from '../icon/phone.svg'
import iconHappy from '../icon/happy.svg'
import iconLink from '../icon/link.svg'

/**
 * [initTest description]
 * @return {[type]} [description]
 */
export default function (body) {
  var layout = new Layout([View, 'button', {},
    [Container, 'hero', {},
      [Button, 'first', { text: 'Flat' }],
      [Button, 'second', { text: 'Raised', type: 'raised', color: 'primary' }],
      [Button, 'third', { icon: iconStar, type: 'action' }],
      [Button, 'fourth', { icon: iconStar, text: 'text' }],
      [Button, 'fifth', { icon: iconStar, type: 'floating', color: 'secondary' }]
    ],
    [Container, 'containerbutton', {},
      [Container, 'options', {},
        [Checkbox, 'darktheme', { label: 'Dark Theme' }]
      ],
      [Component, 'button-default', {},
        [Text, 'standard-button', { text: 'Standard Button', type: 'subheading2' }],
        [Component, 'buttons-container', {},
          [Button, 'default', { text: 'default' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense' }],
          [Button, 'default-link', { text: 'Link', tag: 'a' }]
        ],
        [Component, 'buttons-container', {},
          [Button, 'default', { text: 'default', color: 'primary' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text', color: 'primary' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact', color: 'primary' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense', color: 'primary' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense', color: 'primary' }],
          [Button, 'default-link', { text: 'Link', color: 'primary', tag: 'a' }]
        ],
        [Component, 'buttons-container', {},
          [Button, 'default', { text: 'default', color: 'secondary' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text', color: 'secondary' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact', color: 'secondary' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense', color: 'secondary' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense', color: 'secondary' }],
          [Button, 'default-link', { text: 'Link', color: 'secondary', tag: 'a' }]
        ],
        [Text, 'raised-button', { text: 'Raised Button', type: 'subheading2' }],
        [Component, 'buttons-raised', {},
          [Button, 'raised', { text: 'raised', type: 'raised' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact' }],
          [Button, 'raised-dense', { text: 'Dense', type: 'raised', style: 'dense' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', type: 'raised', style: 'compact dense' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised' }],
          [Button, 'raised-link', { icon: iconStar, type: 'raised' }]
        ],
        [Component, 'buttons-raised-primary', {},
          [Button, 'raised', { text: 'raised primary', type: 'raised', color: 'primary' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text', color: 'primary' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact', color: 'primary' }],
          [Button, 'raised-dense', { text: 'Dense', style: 'dense', type: 'raised', color: 'primary' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', style: 'dense compact', type: 'raised', color: 'primary' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised', color: 'primary' }],
          [Button, 'raised-link', { icon: iconStar, type: 'raised', color: 'primary' }]
        ],
        [Component, 'buttons-raised-secondary', {},
          [Button, 'raised', { text: 'raised secondary', type: 'raised', color: 'secondary' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text', color: 'secondary' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact', color: 'secondary' }],
          [Button, 'raised-dense', { text: 'Dense', type: 'raised', style: 'dense', color: 'secondary' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', type: 'raised', style: 'compact dense', color: 'secondary' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised', color: 'secondary' }]
        ],
        [Text, 'action-button', { text: 'Action Button', type: 'subheading2' }],
        [Component, 'buttons-action', {},
          [Button, 'action', { icon: iconStar, type: 'action' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense' }],
          [Button, 'action-link', { icon: iconLink, type: 'action' }]
        ],
        [Component, 'buttons-action', {},
          [Button, 'action', { icon: iconStar, type: 'action', color: 'primary' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact', color: 'primary' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense', color: 'primary' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense', color: 'primary' }],
          [Button, 'action-link', { icon: iconLink, type: 'action', color: 'primary' }]
        ],
        [Component, 'buttons-action-secondary', {},
          [Button, 'action', { icon: iconStar, type: 'action', color: 'secondary' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact', color: 'secondary' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense', color: 'secondary' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense', color: 'secondary' }],
          [Button, 'action-link', { icon: iconLink, type: 'action', color: 'secondary' }]
        ],
        [Text, 'floating-button', { text: 'Floating Button', type: 'subheading2' }],
        [Component, 'buttons-floating', {},
          [Button, 'floating', { icon: iconStar, type: 'floating' }],
          [Button, 'floating-compact', { icon: iconHappy, type: 'floating', style: 'compact' }],
          [Button, 'floating-dense', { icon: iconPhone, type: 'floating', style: 'dense' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', tag: 'a' }]
        ],
        [Component, 'buttons-floating', {},
          [Button, 'floating', { icon: iconStar, type: 'floating', color: 'primary' }],
          [Button, 'floating-compact', { icon: iconHappy, type: 'floating', style: 'compact', color: 'primary' }],
          [Button, 'floating-dense', { icon: iconPhone, type: 'floating', style: 'dense', color: 'primary' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense', color: 'primary' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', color: 'primary' }]
        ],
        [Component, 'buttons-floating-secondary', {},
          [Button, 'floating', { icon: iconStar, text: 'floating secondary', type: 'floating', color: 'secondary' }],
          [Button, 'floating-compact', { icon: iconHappy, text: 'Compact', type: 'floating', style: 'compact', color: 'secondary' }],
          [Button, 'floating-dense', { icon: iconPhone, text: 'Dense', type: 'floating', style: 'dense', color: 'secondary' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense', color: 'secondary' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', color: 'secondary' }]
        ]
      ]
    ]
  ], body)

  var component = layout.get()

  layout.get('default').on('click', (e) => {
    console.log('click', e, layout.get('default'))
  })

  layout.get('darktheme').on('change', function (checked) {
    console.log('darktheme', checked, layout.get('containerbutton'))
    if (checked) {
      css.add(layout.get('containerbutton').wrapper, 'dark-theme')
    } else {
      css.remove(layout.get('containerbutton').wrapper, 'dark-theme')
    }
  })
}
<|endoftext|>


<commit_before>/*global console: false*/

/**
 * @name JsSIP
 * @namespace
 */
(function(window) {
var JsSIP = (function() {
  "use strict";
  var
    productName = 'JsSIP',
    productVersion = 'devel';

  return {
    name: function() {
      return productName;
    },
    version: function() {
      return productVersion;
    }
  };
}());
<commit_msg>Add Copyright line to code header<commit_after>/*
 * JsSIP
 * Copyright (c) 2012-2013 José Luis Millán - Versatica <http://www.versatica.com>
 * MIT License
 */

/*global console: false*/

/**
 * @name JsSIP
 * @namespace
 */
(function(window) {
var JsSIP = (function() {
  "use strict";
  var
    productName = 'JsSIP',
    productVersion = 'devel';

  return {
    name: function() {
      return productName;
    },
    version: function() {
      return productVersion;
    }
  };
}());
<|endoftext|>


<commit_before>import chalk from "chalk";
import { supportedOutputFormats } from "./argValidator";

export default { show };

const highlight = chalk.cyan;

const ASCII_ART_HEADER =
`   ____  _
  / ___|| |_ _   ___  __
  \\___ \\| __| | | \\ \\/ /
   ___) | |_| |_| |>  <
  |____/ \\__|\\__, /_/\\_\\
             |___/
`;

const usage = `  styx [-o ${highlight("<file>")}] [-f ${highlight("<format>")}]
       [--minified-json] [--help]`;

const formattedOutputFormats = supportedOutputFormats.map(format => highlight(format)).join(" or ");

const argExplanations = `
    -o, --output ${highlight("<file>")}      Path to the output file
    -f, --format ${highlight("<format>")}    The desired output format: ${formattedOutputFormats}

    --minified-json          Minifies the serialized JSON string

    --help                   Displays this help text`;

function show() {
    console.log(highlight(ASCII_ART_HEADER));
    console.log(usage);
    console.log(argExplanations);
}
<commit_msg>Documents the `-g` option<commit_after>import chalk from "chalk";
import { supportedOutputFormats } from "./argValidator";

export default { show };

const highlight = chalk.cyan;

const ASCII_ART_HEADER =
`   ____  _
  / ___|| |_ _   ___  __
  \\___ \\| __| | | \\ \\/ /
   ___) | |_| |_| |>  <
  |____/ \\__|\\__, /_/\\_\\
             |___/
`;

const usage = `  styx [-o ${highlight("<file>")}] [-f ${highlight("<format>")}] [-g ${highlight("<graph id>")}]
       [--minified-json] [--help]`;

const formattedOutputFormats = supportedOutputFormats
    .map(format => highlight(format))
    .join(" or ");

const argExplanations = `
    -o, --output ${highlight("<file>")}       Path to the output file
    -f, --format ${highlight("<format>")}     Desired output format: ${formattedOutputFormats}
    -g, --graph ${highlight("<graph id>")}    ID of the control flow graph to export

    --minified-json           Minifies the serialized JSON string

    --help                    Displays this help text`;

function show() {
    console.log(highlight(ASCII_ART_HEADER));
    console.log(usage);
    console.log(argExplanations);
}
<|endoftext|>


<commit_before>/*
---

script: Update.js

description: Update widget with html or json

license: Public domain (http://unlicense.org).

authors: Yaroslaff Fedin

requires:
  - LSD.Action

provides:
  - LSD.Action.Update
  - LSD.Action.Append
  - LSD.Action.Replace
  - LSD.Action.Before
  - LSD.Action.After

...
*/

LSD.Action.Update = LSD.Action.build({
  container: true,

  enable: function(target, content) {
    if (!content) return LSD.warn('Update action did not recieve content');
    if (content.charAt) {
      var fragment = document.createFragment(content);
      var children = LSD.slice(fragment.childNodes);
    } else {
      var fragment = document.createFragment('');
      if (!content.hasOwnProperty('length')) {
        var children = [content];
        fragment.appendChild(content);
      } else for (var i = 0, child; child = children[i++];) fragment.appendChild(child);
    }
    var widget = LSD.Module.DOM.find(target);
    if (widget.element == target) {
      parent = widget.parentNode;
      var element = target;
      target = parent;
    } else {
      var element = target, parent = widget;
      widget = null;
    }
    this.options.update.apply(this, [element, widget, parent, fragment, children]);
  },

  update: function(element, widget, parent, fragment, children) {
    (widget || parent).removeLayout(null, element.childNodes, element);
    element.appendChild(fragment);
    (widget || parent).addLayout(null, children, element);
  }
});

LSD.Action.Append = LSD.Action.build({
  enable: LSD.Action.Update.prototype.options.enable,

  update: function(element, widget, parent, fragment, children) {
    element.appendChild(fragment);
    (widget || parent).addLayout(null, children, element)
  }
});

LSD.Action.Replace = LSD.Action.build({
  enable: LSD.Action.Update.prototype.options.enable,

  update: function(element, widget, parent, fragment) {
    var parentNode = element.parentNode
    parentNode.replaceChild(fragment, element, children);
    parent.removeLayout(null, widget || element);
    parent.addLayout(null, children, parentNode);
  }
});

LSD.Action.Before = LSD.Action.build({
  enable: LSD.Action.Update.prototype.options.enable,

  update: function(element, widget, parent, fragment, children) {
    target.parentNode.insertBefore(fragment, element);
    parent.addLayout(null, children, element.parentNode, {before: element});
  }
});

LSD.Action.After = LSD.Action.build({
  enable: LSD.Action.Update.prototype.options.enable,

  update: function(element, widget, parent, fragment, children) {
    element.parentNode.insertBefore(fragment, element.nextSibling);
    parent.addLayout(null, children, element.parentNode, {before: element.nextSibling});
  }
});<commit_msg>Make Update treat widgets just as elements, fix two typos<commit_after>/*
---

script: Update.js

description: Update widget with html or json

license: Public domain (http://unlicense.org).

authors: Yaroslaff Fedin

requires:
  - LSD.Action

provides:
  - LSD.Action.Update
  - LSD.Action.Append
  - LSD.Action.Replace
  - LSD.Action.Before
  - LSD.Action.After

...
*/

LSD.Action.Update = LSD.Action.build({
  enable: function(target, content) {
    if (!content) return LSD.warn('Update action did not recieve content');
    if (content.charAt) {
      var fragment = document.createFragment(content);
      var children = LSD.slice(fragment.childNodes);
    } else {
      var fragment = document.createFragment('');
      if (!content.hasOwnProperty('length')) {
        var children = [content];
        fragment.appendChild(content);
      } else for (var i = 0, child; child = children[i++];) fragment.appendChild(child);
    }
    if (target.lsd) {
      var widget = target;
      var element = widget.toElement();
      var parent = target.parentNode;
    } else {
      var widget = LSD.Module.DOM.find(target);
      if (widget.element == target) {
        parent = widget.parentNode;
        var element = target;
      } else {
        var element = target, parent = widget;
        widget = null;
      }
    }
    this.options.update.apply(this, [element, widget, parent, fragment, children]);
  },

  update: function(element, widget, parent, fragment, children) {
    (widget || parent).removeLayout(null, element.childNodes, element);
    element.appendChild(fragment);
    (widget || parent).addLayout(null, children, element);
  }
});

LSD.Action.Append = LSD.Action.build({
  enable: LSD.Action.Update.prototype.options.enable,

  update: function(element, widget, parent, fragment, children) {
    element.appendChild(fragment);
    (widget || parent).addLayout(null, children, element)
  }
});

LSD.Action.Replace = LSD.Action.build({
  enable: LSD.Action.Update.prototype.options.enable,

  update: function(element, widget, parent, fragment, children) {
    var parentNode = element.parentNode
    parentNode.replaceChild(fragment, element);
    parent.removeLayout(null, widget || element);
    parent.addLayout(null, children, parentNode);
  }
});

LSD.Action.Before = LSD.Action.build({
  enable: LSD.Action.Update.prototype.options.enable,

  update: function(element, widget, parent, fragment, children) {
    element.parentNode.insertBefore(fragment, element);
    parent.addLayout(null, children, element.parentNode, {before: element});
  }
});

LSD.Action.After = LSD.Action.build({
  enable: LSD.Action.Update.prototype.options.enable,

  update: function(element, widget, parent, fragment, children) {
    element.parentNode.insertBefore(fragment, element.nextSibling);
    parent.addLayout(null, children, element.parentNode, {before: element.nextSibling});
  }
});<|endoftext|>


<commit_before>test(function (test) {

  var instance;

  test.beforeEach(function () {
    instance = null;
  });

  test.integration('/', function () {

    test.itShould.loadPage();
  });
});<commit_msg>some silly integration tests<commit_after>test(function (test) {

  var instance;

  test.beforeEach(function () {
    instance = null;
  });

  test.integration('/', function () {

    test.itShould.loadPage();

    test.it('should have the correct title', function () {

      expect(this.browser.text('H1')).to.contain('asimov.js');
    });

    test.it('should contain a link to asimovjs.org', function () {

      expect(this.browser.html('a')).to.contain('href="http://asimovjs.org"');
    });
  });
});<|endoftext|>


<commit_before>/**
 *@author Ludvig Boström <c13lbm>
 *@revision: Fredrik Mörtberg <c13fmg>
 */

/**
 * Props params:
 *
 * playCallback:    Function to be called with response from server. should take one parameter.
 * calc:            Only used when testing hardware.
 * postURL:         The url after the globally set url.
 * formDataBuilder  Function to create formdata containing information to send. Function takes:.
 *                                                                                video(blob) as first param
 *                                                                                filename as second param.
 * recButtonID:     [Optional] Button to start recording video. If left out it autorecords on render.
 * stopButtonID:    Id of the button to stop recording video. Might post video as well(read about postButtonID).
 * postButtonID:    [Optional] Id of the post video button. If left out the stop button posts the video to server.
 * replay:          replay="true" if you want the recording to be playable in the same video tag.
 * fileName:        The name the video recording should have.
 * camOnLoad:       camOnLoad="true" If the camera is to start before recording. User will have to click
 *                  stopbutton to be able to reuse camera.
 * autoRecord:      autoRecord="true" if the camera should start recording when class is instantiated.
 *
 *
 * watch HardwareTest.js for example of use.
 */

var mediaStream = null;
var minrecordTimer;
var maxrecordTimer;

function closeStream() {
    if(mediaStream != null && typeof mediaStream !== "undefined"){
        mediaStream.stop();
        mediaStream = null;
    }
}

var Recorder = React.createClass({
    defaultMinTime: 10,
    defaultMaxTime: 120,

    componentDidMount: function() {
        var props = this.props;

        //used for hw testing
        var blobsize;
        var sendTime;
        var forceSubmit = false;
        var cameraStartOnLoad = (typeof props.camOnLoad === "undefined") ?
                        false : props.camOnLoad == "true";
        var cameraStarted = false;
        var startRecordButtonExists = (typeof props.recButtonID !== "undefined");
        var shouldAutoRecord = (typeof props.autoRecord === "undefined") ?
                        !startRecordButtonExists : props.autoRecord == "true";

        var replay = props.replay == "true";
        var previewElement;
        var recordAudio, recordVideo;

        var minRecordTime = parseInt(props.minRecordTime);
        if(isNaN(minRecordTime)) {
            minRecordTime = this.defaultMinTime;
        }
        var maxRecordTime = parseInt(props.maxRecordTime);
        if(isNaN(maxRecordTime)) {
            maxRecordTime = this.defaultMaxTime;
        }

        if(startRecordButtonExists) {
            var recordButton = document.getElementById(props.recButtonID);
            if(cameraStartOnLoad)
                recordButton.disabled = true;
        }

        if(typeof props.calc !== "undefined")
            previewElement = document.getElementById('prev-test');
        else
            previewElement = document.getElementById('preview');

        navigator.getUserMedia = ( navigator.getUserMedia ||
                                  navigator.webkitGetUserMedia ||
        navigator.mediaDevices.getUserMedia ||
                                  navigator.msGetUserMedia);

        if(cameraStartOnLoad) {
            startCamera();
        }

        /* The onclick function for the start record button if it exists. */
        if(startRecordButtonExists) {
            recordButton.onclick = startRecord;
        }

        /* Will start recording and start the webcam if not enabled. */
        function startRecord() {
            if(!cameraStarted) {
                startCamera();
                window.setTimeout(function() {
                    recordAudio.startRecording();
                    recordingStarted();
                }, 1000);
            } else {
                recordAudio.startRecording();
                recordingStarted();
            }
        }

        function recordingStarted() {
            if(startRecordButtonExists) {
                recordButton.disabled = true;
            }
            if(props.siteView == "submission") {
                if(props.minRecordTime != null) {
                    minrecordTimer = setTimeout(function() {
                                    props.setSubmitEnabled(true);
                                    document.getElementById(props.stopButtonID).onclick = stopRecording;
                                }, 1000*minRecordTime);
                }
                if(props.maxRecordTime != null) {
                    maxrecordTimer = setTimeout(function() {
                                    forceSubmit = true;
                                    if(document.getElementById(props.stopButtonID) != null) {
                                        document.getElementById(props.stopButtonID).onclick();
                                    }
                                }, 1000*maxRecordTime);
                }
            } else {
                document.getElementById(props.stopButtonID).onclick = stopRecording;
                document.getElementById(props.stopButtonID).disabled = false;
            }

            if(typeof props.calc !== "undefined") {
                /*document.getElementById("test-rec-text").innerHTML = "🔴";*/
                document.getElementById("test-rec-text").innerHTML = "";
            }
            else {
                /*document.getElementById("rec-text").innerHTML = "🔴";*/
                document.getElementById("rec-text").innerHTML = "";
            }
        }

        /* Start stream from webcam and start recording if autoRecording is true,
         * will record with forced low settings for smaller files. */
        function startCamera () {
            navigator.getUserMedia({
                audio: true,
                video: {
                    mandatory: {
                        minWidth: 160,
                        maxWidth: 320,
                        minHeight: 120,
                        maxHeight: 240,
                        minFrameRate: 5,
                        maxFrameRate: 10
                    }
                }
            }, function (stream) {
                closeStream();
                mediaStream = stream;
                previewElement.src = window.URL.createObjectURL(mediaStream);
                previewElement.removeAttribute("controls");
                previewElement.setAttribute("muted", "muted");
                window.setTimeout(function() {
                    if(previewElement != null)
                        previewElement.play();
                }, 400);

                recordAudio = RecordRTC(mediaStream, {
                    onAudioProcessStarted: function () {
                        recordVideo.startRecording();
                    }
                });

                recordVideo = RecordRTC(mediaStream, {
                    type: 'video'
                });

                if(startRecordButtonExists && cameraStartOnLoad) {
                    recordButton.disabled = false;
                }

                if(shouldAutoRecord) {
                    startRecord();
                }
                cameraStarted = true;
            }, function (error) {
                alert("Problem occured, make sure camera is not\nused elsewhere and that you are connected\nby https.");
            });
        }

        /* Closes the webcam stream and post to server if auto recording is on. */
        function stopRecording() {
            if(props.siteView == "submission") {
                //props.setSubmitEnabled(false);
                if(forceSubmit == false) {
                    /* TODO We want confirm on submit but it blocks the timer so no confirm for now until a solution is found. */
                    /*if(!confirm("Are you sure you want to submit your answer?")) {
                        return;
                    }*/
                }
            }

            if(!shouldAutoRecord){
                recordButton.disabled = false;
            }
            document.getElementById(props.stopButtonID).disabled = true;

            previewElement.src = '';

            var postbutton = null;
            if (typeof props.postButtonID !== "undefined") {
                postbutton = document.getElementById(props.postButtonID);
            }

            recordVideo.stopRecording(function (url) {
                if(replay) {
                    previewElement.src = url;
                    previewElement.setAttribute("controls","controls");
                    previewElement.removeAttribute("muted");
                }
                /*if(props.siteView == "feedback") {
                    props.setVideo(recordVideo.getBlob());
                }*/

                if(postbutton == null) {
                    if(props.siteView !== null) {
                        PostBlob(recordVideo.getBlob(), props.siteView);
                    } else {
                        PostBlob(recordVideo.getBlob());
                    }
                }
                else {
                    previewElement.src = url;
                    previewElement.setAttribute("controls","controls");
                    previewElement.removeAttribute("muted");
                    postbutton.disabled = false;
                    postbutton.onclick = function () {
                        if(props.siteView !== null) {
                            PostBlob(recordVideo.getBlob(), props.siteView);
                        } else {
                            PostBlob(recordVideo.getBlob());
                        }
                    }
                }

                closeStream();

                if(typeof props.calc !== "undefined") {
                    /*document.getElementById("test-rec-text").innerHTML = "⭕";*/
                    if(document.getElementById("test-rec-text") != null) {
                        document.getElementById("test-rec-text").innerHTML = "";
                    }
                }
                else {
                    /*document.getElementById("rec-text").innerHTML = "⭕";*/
                    if(document.getElementById("rec-text")) {
                        document.getElementById("rec-text").innerHTML = "";
                    }
                }
                cameraStarted = false;
            });

            if(props.siteView == "submission") {
                props.endFunc();
            }
        }

        /* Post to the server */
        function PostBlob(blob, siteView) {
            // FormData - data to be sent to the server
            var formData = props.formDataBuilder(blob,props.fileName);

            //used for hw testing
            if(typeof props.calc !== "undefined") {
              blobsize = blob.size / 1048576;
              sendTime = Date.now();
            }

            //If a httpCallback exists use that for sending the data.
            if(typeof props.httpCallback !== "undefined") {
                props.httpCallback(formData);
                console.log("callback");
            } else {
                //call xhr with full url, data and callback function
                xhr(props.postURL, formData, props.playCallback);
                console.log("defualt");
            }
        }

        /* Function for sending XMLHttpRequests. */
        function xhr(url, data, callback) {
            var request = new XMLHttpRequest();
            request.onreadystatechange = function () {
                if (request.readyState == 4 && request.status == 200) {
                    callback(request.responseText);
                    alert("Your video has been uploaded successfully!");
                    if(props.siteView == "submission") {
                        location.reload(); // Maby not best solution.
                    }
                } else if(request.readyState == 4 && request.status != 200) {
                    if(request.responseText.length < 10) {
                        // Error message should be longer than 10 characters
                        alert("Failed to upload video.");

                    } else if(request.responseText.includes("Exception")) {
                        // Do not print out exception (should not occur....)
                        alert("Failed to upload video.");
                    } else {
                        alert(request.responseText);
                    }
                }
            };

            if(typeof props.calc !== "undefined") {
                request.upload.onloadstart = function () {
                    $("#internet-speed").text("Uploading...");
                }
                request.onloadstart = function () {
                    $("#internet-speed").text("Uploading...");
                }
            }
            request.onload = function(){
                if(typeof props.calc !== "undefined") {
                    if(request.status == 404)
                        $("#internet-speed").text("Upload failed, no server connection.");
                    else if(request.status == 408)
                        $("#internet-speed").text("Connection timed out.");
                    else
                        props.calc(blobsize,sendTime);
                }
                else if(request.status == 404) {
                    alert("Upload failed, no server connection.");
                }
                else if(request.status == 408) {
                    alert("Connection timed out.");
                }
            }

            request.open("POST", url,true);
            console.log(recordVideo.getBlob());
            request.send(data);
        }

        /* Showing recording-light on load (not recording) */

        if(typeof props.calc !== "undefined") {
            /*document.getElementById("test-rec-text").innerHTML = "⭕";*/
            if(document.getElementById("test-rec-text") != null) {
                document.getElementById("test-rec-text").innerHTML = "";
            }
        }
        else {
            /*document.getElementById("rec-text").innerHTML = "⭕";*/
            if(document.getElementById("rec-text") != null) {
                document.getElementById("rec-text").innerHTML = "";
            }
        }
    },
    componentWillUnmount: function () {
        closeStream();
        if(typeof this.props.calc !== "undefined" && typeof $("#you-id")[0] !== "undefined") {
            $("#you-id")[0].pause();
        }
        clearTimeout(minrecordTimer);
        clearTimeout(maxrecordTimer);
    },
    render: function() {
        var id;
        var pId;
        var contId;

        if(typeof this.props.contID === "undefined"){
            contId = "prev-container";
        }
        else {
            contId = this.props.contID;
        }
        if(typeof this.props.calc !== "undefined") {
            id="prev-test";
            pId="test-rec-text";

        }
        else {
            id="preview";
            pId="rec-text";

        }

        return (

                    <video id={id} muted ></video>

        );
    }
});

window.Recorder = Recorder;
<commit_msg>Moved functions out of the Recorder component so that they may be more accessible.<commit_after>/**
 *@author Ludvig Boström <c13lbm>
 *@revision: Fredrik Mörtberg <c13fmg>
 */

/**
 * Props params:
 *
 * playCallback:    Function to be called with response from server. should take one parameter.
 * calc:            Only used when testing hardware.
 * postURL:         The url after the globally set url.
 * formDataBuilder  Function to create formdata containing information to send. Function takes:.
 *                                                                                video(blob) as first param
 *                                                                                filename as second param.
 * recButtonID:     [Optional] Button to start recording video. If left out it autorecords on render.
 * stopButtonID:    Id of the button to stop recording video. Might post video as well(read about postButtonID).
 * postButtonID:    [Optional] Id of the post video button. If left out the stop button posts the video to server.
 * replay:          replay="true" if you want the recording to be playable in the same video tag.
 * fileName:        The name the video recording should have.
 * camOnLoad:       camOnLoad="true" If the camera is to start before recording. User will have to click
 *                  stopbutton to be able to reuse camera.
 * autoRecord:      autoRecord="true" if the camera should start recording when class is instantiated.
 *
 *
 * watch HardwareTest.js for example of use.
 */

var mediaStream = null;
var minrecordTimer;
var maxrecordTimer;
var props = null;

//used for hw testing
var blobsize = 0;
var sendTime = 0;
var forceSubmit = false;
var cameraStartOnLoad = false;
var cameraStarted = false;
var startRecordButtonExists = false;
var shouldAutoRecord = false;
var replay = false;
var previewElement = null;
var recordAudio = null;
var recordVideo = null;
var defaultMinTime = 10;
var defaultMaxTime = 120;
var minRecordTime = defaultMinTime;
var maxRecordTime = defaultMaxTime;
var recordButton = null;

function closeStream() {
    if(mediaStream != null && typeof mediaStream !== "undefined"){
        mediaStream.stop();
        mediaStream = null;
    }
}

/* Will start recording and start the webcam if not enabled. */
function startRecord() {
    if(!cameraStarted) {
        startCamera();
        window.setTimeout(function() {
            recordAudio.startRecording();
            recordingStarted();
        }, 1000);
    } else {
        recordAudio.startRecording();
        recordingStarted();
    }
}

function recordingStarted() {
    if(startRecordButtonExists) {
        recordButton.disabled = true;
    }
    if(props.siteView == "submission") {
        minrecordTimer = setTimeout(function() {
                        props.setSubmitEnabled(true);
                        document.getElementById(props.stopButtonID).onclick = stopRecording;
                    }, 1000*minRecordTime);

        maxrecordTimer = setTimeout(function() {
                        forceSubmit = true;
                        if(document.getElementById(props.stopButtonID) != null) {
                            document.getElementById(props.stopButtonID).onclick();
                        }
                    }, 1000*maxRecordTime);
    } else {
        document.getElementById(props.stopButtonID).onclick = stopRecording;
        document.getElementById(props.stopButtonID).disabled = false;
    }

    if(typeof props.calc !== "undefined") {
        /*document.getElementById("test-rec-text").innerHTML = "🔴";*/
        document.getElementById("test-rec-text").innerHTML = "";
    }
    else {
        /*document.getElementById("rec-text").innerHTML = "🔴";*/
        document.getElementById("rec-text").innerHTML = "";
    }
}

/* Start stream from webcam and start recording if autoRecording is true,
 * will record with forced low settings for smaller files. */
function startCamera () {
    navigator.getUserMedia({
        audio: true,
        video: {
            mandatory: {
                minWidth: 160,
                maxWidth: 320,
                minHeight: 120,
                maxHeight: 240,
                minFrameRate: 5,
                maxFrameRate: 10
            }
        }
    }, function (stream) {
        closeStream();
        mediaStream = stream;
        previewElement.src = window.URL.createObjectURL(mediaStream);
        previewElement.removeAttribute("controls");
        previewElement.setAttribute("muted", "muted");
        window.setTimeout(function() {
            if(previewElement != null)
                previewElement.play();
        }, 400);

        recordAudio = RecordRTC(mediaStream, {
            onAudioProcessStarted: function () {
                recordVideo.startRecording();
            }
        });

        recordVideo = RecordRTC(mediaStream, {
            type: 'video'
        });

        if(startRecordButtonExists && cameraStartOnLoad) {
            recordButton.disabled = false;
        }

        if(shouldAutoRecord) {
            startRecord();
        }
        cameraStarted = true;
    }, function (error) {
        alert("Problem occured, make sure camera is not\nused elsewhere and that you are connected\nby https.");
    });
}

/* Closes the webcam stream and post to server if auto recording is on. */
function stopRecording() {
    if(props.siteView == "submission") {
        //props.setSubmitEnabled(false);
        if(forceSubmit == false) {
            /* TODO We want confirm on submit but it blocks the timer so no confirm for now until a solution is found. */
            /*if(!confirm("Are you sure you want to submit your answer?")) {
                return;
            }*/
        }
    }

    if(!shouldAutoRecord && recordButton != null) {
        recordButton.disabled = false;
    }
    document.getElementById(props.stopButtonID).disabled = true;

    previewElement.src = '';

    var postbutton = null;
    if (typeof props.postButtonID !== "undefined") {
        postbutton = document.getElementById(props.postButtonID);
    }

    recordVideo.stopRecording(function (url) {
        if(replay) {
            previewElement.src = url;
            previewElement.setAttribute("controls","controls");
            previewElement.removeAttribute("muted");
        }
        /*if(props.siteView == "feedback") {
            props.setVideo(recordVideo.getBlob());
        }*/

        if(postbutton == null) {
            if(props.siteView !== null) {
                PostBlob(recordVideo.getBlob(), props.siteView);
            } else {
                PostBlob(recordVideo.getBlob());
            }
        }
        else {
            previewElement.src = url;
            previewElement.setAttribute("controls","controls");
            previewElement.removeAttribute("muted");
            postbutton.disabled = false;
            postbutton.onclick = function () {
                if(props.siteView !== null) {
                    PostBlob(recordVideo.getBlob(), props.siteView);
                } else {
                    PostBlob(recordVideo.getBlob());
                }
            }
        }

        closeStream();

        if(typeof props.calc !== "undefined") {
            /*document.getElementById("test-rec-text").innerHTML = "⭕";*/
            if(document.getElementById("test-rec-text") != null) {
                document.getElementById("test-rec-text").innerHTML = "";
            }
        }
        else {
            /*document.getElementById("rec-text").innerHTML = "⭕";*/
            if(document.getElementById("rec-text")) {
                document.getElementById("rec-text").innerHTML = "";
            }
        }
        cameraStarted = false;
    });

    if(props.siteView == "submission") {
        props.endFunc();
    }
}

/* Post to the server */
function PostBlob(blob, siteView) {
    // FormData - data to be sent to the server
    var formData = props.formDataBuilder(blob,props.fileName);

    //used for hw testing
    if(typeof props.calc !== "undefined") {
      blobsize = blob.size / 1048576;
      sendTime = Date.now();
    }

    //If a httpCallback exists use that for sending the data.
    if(typeof props.httpCallback !== "undefined") {
        props.httpCallback(formData);
    } else {
        //call xhr with full url, data and callback function
        xhr(props.postURL, formData, props.playCallback);
    }
}

/* Function for sending XMLHttpRequests. */
function xhr(url, data, callback) {
    var request = new XMLHttpRequest();
    request.onreadystatechange = function () {
        if (request.readyState == 4 && request.status == 200) {
            callback(request.responseText);
            alert("Your video has been uploaded successfully!");
            if(props.siteView == "submission") {
                location.reload(); // Maby not best solution.
            }
        } else if(request.readyState == 4 && request.status != 200) {
            if(request.responseText.length < 10) {
                // Error message should be longer than 10 characters
                alert("Failed to upload video.");

            } else if(request.responseText.includes("Exception")) {
                // Do not print out exception (should not occur....)
                alert("Failed to upload video.");
            } else {
                alert(request.responseText);
            }
        }
    };

    if(typeof props.calc !== "undefined") {
        request.upload.onloadstart = function () {
            $("#internet-speed").text("Uploading...");
        }
        request.onloadstart = function () {
            $("#internet-speed").text("Uploading...");
        }
    }
    request.onload = function(){
        if(typeof props.calc !== "undefined") {
            if(request.status == 404)
                $("#internet-speed").text("Upload failed, no server connection.");
            else if(request.status == 408)
                $("#internet-speed").text("Connection timed out.");
            else
                props.calc(blobsize,sendTime);
        }
        else if(request.status == 404) {
            alert("Upload failed, no server connection.");
        }
        else if(request.status == 408) {
            alert("Connection timed out.");
        }
    }

    request.open("POST", url,true);
    request.send(data);
}

var Recorder = React.createClass({
    componentDidMount: function() {
        props = this.props;

        forceSubmit = false;
        cameraStartOnLoad = (typeof props.camOnLoad === "undefined") ?
                        false : props.camOnLoad == "true";
        cameraStarted = false;
        startRecordButtonExists = (typeof props.recButtonID !== "undefined");
        shouldAutoRecord = (typeof props.autoRecord === "undefined") ?
                        !startRecordButtonExists : props.autoRecord == "true";

        replay = props.replay == "true";

        minRecordTime = parseInt(props.minRecordTime);
        if(isNaN(minRecordTime)) {
            minRecordTime = defaultMinTime;
        }
        maxRecordTime = parseInt(props.maxRecordTime);
        if(isNaN(maxRecordTime)) {
            maxRecordTime = defaultMaxTime;
        }

        if(startRecordButtonExists) {
            recordButton = document.getElementById(props.recButtonID);
            if(cameraStartOnLoad)
                recordButton.disabled = true;
        }

        if(typeof props.calc !== "undefined")
            previewElement = document.getElementById('prev-test');
        else
            previewElement = document.getElementById('preview');

        navigator.getUserMedia = ( navigator.getUserMedia ||
                                  navigator.webkitGetUserMedia ||
        navigator.mediaDevices.getUserMedia ||
                                  navigator.msGetUserMedia);

        if(cameraStartOnLoad) {
            startCamera();
        }

        /* The onclick function for the start record button if it exists. */
        if(startRecordButtonExists) {
            recordButton.onclick = startRecord;
        }

        /* Showing recording-light on load (not recording) */

        if(typeof props.calc !== "undefined") {
            /*document.getElementById("test-rec-text").innerHTML = "⭕";*/
            if(document.getElementById("test-rec-text") != null) {
                document.getElementById("test-rec-text").innerHTML = "";
            }
        }
        else {
            /*document.getElementById("rec-text").innerHTML = "⭕";*/
            if(document.getElementById("rec-text") != null) {
                document.getElementById("rec-text").innerHTML = "";
            }
        }
    },
    shouldComponentUpdate: function(nextProps, nextState) {
        if(nextProps.autoRecord == "true" && this.props.autoRecord == "false") {
            startRecord();
            return true;
        }
        return false;
    },
    componentWillUnmount: function () {
        closeStream();
        if(typeof this.props.calc !== "undefined" && typeof $("#you-id")[0] !== "undefined") {
            $("#you-id")[0].pause();
        }
        clearTimeout(minrecordTimer);
        clearTimeout(maxrecordTimer);
    },
    render: function() {
        var id;
        var pId;
        var contId;

        if(typeof this.props.contID === "undefined"){
            contId = "prev-container";
        }
        else {
            contId = this.props.contID;
        }
        if(typeof this.props.calc !== "undefined") {
            id="prev-test";
            pId="test-rec-text";

        }
        else {
            id="preview";
            pId="rec-text";

        }

        return (

                    <video id={id} muted ></video>

        );
    }
});

window.Recorder = Recorder;
<|endoftext|>


<commit_before>'use strict';

var invert = require('lodash/object/invert');

var keys2Short = {
  index: 'idx',
  query: 'q',
  facets: 'f',
  disjunctiveFacets: 'dF',
  hierarchicalFacets: 'hF',
  facetsRefinements: 'fR',
  facetsExcludes: 'fE',
  disjunctiveFacetsRefinements: 'dFR',
  numericRefinements: 'nR',
  tagRefinements: 'tR',
  hierarchicalFacetsRefinements: 'hFR',
  numericFilters: 'nF',
  tagFilters: 'tF',
  hitsPerPage: 'hPP',
  maxValuesPerFacet: 'mVPF',
  page: 'p',
  queryType: 'qT',
  typoTolerance: 'tT',
  minWordSizefor1Typo: 'mWS1T',
  minWordSizefor2Typos: 'mWS2T',
  allowTyposOnNumericTokens: 'aTONT',
  ignorePlurals: 'iP',
  restrictSearchableAttributes: 'rSA',
  advancedSyntax: 'aS',
  analytics: 'a',
  analyticsTags: 'aT',
  synonyms: 's',
  replaceSynonymsInHighlight: 'rSIH',
  optionalWords: 'oW',
  removeWordsIfNoResults: 'rWINR',
  attributesToRetrieve: 'aTR',
  attributesToHighlight: 'aTH',
  highlightPreTag: 'hPrT',
  highlightPostTag: 'hPoT',
  attributesToSnippet: 'aTS',
  getRankingInfo: 'gRI',
  distinct: 'd',
  aroundLatLng: 'aLL',
  aroundLatLngViaIP: 'aLLVIP',
  aroundRadius: 'aR',
  aroundPrecision: 'aP',
  insideBoundingBox: 'iBB',
  offset: 'o',
  length: 'l'
};

var short2Keys = invert(keys2Short);

module.exports = {
  /**
   * Decode a shorten attribute
   * @param {string} shortKey the shorten attribute
   * @return {string} the decoded attribute, undefined otherwise
   */
  decode: function(shortKey) {
    return short2Keys[shortKey];
  },
  /**
   * Encode an attribute into a short version
   * @param {string} key the attribute
   * @return {string} the shorten attribute
   */
  encode: function(key) {
    return keys2Short[key];
  }
};
<commit_msg>chore(shortener): Sort key names alphabetically<commit_after>'use strict';

var invert = require('lodash/object/invert');

var keys2Short = {
  advancedSyntax: 'aS',
  allowTyposOnNumericTokens: 'aTONT',
  analyticsTags: 'aT',
  analytics: 'a',
  aroundLatLngViaIP: 'aLLVIP',
  aroundLatLng: 'aLL',
  aroundPrecision: 'aP',
  aroundRadius: 'aR',
  attributesToHighlight: 'aTH',
  attributesToRetrieve: 'aTR',
  attributesToSnippet: 'aTS',
  disjunctiveFacetsRefinements: 'dFR',
  disjunctiveFacets: 'dF',
  distinct: 'd',
  facetsExcludes: 'fE',
  facetsRefinements: 'fR',
  facets: 'f',
  getRankingInfo: 'gRI',
  hierarchicalFacetsRefinements: 'hFR',
  hierarchicalFacets: 'hF',
  highlightPostTag: 'hPoT',
  highlightPreTag: 'hPrT',
  hitsPerPage: 'hPP',
  ignorePlurals: 'iP',
  index: 'idx',
  insideBoundingBox: 'iBB',
  length: 'l',
  maxValuesPerFacet: 'mVPF',
  minWordSizefor1Typo: 'mWS1T',
  minWordSizefor2Typos: 'mWS2T',
  numericFilters: 'nF',
  numericRefinements: 'nR',
  offset: 'o',
  optionalWords: 'oW',
  page: 'p',
  queryType: 'qT',
  query: 'q',
  removeWordsIfNoResults: 'rWINR',
  replaceSynonymsInHighlight: 'rSIH',
  restrictSearchableAttributes: 'rSA',
  synonyms: 's',
  tagFilters: 'tF',
  tagRefinements: 'tR',
  typoTolerance: 'tT'
};

var short2Keys = invert(keys2Short);

module.exports = {
  /**
   * Decode a shorten attribute
   * @param {string} shortKey the shorten attribute
   * @return {string} the decoded attribute, undefined otherwise
   */
  decode: function(shortKey) {
    return short2Keys[shortKey];
  },
  /**
   * Encode an attribute into a short version
   * @param {string} key the attribute
   * @return {string} the shorten attribute
   */
  encode: function(key) {
    return keys2Short[key];
  }
};
<|endoftext|>