<commit_before>// Copyright 2012 The Obvious Corporation.

/*
 * A simple stream reader valve, for reliably capturing stream events
 * across tick boundaries.
 */

/*
 * Modules used
 */

"use strict";

var assert = require("assert");
var stream = require("stream");
var util   = require("util");

var consts = require("./consts");
var sealer = require("./sealer");

/*
 * Helper functions
 */

/**
 * Construct a Valve state object.
 */
function State(emitter, source, paused) {
    this.emitter = emitter;
    this.source  = source;
    this.paused  = (paused === undefined) ? true : !!paused;
    this.buffer  = [];
    this.ended   = false;
    this.closed  = false;

    this.onClose = this.onClose.bind(this);
    this.onData  = this.onData.bind(this);
    this.onEnd   = this.onEnd.bind(this);
    this.onError = this.onError.bind(this);

    if (typeof source.on !== "function") {
        throw new Error("Source not an EventEmitter.");
    }

    source.on(consts.CLOSE, this.onClose);
    source.on(consts.DATA,  this.onData);
    source.on(consts.END,   this.onEnd);
    source.on(consts.ERROR, this.onError);
}

State.prototype.destroy = function destroy() {
    var source = this.source;

    source.removeListener(consts.CLOSE, this.onClose);
    source.removeListener(consts.DATA,  this.onData);
    source.removeListener(consts.END,   this.onEnd);
    source.removeListener(consts.ERROR, this.onError);

    this.paused  = true;
    this.buffer  = undefined;
    this.emitter = undefined;
    this.ended   = true;
    this.closed  = true;
};

State.prototype.isReadable = function isReadable() {
    return !this.ended;
}

State.prototype.pause = function pause() {
    this.paused = true;
};

State.prototype.resume = function resume() {
    if (!this.paused) {
        return;
    }

    this.paused = false;

    var buf = this.buffer;
    for (var i = 0; i < buf.length; i++) {
        var one = buf[i];
        one.func(one.arg);
    }
};

State.prototype.onClose = function onClose() {
    if (this.paused) {
        this.buffer.push({ func: this.onClose });
    } else if (this.emitter && !this.closed) {
        this.emitter.emit(consts.CLOSE);
        this.ended = true;
        this.closed = true;
    }
}

State.prototype.onData = function onData(data) {
    if (this.paused) {
        this.buffer.push({ func: this.onData, arg: data });
    } else if (!this.ended) {
        this.emitter.emit(consts.DATA, data);
    }
}

State.prototype.onEnd = function onEnd() {
    if (this.paused) {
        this.buffer.push({ func: this.onEnd });
    } else if (this.emitter && !this.ended) {
        this.emitter.emit(consts.END);
        this.ended = true;
    }
}

State.prototype.onError = function onError(error) {
    if (this.paused) {
        this.buffer.push({ func: this.onError, arg: error });
    } else if (this.emitter && !this.ended) {
        this.emitter.emit(consts.ERROR, error);
        this.ended = true;
        this.closed = true;
    }
}

/*
 * Exported bindings
 */

/**
 * Construct a Valve instance, which relays events coming from the
 * indicated source stream. Valve instances are in turn instances of
 * `stream.Stream`.
 *
 * The optional `paused` argument indicates whether the valve starts
 * out paused (that is, buffering events). It defaults to `true`
 * (because that's the expected primary use case).
 */
function Valve(source, paused) {
    assert.ok(source !== undefined, "Missing source.");

    stream.Stream.call(this);
    this.valve = sealer.seal(new State(this, source, paused));
}

util.inherits(Valve, stream.Stream);

Valve.prototype.destroy = function destroy() {
    sealer.unseal(this.valve).destroy();
};

Valve.prototype.pause = function pause() {
    sealer.unseal(this.valve).pause();
};

Valve.prototype.resume = function resume() {
    sealer.unseal(this.valve).resume();
};

Valve.prototype.setEncoding = function setEncoding() {
    throw new Error("setEncoding() not supported");
};

Object.defineProperty(
    Valve.prototype,
    "readable",
    {
        get: function() { return sealer.unseal(this.valve).isReadable(); },
        enumerable: true
    });

Object.freeze(Valve.prototype);

module.exports = {
    Valve: Valve
};
<commit_msg>Fix the error emission case.<commit_after>// Copyright 2012 The Obvious Corporation.

/*
 * A simple stream reader valve, for reliably capturing stream events
 * across tick boundaries.
 */

/*
 * Modules used
 */

"use strict";

var assert = require("assert");
var stream = require("stream");
var util   = require("util");

var consts = require("./consts");
var sealer = require("./sealer");

/*
 * Helper functions
 */

/**
 * Construct a Valve state object.
 */
function State(emitter, source, paused) {
    this.emitter = emitter;
    this.source  = source;
    this.paused  = (paused === undefined) ? true : !!paused;
    this.buffer  = [];
    this.ended   = false;
    this.closed  = false;

    this.onClose = this.onClose.bind(this);
    this.onData  = this.onData.bind(this);
    this.onEnd   = this.onEnd.bind(this);
    this.onError = this.onError.bind(this);

    if (typeof source.on !== "function") {
        throw new Error("Source not an EventEmitter.");
    }

    source.on(consts.CLOSE, this.onClose);
    source.on(consts.DATA,  this.onData);
    source.on(consts.END,   this.onEnd);
    source.on(consts.ERROR, this.onError);
}

State.prototype.destroy = function destroy() {
    var source = this.source;

    source.removeListener(consts.CLOSE, this.onClose);
    source.removeListener(consts.DATA,  this.onData);
    source.removeListener(consts.END,   this.onEnd);
    source.removeListener(consts.ERROR, this.onError);

    this.paused  = true;
    this.buffer  = undefined;
    this.emitter = undefined;
    this.ended   = true;
    this.closed  = true;
};

State.prototype.isReadable = function isReadable() {
    return !this.ended;
}

State.prototype.pause = function pause() {
    this.paused = true;
};

State.prototype.resume = function resume() {
    if (!this.paused) {
        return;
    }

    this.paused = false;

    var buf = this.buffer;
    for (var i = 0; i < buf.length; i++) {
        var one = buf[i];
        one.func(one.arg);
    }
};

State.prototype.onClose = function onClose() {
    if (this.paused) {
        this.buffer.push({ func: this.onClose });
    } else if (this.emitter && !this.closed) {
        this.emitter.emit(consts.CLOSE);
        this.ended = true;
        this.closed = true;
    }
}

State.prototype.onData = function onData(data) {
    if (this.paused) {
        this.buffer.push({ func: this.onData, arg: data });
    } else if (!this.ended) {
        this.emitter.emit(consts.DATA, data);
    }
}

State.prototype.onEnd = function onEnd() {
    if (this.paused) {
        this.buffer.push({ func: this.onEnd });
    } else if (this.emitter && !this.ended) {
        this.emitter.emit(consts.END);
        this.ended = true;
    }
}

State.prototype.onError = function onError(error) {
    if (this.paused) {
        this.buffer.push({ func: this.onError, arg: error });
    } else if (this.emitter && !this.closed) {
        this.emitter.emit(consts.ERROR, error);
        this.ended = true;
        this.closed = true;
    }
}

/*
 * Exported bindings
 */

/**
 * Construct a Valve instance, which relays events coming from the
 * indicated source stream. Valve instances are in turn instances of
 * `stream.Stream`.
 *
 * The optional `paused` argument indicates whether the valve starts
 * out paused (that is, buffering events). It defaults to `true`
 * (because that's the expected primary use case).
 */
function Valve(source, paused) {
    assert.ok(source !== undefined, "Missing source.");

    stream.Stream.call(this);
    this.valve = sealer.seal(new State(this, source, paused));
}

util.inherits(Valve, stream.Stream);

Valve.prototype.destroy = function destroy() {
    sealer.unseal(this.valve).destroy();
};

Valve.prototype.pause = function pause() {
    sealer.unseal(this.valve).pause();
};

Valve.prototype.resume = function resume() {
    sealer.unseal(this.valve).resume();
};

Valve.prototype.setEncoding = function setEncoding() {
    throw new Error("setEncoding() not supported");
};

Object.defineProperty(
    Valve.prototype,
    "readable",
    {
        get: function() { return sealer.unseal(this.valve).isReadable(); },
        enumerable: true
    });

Object.freeze(Valve.prototype);

module.exports = {
    Valve: Valve
};
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var plugin = require('./plugins');
var utils = require('./utils');
var Base = require('./base');

/**
 * Expose `Views`
 */

module.exports = Views;

/**
 * Create an instance of `Views` with the given `options`.
 *
 * ```js
 * var collection = new Views();
 * collection.addView('foo', {content: 'bar'});
 * ```
 * @param {Object} `options`
 * @api public
 */

function Views(options) {
  if (!(this instanceof Views)) {
    return new Views(options);
  }
  Base.call(this);
  this.init(options || {});
}

/**
 * Inherit `Base`
 */

Base.extend(Views);

/**
 * Mixin prototype methods
 */

plugin.routes(Views.prototype);
plugin.engine(Views.prototype);
plugin.layout(Views.prototype);
plugin.render(Views.prototype);
plugin.lookup(Views.prototype);
plugin.errors(Views.prototype, 'Views');

/**
 * Initialize `Views` defaults
 */

Views.prototype.init = function(opts) {
  this.define('isCollection', true);
  this.define('isViews', true);

  // decorate the instance
  this.use(plugin.init);
  this.use(plugin.renameKey());
  this.use(plugin.context);
  this.use(plugin.helpers);
  this.use(plugin.item('view', 'View'));

  // add constructors
  this.define('List', opts.List || require('./list'));
  this.define('View', opts.View || require('./view'));
  this.define('loaded', false);

  this.queue = [];
  this.views = {};

  // if an instance of `List` of `Views` is passed, load it now
  if (Array.isArray(opts) || opts.isList) {
    this.options = opts.options || {};
    this.addList(opts.items || opts);

  } else if (opts.isCollection) {
    this.options = opts.options;
    this.addViews(opts.views);

  } else {
    this.options = opts;
  }
};

/**
 * Set a view on the collection. This is identical to [addView](#addView)
 * except `setView` does not emit an event for each view.
 *
 * ```js
 * collection.setView('foo', {content: 'bar'});
 * ```
 *
 * @param {String|Object} `key` View key or object
 * @param {Object} `value` If key is a string, value is the view object.
 * @developer This method is decorated onto the collection in the constructor using the `createView` utility method.
 * @return {Object} returns the `view` instance.
 * @api public
 */

Views.prototype.setView = function(key, value) {
  var view = this.view(key, value);
  if (view.use) this.run(view);

  this.views[view.key] = view;
  return view;
};

/**
 * Similar to [setView](#setView), adds a view to the collection
 * but also fires an event and iterates over the loading `queue`
 * for loading views from the `addView` event listener. If the
 * given view is not already an instance of `View`, it will be
 * converted to one before being added to the `views` object.
 *
 * ```js
 * var views = new Views(...);
 * views.addView('a.html', {path: 'a.html', contents: '...'});
 * ```
 * @param {String} `key`
 * @param {Object} `value`
 * @return {Object} Returns the instance of the created `View` to allow chaining view methods.
 * @api public
 */

Views.prototype.addView = function(/*key, value*/) {
  var args = [].slice.call(arguments);
  this.emit.call(this, 'addView', args);

  var view = this.setView.apply(this, args);
  while (this.queue.length) {
    this.setView(this.queue.shift());
  }
  this.extendView(view);
  return view;
};

/**
 * Load multiple views onto the collection.
 *
 * ```js
 * collection.addViews({
 *   'a.html': {content: '...'},
 *   'b.html': {content: '...'},
 *   'c.html': {content: '...'}
 * });
 * ```
 * @param {Object|Array} `views`
 * @return {Object} returns the `collection` object
 * @api public
 */

Views.prototype.addViews = function(views) {
  this.emit('addViews', views);
  if (this.loaded) return this;
  if (utils.hasGlob(views)) {
    throw new Error('glob patterns are not supported by addViews');
  }
  if (Array.isArray(views)) {
    this.addList.apply(this, arguments);
    return this;
  }
  if (arguments.length > 1 && utils.isView(arguments[1])) {
    this.addView.apply(this, arguments);
    return this;
  }
  this.visit('addView', views);
  return this;
};

/**
 * Load an array of views onto the collection.
 *
 * ```js
 * collection.addList([
 *   {path: 'a.html', content: '...'},
 *   {path: 'b.html', content: '...'},
 *   {path: 'c.html', content: '...'}
 * ]);
 * ```
 * @param {Array} `list`
 * @return {Object} returns the `views` instance
 * @api public
 */

Views.prototype.addList = function(list, fn) {
  this.emit('addList', list);
  if (this.loaded) return this;
  if (utils.hasGlob(list)) {
    throw new Error('glob patterns are not supported by addList');
  }
  if (!Array.isArray(list)) {
    throw new TypeError('expected list to be an array.');
  }
  if (typeof fn !== 'function') {
    fn = utils.identity;
  }
  var len = list.length, i = -1;
  while (++i < len) {
    var view = fn(list[i]);
    this.addView(view.path, view);
  }
  return this;
};

/**
 * Get a view from the collection.
 *
 * ```js
 * collection.getView('a.html');
 * ```
 * @param {String} `key` Key of the view to get.
 * @return {Object}
 * @api public
 */

Views.prototype.getView = function(key, options) {
  var opts = utils.extend({}, this.options, options);
  var cwd = opts.cwd || process.cwd();
  var view = this.views[key]
    || this.views[this.renameKey(key)]
    || this.views[path.resolve(cwd, key)]
    || this.views[path.relative(cwd, key)];

  if (!view) {
    var fp = path.join(cwd, key);
    if (fs.existsSync(fp)) {
      var str = fs.readFileSync(fp);
      var view =  this.setView(key, {
        options: utils.extend({}, opts, {renameKey: false}),
        key: key,
        contents: str
      });
      return view;
    }

    var ext = path.extname(fp);
    if (ext) return null;

    ext = this.options.engine;
    if (ext.charAt(0) !== '.') {
      ext = '.' + ext;
    }
    return this.getView(key + ext);
  }
  return view;
};
/**
 * Decorate each view on the collection with additional methods
 * and properties. This provides a way of easily overriding
 * defaults.
 *
 * @param {Object} `view`
 * @return {Object}
 * @api public
 */

Views.prototype.extendView = function(view) {
  return plugin.view.all(this, view);
};

/**
 * Set view types for the collection.
 *
 * @param {String} `plural` e.g. `pages`
 * @param {Object} `options`
 * @api private
 */

Views.prototype.viewType = function() {
  this.options.viewType = utils.arrayify(this.options.viewType || []);
  if (this.options.viewType.length === 0) {
    this.options.viewType.push('renderable');
  }
  return this.options.viewType;
};
<commit_msg>extension cache for lookups<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var plugin = require('./plugins');
var utils = require('./utils');
var Base = require('./base');

/**
 * Expose `Views`
 */

module.exports = Views;

/**
 * Create an instance of `Views` with the given `options`.
 *
 * ```js
 * var collection = new Views();
 * collection.addView('foo', {content: 'bar'});
 * ```
 * @param {Object} `options`
 * @api public
 */

function Views(options) {
  if (!(this instanceof Views)) {
    return new Views(options);
  }
  Base.call(this);
  this.init(options || {});
}

/**
 * Inherit `Base`
 */

Base.extend(Views);

/**
 * Mixin prototype methods
 */

plugin.routes(Views.prototype);
plugin.engine(Views.prototype);
plugin.layout(Views.prototype);
plugin.render(Views.prototype);
plugin.lookup(Views.prototype);
plugin.errors(Views.prototype, 'Views');

/**
 * Initialize `Views` defaults
 */

Views.prototype.init = function(opts) {
  this.define('isCollection', true);
  this.define('isViews', true);

  // decorate the instance
  this.use(plugin.init);
  this.use(plugin.renameKey());
  this.use(plugin.context);
  this.use(plugin.helpers);
  this.use(plugin.item('view', 'View'));

  // add constructors
  this.define('List', opts.List || require('./list'));
  this.define('View', opts.View || require('./view'));
  this.define('loaded', false);

  this.queue = [];
  this.views = {};

  // if an instance of `List` of `Views` is passed, load it now
  if (Array.isArray(opts) || opts.isList) {
    this.options = opts.options || {};
    this.addList(opts.items || opts);

  } else if (opts.isCollection) {
    this.options = opts.options;
    this.addViews(opts.views);

  } else {
    this.options = opts;
  }
};

/**
 * Set a view on the collection. This is identical to [addView](#addView)
 * except `setView` does not emit an event for each view.
 *
 * ```js
 * collection.setView('foo', {content: 'bar'});
 * ```
 *
 * @param {String|Object} `key` View key or object
 * @param {Object} `value` If key is a string, value is the view object.
 * @developer This method is decorated onto the collection in the constructor using the `createView` utility method.
 * @return {Object} returns the `view` instance.
 * @api public
 */

Views.prototype.setView = function(key, value) {
  var view = this.view(key, value);
  if (view.use) this.run(view);

  this.views[view.key] = view;
  return view;
};

/**
 * Similar to [setView](#setView), adds a view to the collection
 * but also fires an event and iterates over the loading `queue`
 * for loading views from the `addView` event listener. If the
 * given view is not already an instance of `View`, it will be
 * converted to one before being added to the `views` object.
 *
 * ```js
 * var views = new Views(...);
 * views.addView('a.html', {path: 'a.html', contents: '...'});
 * ```
 * @param {String} `key`
 * @param {Object} `value`
 * @return {Object} Returns the instance of the created `View` to allow chaining view methods.
 * @api public
 */

Views.prototype.addView = function(/*key, value*/) {
  var args = [].slice.call(arguments);
  this.emit.call(this, 'addView', args);

  var view = this.setView.apply(this, args);
  while (this.queue.length) {
    this.setView(this.queue.shift());
  }
  this.extendView(view);
  return view;
};

/**
 * Load multiple views onto the collection.
 *
 * ```js
 * collection.addViews({
 *   'a.html': {content: '...'},
 *   'b.html': {content: '...'},
 *   'c.html': {content: '...'}
 * });
 * ```
 * @param {Object|Array} `views`
 * @return {Object} returns the `collection` object
 * @api public
 */

Views.prototype.addViews = function(views) {
  this.emit('addViews', views);
  if (this.loaded) return this;
  if (utils.hasGlob(views)) {
    throw new Error('glob patterns are not supported by addViews');
  }
  if (Array.isArray(views)) {
    this.addList.apply(this, arguments);
    return this;
  }
  if (arguments.length > 1 && utils.isView(arguments[1])) {
    this.addView.apply(this, arguments);
    return this;
  }
  this.visit('addView', views);
  return this;
};

/**
 * Load an array of views onto the collection.
 *
 * ```js
 * collection.addList([
 *   {path: 'a.html', content: '...'},
 *   {path: 'b.html', content: '...'},
 *   {path: 'c.html', content: '...'}
 * ]);
 * ```
 * @param {Array} `list`
 * @return {Object} returns the `views` instance
 * @api public
 */

Views.prototype.addList = function(list, fn) {
  this.emit('addList', list);
  if (this.loaded) return this;
  if (utils.hasGlob(list)) {
    throw new Error('glob patterns are not supported by addList');
  }
  if (!Array.isArray(list)) {
    throw new TypeError('expected list to be an array.');
  }
  if (typeof fn !== 'function') {
    fn = utils.identity;
  }
  var len = list.length, i = -1;
  while (++i < len) {
    var view = fn(list[i]);
    this.addView(view.path, view);
  }
  return this;
};

/**
 * Get a view from the collection.
 *
 * ```js
 * collection.getView('a.html');
 * ```
 * @param {String} `key` Key of the view to get.
 * @return {Object}
 * @api public
 */

Views.prototype.getView = function(key, options) {
  var opts = utils.extend({}, this.options, options);
  var cwd = opts.cwd || process.cwd();
  var view = this.views[key]
    || this.views[this.renameKey(key)]
    || this.views[path.resolve(cwd, key)]
    || this.views[path.relative(cwd, key)];

  // TODO: move this code into plugin for matching or lookups
  if (!view) {
    var fp = path.join(cwd, key);
    if (fs.existsSync(fp)) {
      var str = fs.readFileSync(fp);
      var view =  this.setView(key, {
        options: utils.extend({}, opts, {renameKey: false}),
        key: key,
        contents: str
      });
      return view;
    }

    this.__exts__ = this.__exts__ || {};
    var ext = path.extname(fp);
    if (!ext) ext = opts.engine;
    if (!ext) return null;

    if (ext.charAt(0) !== '.') {
      ext = '.' + ext;
    }

    if (this.__exts__[ext]) {
      return null;
    }

    this.__exts__[ext] = true;
    var res = this.getView(key + ext);
    return res;
  }
  return view;
};

/**
 * Decorate each view on the collection with additional methods
 * and properties. This provides a way of easily overriding
 * defaults.
 *
 * @param {Object} `view`
 * @return {Object}
 * @api public
 */

Views.prototype.extendView = function(view) {
  return plugin.view.all(this, view);
};

/**
 * Set view types for the collection.
 *
 * @param {String} `plural` e.g. `pages`
 * @param {Object} `options`
 * @api private
 */

Views.prototype.viewType = function() {
  this.options.viewType = utils.arrayify(this.options.viewType || []);
  if (this.options.viewType.length === 0) {
    this.options.viewType.push('renderable');
  }
  return this.options.viewType;
};
<|endoftext|>


<commit_before><commit_msg>remove stupid files<commit_after><|endoftext|>


<commit_before>'use strict';

var crypto = require('crypto')
  , fs = require('fs');

/**
 * The librarian manages all the assets that we have inside our pagelets. It's
 * able to identify the most commonly included libraries and compiles them in
 * a single core file.
 *
 * All non-common assets are also compiled and saved to disk so we don't have to
 * recompile everything during a request.
 *
 * Options:
 *
 * - threshold, the precentage of pages it's included on for it to be consided
 *   a candicate for the core file. Default to 80%.
 *
 * @constructor
 * @param {Pipe} pipe Reference to the Pipe
 * @api public
 */
function Librarian(pipe, options) {
  options = options || {};

  this.threshold = parseInt(options.threshold || 80, 10); // Threshold for core.
  this.appendix = Object.create(null);                    // List of core files.
  this.buffer = Object.create(null);                      // File lookup table.
  this.pipe = pipe;
}

//
// Proxy some of the pipe's properties directly in to our librarian.
//
['log', 'pages', 'temper'].forEach(function proxy(api) {
  Object.defineProperty(Librarian.prototype, api, {
    get: function get() {
      return this.pipe[api];
    }
  });
});

//
// Provide a pre-parsed interface to the pagelet for easy modification.
//
Object.defineProperty(Librarian.prototype, 'parsed', {
  get: function pagelets() {
    var authorization = {}
      , pagelet = {};

    var pages = this.pipe.pages.reduce(function each(memo, Page) {
      memo[Page.id] = Page.prototype.pagelets.map(function normalize(Pagelet) {
        var proto = Pagelet.prototype;

        return {
          dependencies: proto.dependencies,   // Array of pagelet dependencies.
          authorized: !!proto.authorize,      // Is authorization required.
          view: proto.view,                   // Location of the view.
          name: proto.name,                   // Name of the pagelet.
          css: proto.css,                     // Location of the CSS.
          js: proto.view,                     // Location of the JS.
          id: Page.id                         // Id of the page.
        };
      }).reduce(function sort(pagelets, data) {
        if (data.authorized) authorization[data.name] = data;
        else pagelet[data.name] = data;

        pagelets[data.name] = data;
        return pagelets;
      }, {});

      return memo;
    }, {});

    //
    // Add some easy to use iterators.
    //
    [authorization, pagelet, pages].forEach(function each(data) {
      Object.defineProperty(data, 'forEach', {
        value: function (fn) {
          Object.keys(data).forEach(function (key) {
            fn(data[key], key, data);
          });
        }
      });
    });

    return {
      authorized: authorization,
      pagelets: pagelet,
      pages: pages
    };
  }
});

Librarian.prototype.catalog = function catalog() {
  var meta = this.meta();
};

/**
 * Scan the supplied pages for duplicate pagelet definitions. Some rules for
 * scanning:
 *
 * - Pagelets that require authorization should never be included in the core
 *   file. This includes the template engines they leverage. As this code
 *   shouldn't be exposed to the general public.
 *
 * @api public
 */
Librarian.prototype.meta = function metagenerator() {
  var temper = this.temper
    , data = this.parsed
    , meta = {};

  /**
   * Increment a metric.
   *
   * @param {String} what Name of the metrics.
   * @api private
   */
  function incr(what) {
    if (what in meta) meta['counter::'+ what]++;
    else meta['counter::'+ what] = 1;

    return incr;
  }

  data.pagelets.forEach(function each(pagelet) {
    var template = temper.fetch(pagelet.view);

    meta[template.engine] = template.library;
    incr('library::'+ template.engine);
  });

  return meta;
};

/**
 * Returns a list of files that should be embed in to the page.
 *
 * @api public
 */
Librarian.prototype.lend = function lend(page) {

};

/**
 * Serve the content over the HTTP connection.
 *
 * @param {Request} req The HTTP request.
 * @param {Response} res The HTTP response.
 * @returns {Boolean} Served by the librarian.
 * @api public
 */
Librarian.prototype.serve = function serve(req, res) {
  if (!(req.url in this.buffer)) return false;

  return true;
};

/**
 * Create a versioned filename from the content. This allows cache busting when
 * the content has changed.
 *
 * @param {String} extension The file extension returned from path.extname.
 * @param {String} content The content.
 * @returns {String} The versioned filename
 * @api private
 */
Librarian.prototype.version = function version(extension, content) {
  return crypto.createHash('sha1')
    .update(content)
    .digest()
    .toString('hex') + extension;
};

/**
 * Read a file location.
 *
 * @param {String} path Location of the file.
 * @api private
 */
Librarian.prototype.read = function read(path) {
  if (path in this.buffer) return this.buffer[path];

  return this.buffer[path] = fs.readFileSync(path, 'utf-8');
};

//
// Initialize.
//
module.exports = Librarian;
<commit_msg>[minor] Count css, js and views<commit_after>'use strict';

var crypto = require('crypto')
  , fs = require('fs');

/**
 * The librarian manages all the assets that we have inside our pagelets. It's
 * able to identify the most commonly included libraries and compiles them in
 * a single core file.
 *
 * All non-common assets are also compiled and saved to disk so we don't have to
 * recompile everything during a request.
 *
 * Options:
 *
 * - threshold, the precentage of pages it's included on for it to be consided
 *   a candicate for the core file. Default to 80%.
 *
 * @constructor
 * @param {Pipe} pipe Reference to the Pipe
 * @api public
 */
function Librarian(pipe, options) {
  options = options || {};

  this.threshold = parseInt(options.threshold || 80, 10); // Threshold for core.
  this.appendix = Object.create(null);                    // List of core files.
  this.buffer = Object.create(null);                      // File lookup table.
  this.pipe = pipe;
}

//
// Proxy some of the pipe's properties directly in to our librarian.
//
['log', 'pages', 'temper'].forEach(function proxy(api) {
  Object.defineProperty(Librarian.prototype, api, {
    get: function get() {
      return this.pipe[api];
    }
  });
});

//
// Provide a pre-parsed interface to the pagelet for easy modification.
//
Object.defineProperty(Librarian.prototype, 'parsed', {
  get: function pagelets() {
    var authorization = {}
      , pagelet = {};

    var pages = this.pipe.pages.reduce(function each(memo, Page) {
      memo[Page.id] = Page.prototype.pagelets.map(function normalize(Pagelet) {
        var proto = Pagelet.prototype;

        return {
          dependencies: proto.dependencies,   // Array of pagelet dependencies.
          authorized: !!proto.authorize,      // Is authorization required.
          view: proto.view,                   // Location of the view.
          name: proto.name,                   // Name of the pagelet.
          css: proto.css,                     // Location of the CSS.
          js: proto.view,                     // Location of the JS.
          id: Page.id                         // Id of the page.
        };
      }).reduce(function sort(pagelets, data) {
        if (data.authorized) authorization[data.name] = data;
        else pagelet[data.name] = data;

        pagelets[data.name] = data;
        return pagelets;
      }, {});

      return memo;
    }, {});

    //
    // Add some easy to use iterators.
    //
    [authorization, pagelet, pages].forEach(function each(data) {
      Object.defineProperty(data, 'forEach', {
        value: function (fn) {
          Object.keys(data).forEach(function (key) {
            fn(data[key], key, data);
          });
        }
      });
    });

    return {
      authorized: authorization,
      pagelets: pagelet,
      pages: pages
    };
  }
});

Librarian.prototype.catalog = function catalog() {
  var meta = this.meta();
};

/**
 * Scan the supplied pages for duplicate pagelet definitions. Some rules for
 * scanning:
 *
 * - Pagelets that require authorization should never be included in the core
 *   file. This includes the template engines they leverage. As this code
 *   shouldn't be exposed to the general public.
 *
 * @api public
 */
Librarian.prototype.meta = function metagenerator() {
  var temper = this.temper
    , data = this.parsed
    , meta = {};

  /**
   * Increment a metric.
   *
   * @param {String} what Name of the metrics.
   * @api private
   */
  function incr(what) {
    if (what in meta) meta['counter::'+ what]++;
    else meta['counter::'+ what] = 1;

    return incr;
  }

  data.pagelets.forEach(function each(pagelet) {
    var template = temper.fetch(pagelet.view);

    meta[template.engine] = template.library;
    incr('library::'+ template.engine);
    incr('view::'+ pagelet.view);
    incr('css::'+ pagelet.css);
    incr('js::'+ pagelet.js);
  });

  return meta;
};

/**
 * Returns a list of files that should be embed in to the page.
 *
 * @param {Page} page A page instance.
 * @returns {Object} JavaScript and CSS that needs to be included in the page.
 * @api public
 */
Librarian.prototype.lend = function lend(page) {

};

/**
 * Serve the content over the HTTP connection.
 *
 * @param {Request} req The HTTP request.
 * @param {Response} res The HTTP response.
 * @returns {Boolean} Served by the librarian.
 * @api public
 */
Librarian.prototype.serve = function serve(req, res) {
  if (!(req.url in this.buffer)) return false;

  return true;
};

/**
 * Create a versioned filename from the content. This allows cache busting when
 * the content has changed.
 *
 * @param {String} extension The file extension returned from path.extname.
 * @param {String} content The content.
 * @returns {String} The versioned filename
 * @api private
 */
Librarian.prototype.version = function version(extension, content) {
  return crypto.createHash('sha1')
    .update(content)
    .digest()
    .toString('hex') + extension;
};

/**
 * Read a file location.
 *
 * @param {String} path Location of the file.
 * @api private
 */
Librarian.prototype.read = function read(path) {
  if (path in this.buffer) return this.buffer[path];

  return this.buffer[path] = fs.readFileSync(path, 'utf-8');
};

//
// Initialize.
//
module.exports = Librarian;
<|endoftext|>


<commit_before>var map;
function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: -34.397, lng: 150.644},
      zoom: 20,
      scrollwheel: false,
      zoomControl: false,
      mapTypeControl: false,
      scaleControl: false,
      streetViewControl: false,
      rotateControl: false,
      fullscreenControl: false,
      draggable: false,
      keyboardShortcuts: false
    });
    var infoWindow = new google.maps.InfoWindow({map: map});

    // Try HTML5 geolocation.
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(function(position) {
        var pos = {
          lat: position.coords.latitude,
          lng: position.coords.longitude
        };

        infoWindow.setPosition(pos);
        infoWindow.setContent('Location found.');
        map.setCenter(pos);
      }, function() {
        handleLocationError(true, infoWindow, map.getCenter());
      });
    } else {
        handleLocationError(false, infoWindow, map.getCenter());
    }
    //var currentPosition = {lat: -34.397, lng: 150.644};
    var currentPosition = getPosition(infoWindow);
    var target = {lat: 90, lng: 120.644};
    //setInterval(getPosition(infoWindow), 1000);
    setInterval(function() {
	getPosition(infoWindow);
	//trace
        console.log("fuck");
    }, 1000);
    trace(currentPosition, target);
}
function getPosition(infoWindow) {
    navigator.geolocation.getCurrentPosition(function(position) {
	var pos = {
            lat: position.coords.latitude,
            lng: position.coords.longitude
	};

	infoWindow.setPosition(pos);
	infoWindow.setContent('Location found.');
	map.setCenter(pos);
	console.log("rrrr");
    }, function() {
	console.log("fucked it");
	handleLocationError(true, infoWindow, map.getCenter());
    });
}
function trace(currentPosition, targetPosition){
    nbOfPointers = 100; //getDistance(currentPosition, targetPosition);
    xDistance = (targetPosition.lat - currentPosition.lat)/nbOfPointers;
    yDistance = (targetPosition.lng - currentPosition.lng)/nbOfPointers;
    var flightPlanCoordinates = [];

    var angle = Math.atan2(targetPosition.lat - currentPosition.lat, targetPosition.lng - currentPosition.lng )*(180/Math.PI);
    var image = {
        url: "./traceIcon.png",
        scaledSize: new google.maps.Size(32, 30),
        anchor: new google.maps.Point(16, 15) ,
        rotation: 52
    };
    nbOfShownPointers = nbOfPointers/10;
    console.log(angle);
    for (var i = 0; i < nbOfShownPointers; i++){
        var p = {lat: currentPosition.lat + (xDistance *i), lng: currentPosition.lng + (yDistance *i)};
        var marker = new google.maps.Marker({
          position: p,
          map: map,
          icon: image
        });
    }
    var marker = new google.maps.Marker({
          position: currentPosition,
          map: map,
        });
    var marker = new google.maps.Marker({
          position: targetPosition,
          map: map,
        });
}
function handleLocationError(browserHasGeolocation, infoWindow, pos) {
    infoWindow.setPosition(pos);
    infoWindow.setContent(browserHasGeolocation ?
                          'Error: The Geolocation service failed.' :
                          'Error: Your browser doesn\'t support geolocation.');
}
<commit_msg>jacks code<commit_after>var map;
function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: -34.397, lng: 150.644},
      zoom: 20,
      scrollwheel: false,
      zoomControl: false,
      mapTypeControl: false,
      scaleControl: false,
      streetViewControl: false,
      rotateControl: false,
      fullscreenControl: false,
      draggable: false,
      keyboardShortcuts: false
    });
    var infoWindow = new google.maps.InfoWindow({map: map});

    // Try HTML5 geolocation.
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(function(position) {
        var pos = {
          lat: position.coords.latitude,
          lng: position.coords.longitude
        };

        infoWindow.setPosition(pos);
        infoWindow.setContent('Location found.');
        map.setCenter(pos);
      }, function() {
        handleLocationError(true, infoWindow, map.getCenter());
      });
    } else {
        handleLocationError(false, infoWindow, map.getCenter());
    }
    //var currentPosition = {lat: -34.397, lng: 150.644};
    var currentPosition = getPosition(infoWindow);
    var target = {lat: 90, lng: 120.644};
    //setInterval(getPosition(infoWindow), 1000);
    setInterval(function() {
	getPosition(infoWindow);
	//trace
        console.log("fuck");
    }, 1000);
    trace(currentPosition, target);
}
function getPosition(infoWindow) {
    navigator.geolocation.getCurrentPosition(function(position) {
	var pos = {
            lat: position.coords.latitude,
            lng: position.coords.longitude
	};

	infoWindow.setPosition(pos);
	infoWindow.setContent('Location found.');
	map.setCenter(pos);
	console.log("rrrr");
    }, function() {
	console.log("fucked it");
	handleLocationError(true, infoWindow, map.getCenter());
    });
}
function trace(currentPosition, targetPosition){
    nbOfPointers = 100; //getDistance(currentPosition, targetPosition);
    xDistance = (targetPosition.lat - currentPosition.lat)/nbOfPointers;
    yDistance = (targetPosition.lng - currentPosition.lng)/nbOfPointers;
    var flightPlanCoordinates = [];

    var angle = Math.atan2(targetPosition.lat - currentPosition.lat, targetPosition.lng - currentPosition.lng )*(180/Math.PI);
    var image = {
        path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,
        scaledSize: new google.maps.Size(32, 30),
        anchor: new google.maps.Point(16, 15) ,
        rotation: 52
    };
    nbOfShownPointers = nbOfPointers/10;
    console.log(angle);
    for (var i = 0; i < nbOfShownPointers; i++){
        var p = {lat: currentPosition.lat + (xDistance *i), lng: currentPosition.lng + (yDistance *i)};
        var marker = new google.maps.Marker({
          position: p,
          map: map,
          icon: image
        });
    }
    var marker = new google.maps.Marker({
          position: currentPosition,
          map: map,
        });
    var marker = new google.maps.Marker({
          position: targetPosition,
          map: map,
        });
}
function handleLocationError(browserHasGeolocation, infoWindow, pos) {
    infoWindow.setPosition(pos);
    infoWindow.setContent(browserHasGeolocation ?
                          'Error: The Geolocation service failed.' :
                          'Error: Your browser doesn\'t support geolocation.');
}
<|endoftext|>


<commit_before>var frequencies, pivots;

/**
 * for each node, calculate the derivative of the frequency tranjectory. if none exists, copy parent
**/
function calcDfreq(node, freq_ii){
	if (typeof node.children != "undefined") {
		for (var i1=0; i1<node.children.length; i1++) {
			if (typeof node.children[i1].freq != "undefined") {
				if (node.children[i1].freq["global"] != "undefined"){
					var tmp_freq = node.children[i1].freq["global"]
					node.children[i1].dfreq = 0.5*(tmp_freq[freq_ii] - tmp_freq[freq_ii-dfreq_dn])/(tmp_freq[freq_ii] + tmp_freq[freq_ii-dfreq_dn] + 0.1);
				} else {
					node.children[i1].dfreq = node.dfreq;
				}
			}
			calcDfreq(node.children[i1], freq_ii);
		}
	}
};
function parse_gt_string(gt){
	mutations = [];
	gt.split(',').map( function (d) {
		var tmp = d.split(/[\s//]/); //FIXME: make more inclusive
		var region;
		var positions = [];
		for (var i=0; i<tmp.length; i++){
			if (contains(["EU","NA","AS","OC"], tmp[i])){
				region = tmp[i];
			}else{
				if (tmp[i].length>0) positions.push(tmp[i]);
			}
		}
		if (typeof region == "undefined") region="global";
		// sort of this is a multi mutation genotype
		if (positions.length>1){
			positions.sort(function (a,b){
				return parseInt(a.substring(0,a.length-1)) - parseInt(b.substring(0,b.length-1));
			});
		}
		mutations.push([region, positions.join('/')]);
	});
	return mutations;
};

/**
loops over all genotypes from a certain region and sums the frequency contributions
of the genotype matches at the specified positions
**/
function get_frequencies(region, gt){
	var freq = [];
	for (var pi=0; pi<pivots.length; pi++){freq[freq.length]=0;}
	if (frequencies["clades"][region][gt.toLowerCase()]!=undefined) {
		console.log(gt+" found as clade");
		for (var pi=0; pi<freq.length; pi++){
			freq[pi]+=frequencies["clades"][region][gt.toLowerCase()][pi];
		}
	}
	else if ((typeof frequencies["genotypes"] !="undefined") && (frequencies["genotypes"][region][gt]!=undefined)) {
		console.log(gt+" found as genotype");
		for (var pi=0; pi<freq.length; pi++){
			freq[pi]+=frequencies["genotypes"][region][gt][pi];
		}
	}else if (frequencies["mutations"][region][gt]!=undefined) {
		console.log(gt+" found as mutation");
		for (var pi=0; pi<freq.length; pi++){
			freq[pi]+=frequencies["mutations"][region][gt][pi];
		}
	}
	return freq.map(function (d) {return Math.round(d*100)/100;});
};

function make_gt_chart(gt){
	var tmp_data = [];
	var tmp_trace = ['x'];
	var tmp_colors = {};
	tmp_data.push(tmp_trace.concat(pivots));
	gt.forEach(function (d, i) {
		var region = d[0];
		var genotype = d[1];
		var freq = get_frequencies(region, genotype);
		if (d3.max(freq)>0) {
			var tmp_trace = genotype.toString().replace(/,/g, ', ');
			if (region != "global") {
				tmp_trace = region + ':\t' + tmp_trace;
			}
			tmp_data.push([tmp_trace].concat(freq));
			tmp_colors[tmp_trace] = genotypeColors[i];
		}
	});
	console.log(tmp_colors);
	gt_chart.load({
       	columns: tmp_data,
       	unload: true
	});
	gt_chart.data.colors(tmp_colors);
}

function addClade(d) {
	if (typeof gt_chart != "undefined"){
		var plot_data = [['x'].concat(rootNode["pivots"])];
		var reg = "global";
		if ((typeof d.target.freq !="undefined" )&&(d.target.freq[reg] != "undefined")){
			plot_data[plot_data.length] = [reg].concat(d.target.freq[reg]);
		}
		if (plot_data.length > 1) {
			if (plot_data[1][0] == "global") {
				plot_data[1][0] = "clade";
			}
		}
		gt_chart.load({
	       	columns: plot_data
		});
	}
}

function removeClade() {
	if (typeof gt_chart != "undefined"){
		gt_chart.unload({
	       	ids: ["clade"]
		});
	}
}

width = parseInt(d3.select(".freqplot-container").style("width"), 10);
height = 250;
var position = "inset";

var gt_chart = c3.generate({
	bindto: '#gtchart',
	size: {width: width-10, height: height},
	onresize: function() {
		width = parseInt(d3.select(".freqplot-container").style("width"), 10);
		height = 250;
		gt_chart.resize({height: height, width: width});
	},
	legend: {
		position: position,
		inset: {
    		anchor: 'top-right',
    		x: 10,
    		y: -15,
    		step: 1
    	}
	},
  	color: {
        pattern: genotypeColors
    },
	axis: {
		y: {
			label: {
				text: 'frequency',
				position: 'outer-middle'
			},
			tick: {
				values: [0.0, 0.2, 0.4, 0.6, 0.8, 1.0],
				outer: false
			},
            min: 0,
			max: 1
		},
		x: {
			label: {
				text: 'time',
				position: 'outer-center'
			},
			tick: {
				values: time_ticks,
				outer: false
			}
		}
	},
	data: {
		x: 'x',
		columns: [],
	}
});

function contains(arr, obj) {
    for(var i=0; i<arr.length; i++) {
        if (arr[i] == obj) return true;
    }
}

d3.json(path + file_prefix + "frequencies.json", function(error, json){
	console.log(error);
	frequencies = json;
	pivots= frequencies["mutations"]["global"]["pivots"].map(function (d) {return Math.round(parseFloat(d)*100)/100;});
	var ticks = [Math.round(pivots[0])];
	var tick_step = Math.round((pivots[pivots.length-1]-pivots[0])/6*10)/10;
	while (ticks[ticks.length-1]<pivots[pivots.length-1]){
		ticks.push(Math.round((ticks[ticks.length-1]+tick_step)*10)/10);
	}
	//gt_chart.axis.x.values = ticks;
	/**
		parses a genotype string into region and positions
	**/

	var chart_data = {'x':[], '':[]};
	for (var ii=0;ii<frequencies["entropy"].length;ii+=1){
		if (Math.round(10000*frequencies["entropy"][ii][1])/10000>0.05){
			chart_data[''].push(Math.round(10000*frequencies["entropy"][ii][1])/10000);
			chart_data['x'].push(ii+1);
		}
	}

	var chart_types = {'':'bar'}
	var chart_xaxis = {'':'x'}
	var ymin = 0;
	for (x in genome_annotation){
		chart_data['x'+x] = genome_annotation[x][1];
		chart_data[x] = genome_annotation[x][0].map(function(d) {return -0.1*d;});
		if (ymin>chart_data[x][0]){
			ymin = chart_data[x][0];
		}
		chart_types[x] = 'line';
		chart_xaxis[x] = 'x'+x;
	}
	ymin-=0.08;
	console.log(chart_data);
	console.log(chart_types);
	console.log(chart_xaxis);
	var entropy_chart = c3.generate({
		bindto: '#entropy',
		size: {width: width-10, height: height},
		onresize: function() {
			width = parseInt(d3.select(".entropy-container").style("width"), 10);
			height = 250;
			entropy_chart.resize({height: height, width: width});
		},
		legend: {show: false},
		color: {pattern: ["#AAA"]},
		axis: {
			y: {
				label: {
					text: 'variability',
					position: 'outer-middle'
				},
				tick: {
					values: [0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6],
					outer: false
				},
				min:ymin,
			},
			x: {
				label: {
					text: 'position',
					position: 'outer-center'
				},
				tick: {
					outer: false,
					values: [100,200,300,400,500]
				}
			},
		},
		data: {
			xs: chart_xaxis,
			json: chart_data,
			types: chart_types,
			onclick: function (d,i) {
				console.log(d);
				if (frequencies["entropy"][d.x-1][2].length>1){
					var tmp = [];
					for (var ii=0;ii<frequencies["entropy"][d.x-1][2].length;ii+=1){
						tmp.push(["global",d.x+frequencies["entropy"][d.x-1][2][ii]]);
					}
					colorBy = "genotype";
					colorByGenotypePosition([d.x-1]);
					d3.select("#gt-color").property("value", d.x);
				}
		    },
		    onmouseover: function (d){
		    	document.body.style.cursor = "pointer";
		    },
		    onmouseout: function (d){
		    	document.body.style.cursor = "default";
		    },
			labels:{
				format:function (v, id, i, j){return i==1?id:'';},
			},
		},
		bar: {width: 2},
	    grid: {
    	    y: {
        	    lines: [{value: 0}]
        	}
    	},
	    tooltip: {
	        format: {
	            title: function (d) {
	            	return 'Position ' + d + frequencies["entropy"][d-1][2].join(","); },
	            value: function (value, ratio, id) {
	                return id==''?"Variability: "+value:"start/stop";
	            }
	        }
		},
	});

	d3.select("#plotfreq")
		.on("click", function (){
			gt = parse_gt_string(document.getElementById("gtspec").value);
			make_gt_chart(gt);
		});
	make_gt_chart(parse_gt_string(document.getElementById("gtspec").value));
});
<commit_msg>Still work when genome_annotation is absent.<commit_after>var frequencies, pivots;

/**
 * for each node, calculate the derivative of the frequency tranjectory. if none exists, copy parent
**/
function calcDfreq(node, freq_ii){
	if (typeof node.children != "undefined") {
		for (var i1=0; i1<node.children.length; i1++) {
			if (typeof node.children[i1].freq != "undefined") {
				if (node.children[i1].freq["global"] != "undefined"){
					var tmp_freq = node.children[i1].freq["global"]
					node.children[i1].dfreq = 0.5*(tmp_freq[freq_ii] - tmp_freq[freq_ii-dfreq_dn])/(tmp_freq[freq_ii] + tmp_freq[freq_ii-dfreq_dn] + 0.1);
				} else {
					node.children[i1].dfreq = node.dfreq;
				}
			}
			calcDfreq(node.children[i1], freq_ii);
		}
	}
};
function parse_gt_string(gt){
	mutations = [];
	gt.split(',').map( function (d) {
		var tmp = d.split(/[\s//]/); //FIXME: make more inclusive
		var region;
		var positions = [];
		for (var i=0; i<tmp.length; i++){
			if (contains(["EU","NA","AS","OC"], tmp[i])){
				region = tmp[i];
			}else{
				if (tmp[i].length>0) positions.push(tmp[i]);
			}
		}
		if (typeof region == "undefined") region="global";
		// sort of this is a multi mutation genotype
		if (positions.length>1){
			positions.sort(function (a,b){
				return parseInt(a.substring(0,a.length-1)) - parseInt(b.substring(0,b.length-1));
			});
		}
		mutations.push([region, positions.join('/')]);
	});
	return mutations;
};

/**
loops over all genotypes from a certain region and sums the frequency contributions
of the genotype matches at the specified positions
**/
function get_frequencies(region, gt){
	var freq = [];
	for (var pi=0; pi<pivots.length; pi++){freq[freq.length]=0;}
	if (frequencies["clades"][region][gt.toLowerCase()]!=undefined) {
		console.log(gt+" found as clade");
		for (var pi=0; pi<freq.length; pi++){
			freq[pi]+=frequencies["clades"][region][gt.toLowerCase()][pi];
		}
	}
	else if ((typeof frequencies["genotypes"] !="undefined") && (frequencies["genotypes"][region][gt]!=undefined)) {
		console.log(gt+" found as genotype");
		for (var pi=0; pi<freq.length; pi++){
			freq[pi]+=frequencies["genotypes"][region][gt][pi];
		}
	}else if (frequencies["mutations"][region][gt]!=undefined) {
		console.log(gt+" found as mutation");
		for (var pi=0; pi<freq.length; pi++){
			freq[pi]+=frequencies["mutations"][region][gt][pi];
		}
	}
	return freq.map(function (d) {return Math.round(d*100)/100;});
};

function make_gt_chart(gt){
	var tmp_data = [];
	var tmp_trace = ['x'];
	var tmp_colors = {};
	tmp_data.push(tmp_trace.concat(pivots));
	gt.forEach(function (d, i) {
		var region = d[0];
		var genotype = d[1];
		var freq = get_frequencies(region, genotype);
		if (d3.max(freq)>0) {
			var tmp_trace = genotype.toString().replace(/,/g, ', ');
			if (region != "global") {
				tmp_trace = region + ':\t' + tmp_trace;
			}
			tmp_data.push([tmp_trace].concat(freq));
			tmp_colors[tmp_trace] = genotypeColors[i];
		}
	});
	console.log(tmp_colors);
	gt_chart.load({
       	columns: tmp_data,
       	unload: true
	});
	gt_chart.data.colors(tmp_colors);
}

function addClade(d) {
	if (typeof gt_chart != "undefined"){
		var plot_data = [['x'].concat(rootNode["pivots"])];
		var reg = "global";
		if ((typeof d.target.freq !="undefined" )&&(d.target.freq[reg] != "undefined")){
			plot_data[plot_data.length] = [reg].concat(d.target.freq[reg]);
		}
		if (plot_data.length > 1) {
			if (plot_data[1][0] == "global") {
				plot_data[1][0] = "clade";
			}
		}
		gt_chart.load({
	       	columns: plot_data
		});
	}
}

function removeClade() {
	if (typeof gt_chart != "undefined"){
		gt_chart.unload({
	       	ids: ["clade"]
		});
	}
}

width = parseInt(d3.select(".freqplot-container").style("width"), 10);
height = 250;
var position = "inset";

var gt_chart = c3.generate({
	bindto: '#gtchart',
	size: {width: width-10, height: height},
	onresize: function() {
		width = parseInt(d3.select(".freqplot-container").style("width"), 10);
		height = 250;
		gt_chart.resize({height: height, width: width});
	},
	legend: {
		position: position,
		inset: {
    		anchor: 'top-right',
    		x: 10,
    		y: -15,
    		step: 1
    	}
	},
  	color: {
        pattern: genotypeColors
    },
	axis: {
		y: {
			label: {
				text: 'frequency',
				position: 'outer-middle'
			},
			tick: {
				values: [0.0, 0.2, 0.4, 0.6, 0.8, 1.0],
				outer: false
			},
            min: 0,
			max: 1
		},
		x: {
			label: {
				text: 'time',
				position: 'outer-center'
			},
			tick: {
				values: time_ticks,
				outer: false
			}
		}
	},
	data: {
		x: 'x',
		columns: [],
	}
});

function contains(arr, obj) {
    for(var i=0; i<arr.length; i++) {
        if (arr[i] == obj) return true;
    }
}

d3.json(path + file_prefix + "frequencies.json", function(error, json){
	console.log(error);
	frequencies = json;
	pivots= frequencies["mutations"]["global"]["pivots"].map(function (d) {return Math.round(parseFloat(d)*100)/100;});
	var ticks = [Math.round(pivots[0])];
	var tick_step = Math.round((pivots[pivots.length-1]-pivots[0])/6*10)/10;
	while (ticks[ticks.length-1]<pivots[pivots.length-1]){
		ticks.push(Math.round((ticks[ticks.length-1]+tick_step)*10)/10);
	}
	//gt_chart.axis.x.values = ticks;
	/**
		parses a genotype string into region and positions
	**/

	var chart_data = {'x':[], '':[]};
	for (var ii=0;ii<frequencies["entropy"].length;ii+=1){
		if (Math.round(10000*frequencies["entropy"][ii][1])/10000>0.05){
			chart_data[''].push(Math.round(10000*frequencies["entropy"][ii][1])/10000);
			chart_data['x'].push(ii+1);
		}
	}

	var chart_types = {'':'bar'}
	var chart_xaxis = {'':'x'}
	var ymin = 0;
	if (typeof genome_annotation !== 'undefined') {
		for (x in genome_annotation){
			chart_data['x'+x] = genome_annotation[x][1];
			chart_data[x] = genome_annotation[x][0].map(function(d) {return -0.1*d;});
			if (ymin>chart_data[x][0]){
				ymin = chart_data[x][0];
			}
			chart_types[x] = 'line';
			chart_xaxis[x] = 'x'+x;
		}
		ymin-=0.08;
	}
	console.log(chart_data);
	console.log(chart_types);
	console.log(chart_xaxis);
	var entropy_chart = c3.generate({
		bindto: '#entropy',
		size: {width: width-10, height: height},
		onresize: function() {
			width = parseInt(d3.select(".entropy-container").style("width"), 10);
			height = 250;
			entropy_chart.resize({height: height, width: width});
		},
		legend: {show: false},
		color: {pattern: ["#AAA"]},
		axis: {
			y: {
				label: {
					text: 'variability',
					position: 'outer-middle'
				},
				tick: {
					values: [0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6],
					outer: false
				},
				min:ymin,
			},
			x: {
				label: {
					text: 'position',
					position: 'outer-center'
				},
				tick: {
					outer: false,
					values: [100,200,300,400,500]
				}
			},
		},
		data: {
			xs: chart_xaxis,
			json: chart_data,
			types: chart_types,
			onclick: function (d,i) {
				console.log(d);
				if (frequencies["entropy"][d.x-1][2].length>1){
					var tmp = [];
					for (var ii=0;ii<frequencies["entropy"][d.x-1][2].length;ii+=1){
						tmp.push(["global",d.x+frequencies["entropy"][d.x-1][2][ii]]);
					}
					colorBy = "genotype";
					colorByGenotypePosition([d.x-1]);
					d3.select("#gt-color").property("value", d.x);
				}
		    },
		    onmouseover: function (d){
		    	document.body.style.cursor = "pointer";
		    },
		    onmouseout: function (d){
		    	document.body.style.cursor = "default";
		    },
			labels:{
				format:function (v, id, i, j){return i==1?id:'';},
			},
		},
		bar: {width: 2},
	    grid: {
    	    y: {
        	    lines: [{value: 0}]
        	}
    	},
	    tooltip: {
	        format: {
	            title: function (d) {
	            	return 'Position ' + d + frequencies["entropy"][d-1][2].join(","); },
	            value: function (value, ratio, id) {
	                return id==''?"Variability: "+value:"start/stop";
	            }
	        }
		},
	});

	d3.select("#plotfreq")
		.on("click", function (){
			gt = parse_gt_string(document.getElementById("gtspec").value);
			make_gt_chart(gt);
		});
	make_gt_chart(parse_gt_string(document.getElementById("gtspec").value));
});
<|endoftext|>


<commit_before>/**
 * Preload a collection of images (license : GPL v2)
 * @author Boris Schapira
 *
 * @param {(object|string[])} srcCollection - A collection of images
 * @param {function(object)=} callbackOne - A function callback that is called after each loading
 * @param {function((object|object[]))=} callbackAll - A function callback that is called after all the loading
 * @param {boolean} [sequential=false] - A boolean defining wheter to force the sequential loading. Default : false.
 *
 */
function preloadr(srcCollection, callbackOne, callbackAll, sequential) {

    sequential = typeof sequential !== 'undefined' ? sequential : false;

    var imgCollection = srcCollection instanceof Array ? [] : {};
    var srcIndexArray = [];
    for (var key in srcCollection) {
        srcIndexArray.push(key);
    }

    function onEvent(index) {
        return function () {
                    load(imgCollection[srcIndexArray[index]], (function () {
                        if (sequential && index < srcIndexArray.length - 1) {
                            return function () {
                                var newIndex = srcIndexArray[index + 1];
                                imgCollection[newIndex].src = srcCollection[newIndex];
                            };
                        } else {
                            return null;
                        }
                    })());
                };
    }

    function load(image, callback) {
        if (isFunctionCallbackOne) {
            callbackOne(image);
        }
        if (callback && 'function' === typeof callback) {
            callback();
        }
        if (++nbLoaded >= nbToLoad && 'function' === typeof callbackAll) {
            callbackAll(imgCollection);
        }
    }

    if (srcIndexArray.length) {
        var nbLoaded = 0,
            nbToLoad = 0;
        var isFunctionCallbackOne = 'function' === typeof callbackOne;
        for (var i = 0; i < srcIndexArray.length; i++) {

            nbToLoad++;
            imgCollection[srcIndexArray[i]] = new Image();
            imgCollection[srcIndexArray[i]].onload = imgCollection[srcIndexArray[i]].onerror = imgCollection[srcIndexArray[i]].onabort = onEvent(i);

            if (!sequential) {
                imgCollection[srcIndexArray[i]].src = srcCollection[srcIndexArray[i]].src;
                imgCollection[srcIndexArray[i]].props = srcCollection[srcIndexArray[i]].props;
            }
        }
        if (sequential) {
            imgCollection[srcIndexArray[0]].src = srcCollection[srcIndexArray[0]];
        }
    }
}<commit_msg>forgot to add props on sequential load<commit_after>/**
 * Preload a collection of images (license : GPL v2)
 * @author Boris Schapira
 *
 * @param {(object|string[])} srcCollection - A collection of images
 * @param {function(object)=} callbackOne - A function callback that is called after each loading
 * @param {function((object|object[]))=} callbackAll - A function callback that is called after all the loading
 * @param {boolean} [sequential=false] - A boolean defining wheter to force the sequential loading. Default : false.
 *
 */
function preloadr(srcCollection, callbackOne, callbackAll, sequential) {

    sequential = typeof sequential !== 'undefined' ? sequential : false;

    var imgCollection = srcCollection instanceof Array ? [] : {};
    var srcIndexArray = [];
    for (var key in srcCollection) {
        srcIndexArray.push(key);
    }

    function onEvent(index) {
        return function () {
                    load(imgCollection[srcIndexArray[index]], (function () {
                        if (sequential && index < srcIndexArray.length - 1) {
                            return function () {
                                var newIndex = srcIndexArray[index + 1];
                                imgCollection[newIndex].src = srcCollection[newIndex];
                            };
                        } else {
                            return null;
                        }
                    })());
                };
    }

    function load(image, callback) {
        if (isFunctionCallbackOne) {
            callbackOne(image);
        }
        if (callback && 'function' === typeof callback) {
            callback();
        }
        if (++nbLoaded >= nbToLoad && 'function' === typeof callbackAll) {
            callbackAll(imgCollection);
        }
    }

    if (srcIndexArray.length) {
        var nbLoaded = 0,
            nbToLoad = 0;
        var isFunctionCallbackOne = 'function' === typeof callbackOne;
        for (var i = 0; i < srcIndexArray.length; i++) {

            nbToLoad++;
            imgCollection[srcIndexArray[i]] = new Image();
            imgCollection[srcIndexArray[i]].onload = imgCollection[srcIndexArray[i]].onerror = imgCollection[srcIndexArray[i]].onabort = onEvent(i);

            if (!sequential) {
                imgCollection[srcIndexArray[i]].src = srcCollection[srcIndexArray[i]].src;
                imgCollection[srcIndexArray[i]].props = srcCollection[srcIndexArray[i]].props;
            }
        }
        if (sequential) {
            imgCollection[srcIndexArray[0]].src = srcCollection[srcIndexArray[0]];
			imgCollection[srcIndexArray[i]].props = srcCollection[srcIndexArray[i]].props;
        }
    }
}<|endoftext|>


<commit_before>//
// Created by Bradley Austin Davis on 2016/12/12
// Copyright 2013-2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/*global print, Resources, Test, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */
/*global ColorIndicator */

'use strict';

Script.include("../BenchmarkLib.js");
Resources.overrideUrlPrefix(TEST_ROOT, Script.resolvePath(".."));

var TRACE_TOOLBAR = "com.highfidelity.interface.toolbar.trace";
var TRACE_ICON = Script.resolvePath("../assets/traceButton.png");
var TRACE_NAME = "trace-{DATE}_{TIME}";
var TRACE_DURATION = 20;

var traceActive = false;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var button = tablet.addButton({
    icon: TRACE_ICON,
    activeIcon: TRACE_ICON,
    text: "toggleTrace",
    sortOrder: 1
});

function stopTrace() {
    if (!traceActive) {
        return;
    }
    traceActive = false;
    button.editProperties({isActive: traceActive});
    Test.stopTracing("traces/" + TRACE_NAME + ".json.gz");
}

function startTrace() {
    if (traceActive) {
        return;
    }
    var newTraceName = Window.prompt("Name of trace file", TRACE_NAME);
    if (!newTraceName) {
        return;
    }
    TRACE_NAME = newTraceName;

    var newTraceDuration = Window.prompt("Trace duration in seconds (0 for manual shutdown)", TRACE_DURATION);
    if (newTraceDuration == "") {
        return;
    }
    newTraceDuration = Number(newTraceDuration);
    if (isNaN(newTraceDuration)) {
        return;
    }

    if (newTraceDuration > 60) {
        Window.alert("Max trace time is 60 seconds");
        return;
    }

    TRACE_DURATION = newTraceDuration;
    traceActive = true;
    button.editProperties({isActive: traceActive});
    print("QQQ starting trace " + TRACE_NAME + " for " + TRACE_DURATION + " seconds");
    Test.startTracing(DEFAULT_TRACING_RULES);
    if (TRACE_DURATION > 0) {
        Script.setTimeout(function(){
            stopTrace();
        }, TRACE_DURATION * 1000);
    }
}

function traceToggle() {
    if (traceActive) {
        stopTrace();
    } else {
        startTrace();
    }
}

function onClicked() {
    traceToggle();
}

button.clicked.connect(onClicked);

print("QQQ trace script! done init");

TestScript.locationLoader("engine-dev.highfidelity.io",
							true,
							{ x: -19, y: -10, z: 7 },
							{ "x":0,"y":0.9652830362319946,"z":0,"w":-0.2612062096595764 })()<commit_msg>Specializing the details observed in spot500 benchmark<commit_after>//
// Created by Bradley Austin Davis on 2016/12/12
// Copyright 2013-2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/*global print, Resources, Test, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */
/*global ColorIndicator */

'use strict';

Script.include("../BenchmarkLib.js");
Resources.overrideUrlPrefix(TEST_ROOT, Script.resolvePath(".."));

SPOT500_TRACING_RULES = "" +
    "trace.*=true\n" +
    "*.detail=false\n" +
    "";

var TRACE_TOOLBAR = "com.highfidelity.interface.toolbar.trace";
var TRACE_ICON = Script.resolvePath("../assets/traceButton.png");
var TRACE_NAME = "trace-{DATE}_{TIME}";
var TRACE_DURATION = 20;

var traceActive = false;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var button = tablet.addButton({
    icon: TRACE_ICON,
    activeIcon: TRACE_ICON,
    text: "toggleTrace",
    sortOrder: 1
});

function stopTrace() {
    if (!traceActive) {
        return;
    }
    traceActive = false;
    button.editProperties({isActive: traceActive});
    Test.stopTracing("traces/" + TRACE_NAME + ".json.gz");
}

function startTrace() {
    if (traceActive) {
        return;
    }
    var newTraceName = Window.prompt("Name of trace file", TRACE_NAME);
    if (!newTraceName) {
        return;
    }
    TRACE_NAME = newTraceName;

    var newTraceDuration = Window.prompt("Trace duration in seconds (0 for manual shutdown)", TRACE_DURATION);
    if (newTraceDuration == "") {
        return;
    }
    newTraceDuration = Number(newTraceDuration);
    if (isNaN(newTraceDuration)) {
        return;
    }

    if (newTraceDuration > 60) {
        Window.alert("Max trace time is 60 seconds");
        return;
    }

    TRACE_DURATION = newTraceDuration;
    traceActive = true;
    button.editProperties({isActive: traceActive});
    print("QQQ starting trace " + TRACE_NAME + " for " + TRACE_DURATION + " seconds");
    Test.startTracing(SPOT500_TRACING_RULES);
    if (TRACE_DURATION > 0) {
        Script.setTimeout(function(){
            stopTrace();
        }, TRACE_DURATION * 1000);
    }
}

function traceToggle() {
    if (traceActive) {
        stopTrace();
    } else {
        startTrace();
    }
}

function onClicked() {
    traceToggle();
}

button.clicked.connect(onClicked);

print("QQQ trace script! done init");

TestScript.locationLoader("engine-dev.highfidelity.io",
							true,
							{ x: -19, y: -10, z: 7 },
							{ "x":0,"y":0.9652830362319946,"z":0,"w":-0.2612062096595764 })()<|endoftext|>


<commit_before>"use strict";
var VFindMode = {
  isActive: false,
  query: "",
  parsedQuery: "",
  partialQuery: "",
  historyIndex: 0,
  isRegex: false,
  ignoreCase: false,
  hasResults: false,
  matchCount: 0,
  scrollX: 0,
  scrollY: 0,
  initialRange: null,
  activeRegexIndex: 0,
  regexMatches: null,
  box: null,
  input: null,
  countEl: null,
  styleIn: null,
  options: null,
  cssSel: "::selection{background:#ff9632;}",
  cssIFrame: '*{font:normal normal normal 12px "Helvetica Neue",Helvetica,Arial,sans-serif !important;\
height:14px;line-height:12px;margin:0;overflow-y:hidden;vertical-align:top;white-space:nowrap;cursor:default;}\
body{cursor:text;display:inline-block;padding:0 3px 0 1px;min-width:7px;}body *{cursor:text;display:inline;}body br{display:none;}',
  activate: function(options) {
    if (!document.body) { return false; }
    options = Object.setPrototypeOf(options || {}, null);
    var query = options.query;
    if (this.isActive) {
      if (query != null) {
        this.findAndFocus(this.query || query, {dir: options.dir || 1, count: options.count || 1});
        return;
      }
      this.box.contentWindow.focus();
      this.input.focus();
      this.box.contentWindow.getSelection().selectAllChildren(this.input);
      return;
    }

    query !== this.query && Marks.setPreviousPosition();
    this.options = options;
    if (query != null) {
      this.findAndFocus(query, options);
      return;
    }
    this.init && this.init();
    this.scrollX = window.scrollX;
    this.scrollY = window.scrollY;
    this.parsedQuery = this.query = "";
    this.regexMatches = null;
    this.activeRegexIndex = 0;
    this.getCurrentRange();

    var el, wnd, doc;
    el = this.box = DomUtils.createElement("iframe");
    el.className = "R HUD";
    el.style.width = "0px";
    VHUD.box ? DomUtils.UI.root.insertBefore(el, VHUD.box) : DomUtils.UI.addElement(el);
    wnd = el.contentWindow;
    wnd.onmousedown = el.onmousedown = this.OnMousedown;
    wnd.onkeydown = this.onKeydown.bind(this);
    wnd.onfocus = VEventMode.on("WndFocus");
    doc = wnd.document;
    el = this.input = doc.body;
    el.contentEditable = "plaintext-only";
    el.oninput = this.onInput.bind(this);
    doc.documentElement.appendChild(this.countEl = doc.createElement("span"));

    el = DomUtils.UI.createStyle(this.cssIFrame, doc);
    doc.head.appendChild(el);
    doc.documentElement.insertBefore(new wnd.Text("/"), doc.body);

    DomUtils.UI.focus(this.input);
    this.isActive = true;
  },
  init: function() {
    var ref = this.postMode, UI = DomUtils.UI;
    ref.exit = ref.exit.bind(ref);
    this.styleIn = UI.createStyle(this.cssSel);
    UI.init && UI.init();
    UI.box.appendChild(UI.createStyle(".vimiumFindMode " + this.cssSel));
    this.init = null;
  },
  findAndFocus: function(query, options) {
    if (query !== this.query) {
      this.updateQuery(query);
      if (this.isActive) {
        this.input.textContent = query.replace(/^ /, '\xa0');
        this.showCount();
      }
    }
    this.init && this.init();
    var style = this.isActive || VHUD.opacity !== 1 ? null : VHUD.box.style;
    style && (style.visibility = "hidden");
    this.execute(null, options);
    style && (style.visibility = "");
    if (!this.hasResults) {
      this.isActive || VHUD.showForDuration("No matches for '" + this.query + "'", 1000);
      return;
    }
    this.focusFoundLink(window.getSelection().anchorNode);
    this.postMode.activate();
  },
  deactivate: function() { // need keep @hasResults
    this.checkReturnToViewPort();
    window.focus();
    var el = DomUtils.getSelectionFocusElement();
    el && el.focus();
    this.box.remove();
    this.box = this.input = this.countEl = this.options = null;
    this.styleIn.remove();
    this.partialQuery = this.parsedQuery = this.query = "";
    this.initialRange = this.regexMatches = null;
    this.historyIndex = this.matchCount = this.scrollY = this.scrollX = 0;
    this.isActive = false;
    return el;
  },
  OnMousedown: function(event) { if (event.target !== VFindMode.input) { event.preventDefault(); VFindMode.input.focus(); } },
  onKeydown: function(event) {
    var i = event.keyCode, n = i, el, el2;
    i = event.altKey ? 0 : i === KeyCodes.enter ? (this.saveQuery(), 2)
      : (i === KeyCodes.backspace || i === KeyCodes.deleteKey) ? +!this.query.length
      : 0;
    if (!i) {
      if (!KeyboardUtils.isPlain(event)) {
        if (event.shiftKey || !(event.ctrlKey || event.metaKey)) { return; }
        else if (n >= 74 && n <= 75) { this.execute(null, {dir: 74 - n }); }
      }
      else if (n === KeyCodes.f1) { this.box.contentDocument.execCommand("delete"); }
      else if (n === KeyCodes.f1 + 1) { window.focus(); }
      else if (n === KeyCodes.esc) { i = 3; }
      else if (n === KeyCodes.up || n === KeyCodes.down) { this.nextQuery(n === KeyCodes.up ? 1 : -1); }
      else { return; }
    }
    Utils.Prevent(event);
    if (!i) { return; }
    var hasStyle = !!this.styleIn.parentNode;
    el = this.deactivate();
    if (i < 2 || !this.hasResults) { return; }
    if (i === 3 && hasStyle) {
      this.toggleStyle("remove");
      this.restoreSelection(true);
    }
    if (!el || el !== VEventMode.lock()) {
      el = window.getSelection().anchorNode;
      if (el && !this.focusFoundLink(el) && i === 3 && (el2 = document.activeElement)) {
        DomUtils.getEditableType(el2) === 3 && el.contains(el2) && DomUtils.UI.simulateSelect(el2);
      }
    }
    i === 2 && this.postMode.activate();
  },
  focusFoundLink: function(el) {
    for (; el && el !== document.body; el = el.parentElement) {
      if (el instanceof HTMLAnchorElement) {
        el.focus();
        return true;
      }
    }
  },
  nextQuery: function(dir) {
    var ind = this.historyIndex + dir, query;
    if (ind === 1 && dir > 0) { this.partialQuery = this.query; }
    else if (ind < 1) { query = ind < 0 ? (ind = 0, this.query) : this.partialQuery; }
    this.historyIndex = ind;
    if (ind < 1) { this.SetQuery(query); return; }
    MainPort.sendMessage({ handler: "findQuery", index: ind }, this.SetQuery);
  },
  SetQuery: function(query) {
    var _this = VFindMode, sel;
    if (query === _this.query) { return; }
    if (!query && _this.historyIndex > 0) { --_this.historyIndex; return; }
    _this.input.textContent = query.replace(/^ /, '\xa0');
    sel = _this.box.contentWindow.getSelection();
    sel.selectAllChildren(_this.input);
    sel.collapseToEnd();
    _this.onInput();
  },
  saveQuery: function() {
    this.query && MainPort.port.postMessage({ handler: "findQuery", query: this.query });
  },
  postMode: {
    lock: null,
    activate: function() {
      var el = VEventMode.lock(), Exit = this.exit;
      if (!el || el === Vomnibar.input) { Exit(); return; }
      handlerStack.push(this.onKeydown, this);
      if (el === this.lock) { return; }
      if (!this.lock) {
        addEventListener("click", Exit, true);
        VEventMode.setupSuppress(Exit);
      }
      this.exit(true);
      this.lock = el;
      el.addEventListener("blur", Exit, true);
    },
    onKeydown: function(event) {
      var exit = event.keyCode === KeyCodes.esc && KeyboardUtils.isPlain(event);
      exit ? this.exit() : handlerStack.remove(this);
      return 2 * exit;
    },
    exit: function(skip) {
      this.lock && this.lock.removeEventListener("blur", this.exit, true);
      if (!this.lock || skip === true) { return; }
      this.lock = null;
      removeEventListener("click", this.exit, true);
      handlerStack.remove(this);
      VEventMode.exitSuppress();
    }
  },
  onInput: function() {
    var query = this.input.textContent.replace('\xa0', " "), count;
    this.checkReturnToViewPort();
    this.updateQuery(query);
    this.restoreSelection();
    this.execute(!this.isRegex ? this.parsedQuery : this.regexMatches ? this.regexMatches[0] : "");
    this.showCount();
  },
  showCount: function() {
    var count = this.matchCount;
    this.countEl.textContent = this.parsedQuery ? "(" + (count || (this.hasResults ? "Some" : "No")) + " match" + (count !== 1 ? "es)" : ")") : "";
    count = this.input.getBoundingClientRect().width + this.countEl.getBoundingClientRect().width;
    this.box.style.width = (count | 0) + 4 + "px";
  },
  checkReturnToViewPort: function() {
    this.options.returnToViewport && window.scrollTo(this.scrollX, this.scrollY);
  },
  _ctrlRe: /(\\\\?)([rRI]?)/g,
  escapeAllRe: /[\$\(\)\*\+\.\?\[\\\]\^\{\|\}]/g,
  updateQuery: function(query) {
    this.query = query;
    this.isRegex = this.options.isRegex;
    this.hasNoIgnoreCaseFlag = false;
    query = this.parsedQuery = query.replace(this._ctrlRe, this.FormatQuery);
    this.ignoreCase = !this.hasNoIgnoreCaseFlag && !/[A-Z]/.test(query);
    this.isRegex || (query = this.isActive && query.replace(this.escapeAllRe, "\\$&"));

    var re, matches;
    if (query) {
      try { re = new RegExp(query, this.ignoreCase ? "gi" : "g"); } catch (e) {}
    }
    matches = re && (document.webkitFullscreenElement || document.documentElement).innerText.match(re);
    this.regexMatches = this.isRegex && matches || null;
    this.activeRegexIndex = 0;
    this.matchCount = matches ? matches.length : 0;
  },
  FormatQuery: function(match, slashes, flag) {
    if (!flag || slashes.length != 1) { return match; }
    if (flag === 'I') { VFindMode.hasNoIgnoreCaseFlag = true; }
    else { VFindMode.isRegex = flag === 'r'; }
    return "";
  },
  restoreSelection: function(isCur) {
    var sel = window.getSelection(), range;
    range = !isCur ? this.initialRange : sel.isCollapsed ? null : sel.getRangeAt(0);
    if (!range) { return; }
    sel.removeAllRanges()
    sel.addRange(range);
  },
  getNextQueryFromRegexMatches: function(dir) {
    if (!this.regexMatches) { return ""; }
    var count = this.matchCount;
    this.activeRegexIndex = count = (this.activeRegexIndex + dir + count) % count;
    return this.regexMatches[count];
  },
  execute: function(query, options) {
    options || (options = {});
    var el, found, count = options.count | 0, dir = options.dir || 1, q;
    options.noColor || this.toggleStyle('add');
    do {
      q = query != null ? query : this.isRegex ? this.getNextQueryFromRegexMatches(dir) : this.parsedQuery;
      found = window.find(q, options.caseSensitive || !this.ignoreCase, dir < 0, true, false, true, false);
    } while (0 < --count && found);
    options.noColor || setTimeout(this.hookSel.bind(this, "add"), 0);
    (el = VEventMode.lock()) && DomUtils.getEditableType(el) > 1 && !DomUtils.isSelected(document.activeElement) && el.blur();
    return this.hasResults = found;
  },
  RestoreHighlight: function() { VFindMode.toggleStyle('remove'); },
  hookSel: function(action) { document[action + "EventListener"]("selectionchange", this.RestoreHighlight, true); },
  toggleStyle: function(action) {
    this.hookSel("remove");
    document.documentElement.classList[action]("vimiumFindMode");
    action !== "add" ? this.styleIn && this.styleIn.remove() :
    DomUtils.UI.root && DomUtils.UI.addElement(this.styleIn);
  },
  getCurrentRange: function() {
    var sel = window.getSelection(), range;
    if (sel.type == "None") {
      range = this.initialRange = document.createRange();
      range.setStart(document.body, 0);
      range.setEnd(document.body, 0);
    } else {
      sel.type == "Range" && sel.collapseToStart();
      this.initialRange = sel.getRangeAt(0);
    }
  }
};
<commit_msg>VFindMode: clean selection listener on exit if only esc or not @hasResults<commit_after>"use strict";
var VFindMode = {
  isActive: false,
  query: "",
  parsedQuery: "",
  partialQuery: "",
  historyIndex: 0,
  isRegex: false,
  ignoreCase: false,
  hasResults: false,
  matchCount: 0,
  scrollX: 0,
  scrollY: 0,
  initialRange: null,
  activeRegexIndex: 0,
  regexMatches: null,
  box: null,
  input: null,
  countEl: null,
  styleIn: null,
  options: null,
  cssSel: "::selection{background:#ff9632;}",
  cssIFrame: '*{font:normal normal normal 12px "Helvetica Neue",Helvetica,Arial,sans-serif !important;\
height:14px;line-height:12px;margin:0;overflow-y:hidden;vertical-align:top;white-space:nowrap;cursor:default;}\
body{cursor:text;display:inline-block;padding:0 3px 0 1px;min-width:7px;}body *{cursor:text;display:inline;}body br{display:none;}',
  activate: function(options) {
    if (!document.body) { return false; }
    options = Object.setPrototypeOf(options || {}, null);
    var query = options.query;
    if (this.isActive) {
      if (query != null) {
        this.findAndFocus(this.query || query, {dir: options.dir || 1, count: options.count || 1});
        return;
      }
      this.box.contentWindow.focus();
      this.input.focus();
      this.box.contentWindow.getSelection().selectAllChildren(this.input);
      return;
    }

    query !== this.query && Marks.setPreviousPosition();
    this.options = options;
    if (query != null) {
      this.findAndFocus(query, options);
      return;
    }
    this.init && this.init();
    this.scrollX = window.scrollX;
    this.scrollY = window.scrollY;
    this.parsedQuery = this.query = "";
    this.regexMatches = null;
    this.activeRegexIndex = 0;
    this.getCurrentRange();

    var el, wnd, doc;
    el = this.box = DomUtils.createElement("iframe");
    el.className = "R HUD";
    el.style.width = "0px";
    VHUD.box ? DomUtils.UI.root.insertBefore(el, VHUD.box) : DomUtils.UI.addElement(el);
    wnd = el.contentWindow;
    wnd.onmousedown = el.onmousedown = this.OnMousedown;
    wnd.onkeydown = this.onKeydown.bind(this);
    wnd.onfocus = VEventMode.on("WndFocus");
    doc = wnd.document;
    el = this.input = doc.body;
    el.contentEditable = "plaintext-only";
    el.oninput = this.onInput.bind(this);
    doc.documentElement.appendChild(this.countEl = doc.createElement("span"));

    el = DomUtils.UI.createStyle(this.cssIFrame, doc);
    doc.head.appendChild(el);
    doc.documentElement.insertBefore(new wnd.Text("/"), doc.body);

    DomUtils.UI.focus(this.input);
    this.isActive = true;
  },
  init: function() {
    var ref = this.postMode, UI = DomUtils.UI;
    ref.exit = ref.exit.bind(ref);
    this.styleIn = UI.createStyle(this.cssSel);
    UI.init && UI.init();
    UI.box.appendChild(UI.createStyle(".vimiumFindMode " + this.cssSel));
    this.init = null;
  },
  findAndFocus: function(query, options) {
    if (query !== this.query) {
      this.updateQuery(query);
      if (this.isActive) {
        this.input.textContent = query.replace(/^ /, '\xa0');
        this.showCount();
      }
    }
    this.init && this.init();
    var style = this.isActive || VHUD.opacity !== 1 ? null : VHUD.box.style;
    style && (style.visibility = "hidden");
    this.execute(null, options);
    style && (style.visibility = "");
    if (!this.hasResults) {
      this.isActive || VHUD.showForDuration("No matches for '" + this.query + "'", 1000);
      return;
    }
    this.focusFoundLink(window.getSelection().anchorNode);
    this.postMode.activate();
  },
  deactivate: function() { // need keep @hasResults
    this.checkReturnToViewPort();
    window.focus();
    var el = DomUtils.getSelectionFocusElement();
    el && el.focus();
    this.box.remove();
    this.box = this.input = this.countEl = this.options = null;
    this.styleIn.remove();
    this.partialQuery = this.parsedQuery = this.query = "";
    this.initialRange = this.regexMatches = null;
    this.historyIndex = this.matchCount = this.scrollY = this.scrollX = 0;
    this.isActive = false;
    return el;
  },
  OnMousedown: function(event) { if (event.target !== VFindMode.input) { event.preventDefault(); VFindMode.input.focus(); } },
  onKeydown: function(event) {
    var i = event.keyCode, n = i, el, el2;
    i = event.altKey ? 0 : i === KeyCodes.enter ? (this.saveQuery(), 2)
      : (i === KeyCodes.backspace || i === KeyCodes.deleteKey) ? +!this.query.length
      : 0;
    if (!i) {
      if (!KeyboardUtils.isPlain(event)) {
        if (event.shiftKey || !(event.ctrlKey || event.metaKey)) { return; }
        else if (n >= 74 && n <= 75) { this.execute(null, {dir: 74 - n }); }
      }
      else if (n === KeyCodes.f1) { this.box.contentDocument.execCommand("delete"); }
      else if (n === KeyCodes.f1 + 1) { window.focus(); }
      else if (n === KeyCodes.esc) { i = 3; }
      else if (n === KeyCodes.up || n === KeyCodes.down) { this.nextQuery(n === KeyCodes.up ? 1 : -1); }
      else { return; }
    }
    Utils.Prevent(event);
    if (!i) { return; }
    var hasStyle = !!this.styleIn.parentNode;
    el = this.deactivate();
    if ((i === 3 || !this.hasResults) && hasStyle) {
      this.toggleStyle("remove");
      this.restoreSelection(true);
    }
    if (i < 2 || !this.hasResults) { return; }
    if (!el || el !== VEventMode.lock()) {
      el = window.getSelection().anchorNode;
      if (el && !this.focusFoundLink(el) && i === 3 && (el2 = document.activeElement)) {
        DomUtils.getEditableType(el2) === 3 && el.contains(el2) && DomUtils.UI.simulateSelect(el2);
      }
    }
    i === 2 && this.postMode.activate();
  },
  focusFoundLink: function(el) {
    for (; el && el !== document.body; el = el.parentElement) {
      if (el instanceof HTMLAnchorElement) {
        el.focus();
        return true;
      }
    }
  },
  nextQuery: function(dir) {
    var ind = this.historyIndex + dir, query;
    if (ind === 1 && dir > 0) { this.partialQuery = this.query; }
    else if (ind < 1) { query = ind < 0 ? (ind = 0, this.query) : this.partialQuery; }
    this.historyIndex = ind;
    if (ind < 1) { this.SetQuery(query); return; }
    MainPort.sendMessage({ handler: "findQuery", index: ind }, this.SetQuery);
  },
  SetQuery: function(query) {
    var _this = VFindMode, sel;
    if (query === _this.query) { return; }
    if (!query && _this.historyIndex > 0) { --_this.historyIndex; return; }
    _this.input.textContent = query.replace(/^ /, '\xa0');
    sel = _this.box.contentWindow.getSelection();
    sel.selectAllChildren(_this.input);
    sel.collapseToEnd();
    _this.onInput();
  },
  saveQuery: function() {
    this.query && MainPort.port.postMessage({ handler: "findQuery", query: this.query });
  },
  postMode: {
    lock: null,
    activate: function() {
      var el = VEventMode.lock(), Exit = this.exit;
      if (!el || el === Vomnibar.input) { Exit(); return; }
      handlerStack.push(this.onKeydown, this);
      if (el === this.lock) { return; }
      if (!this.lock) {
        addEventListener("click", Exit, true);
        VEventMode.setupSuppress(Exit);
      }
      this.exit(true);
      this.lock = el;
      el.addEventListener("blur", Exit, true);
    },
    onKeydown: function(event) {
      var exit = event.keyCode === KeyCodes.esc && KeyboardUtils.isPlain(event);
      exit ? this.exit() : handlerStack.remove(this);
      return 2 * exit;
    },
    exit: function(skip) {
      this.lock && this.lock.removeEventListener("blur", this.exit, true);
      if (!this.lock || skip === true) { return; }
      this.lock = null;
      removeEventListener("click", this.exit, true);
      handlerStack.remove(this);
      VEventMode.exitSuppress();
    }
  },
  onInput: function() {
    var query = this.input.textContent.replace('\xa0', " "), count;
    this.checkReturnToViewPort();
    this.updateQuery(query);
    this.restoreSelection();
    this.execute(!this.isRegex ? this.parsedQuery : this.regexMatches ? this.regexMatches[0] : "");
    this.showCount();
  },
  showCount: function() {
    var count = this.matchCount;
    this.countEl.textContent = this.parsedQuery ? "(" + (count || (this.hasResults ? "Some" : "No")) + " match" + (count !== 1 ? "es)" : ")") : "";
    count = this.input.getBoundingClientRect().width + this.countEl.getBoundingClientRect().width;
    this.box.style.width = (count | 0) + 4 + "px";
  },
  checkReturnToViewPort: function() {
    this.options.returnToViewport && window.scrollTo(this.scrollX, this.scrollY);
  },
  _ctrlRe: /(\\\\?)([rRI]?)/g,
  escapeAllRe: /[\$\(\)\*\+\.\?\[\\\]\^\{\|\}]/g,
  updateQuery: function(query) {
    this.query = query;
    this.isRegex = this.options.isRegex;
    this.hasNoIgnoreCaseFlag = false;
    query = this.parsedQuery = query.replace(this._ctrlRe, this.FormatQuery);
    this.ignoreCase = !this.hasNoIgnoreCaseFlag && !/[A-Z]/.test(query);
    this.isRegex || (query = this.isActive && query.replace(this.escapeAllRe, "\\$&"));

    var re, matches;
    if (query) {
      try { re = new RegExp(query, this.ignoreCase ? "gi" : "g"); } catch (e) {}
    }
    matches = re && (document.webkitFullscreenElement || document.documentElement).innerText.match(re);
    this.regexMatches = this.isRegex && matches || null;
    this.activeRegexIndex = 0;
    this.matchCount = matches ? matches.length : 0;
  },
  FormatQuery: function(match, slashes, flag) {
    if (!flag || slashes.length != 1) { return match; }
    if (flag === 'I') { VFindMode.hasNoIgnoreCaseFlag = true; }
    else { VFindMode.isRegex = flag === 'r'; }
    return "";
  },
  restoreSelection: function(isCur) {
    var sel = window.getSelection(), range;
    range = !isCur ? this.initialRange : sel.isCollapsed ? null : sel.getRangeAt(0);
    if (!range) { return; }
    sel.removeAllRanges()
    sel.addRange(range);
  },
  getNextQueryFromRegexMatches: function(dir) {
    if (!this.regexMatches) { return ""; }
    var count = this.matchCount;
    this.activeRegexIndex = count = (this.activeRegexIndex + dir + count) % count;
    return this.regexMatches[count];
  },
  execute: function(query, options) {
    options || (options = {});
    var el, found, count = options.count | 0, dir = options.dir || 1, q;
    options.noColor || this.toggleStyle('add');
    do {
      q = query != null ? query : this.isRegex ? this.getNextQueryFromRegexMatches(dir) : this.parsedQuery;
      found = window.find(q, options.caseSensitive || !this.ignoreCase, dir < 0, true, false, true, false);
    } while (0 < --count && found);
    options.noColor || setTimeout(this.hookSel.bind(this, "add"), 0);
    (el = VEventMode.lock()) && DomUtils.getEditableType(el) > 1 && !DomUtils.isSelected(document.activeElement) && el.blur();
    return this.hasResults = found;
  },
  RestoreHighlight: function() { VFindMode.toggleStyle('remove'); },
  hookSel: function(action) { document[action + "EventListener"]("selectionchange", this.RestoreHighlight, true); },
  toggleStyle: function(action) {
    this.hookSel("remove");
    document.documentElement.classList[action]("vimiumFindMode");
    action !== "add" ? this.styleIn && this.styleIn.remove() :
    DomUtils.UI.root && DomUtils.UI.addElement(this.styleIn);
  },
  getCurrentRange: function() {
    var sel = window.getSelection(), range;
    if (sel.type == "None") {
      range = this.initialRange = document.createRange();
      range.setStart(document.body, 0);
      range.setEnd(document.body, 0);
    } else {
      sel.type == "Range" && sel.collapseToStart();
      this.initialRange = sel.getRangeAt(0);
    }
  }
};
<|endoftext|>


<commit_before>"use strict";

import React from "react";

import classNames from "classnames";

import Icon from "./Icon.js";
import StatusView from "./Status.js";
import PlayerKeyView from "./PlayerKey.js";

import ContainerActions from "../actions/ContainerActions.js";
import ContainerConstants from "../constants/ContainerConstants.js";
import ContainerStore from "../stores/ContainerStore.js";

import LeftColumnActions from "../actions/LeftColumnActions.js";
import LeftColumnStore from "../stores/LeftColumnStore.js";

function getToolBarItemState(mode) {
  return {selected: mode === ContainerStore.getMode()};
}

class ToolbarItem extends React.Component {
  constructor(props) {
    super(props);

    this.state = getToolBarItemState(this.props.mode);
    this._onClick = this._onClick.bind(this);
    this._onChange = this._onChange.bind(this);
  }

  componentDidMount() {
    ContainerStore.addChangeListener(this._onChange);
    LeftColumnStore.addChangeListener(this._onChange);
  }

  componentWillUnmount() {
    ContainerStore.removeChangeListener(this._onChange);
    LeftColumnStore.removeChangeListener(this._onChange);
  }

  render() {
    var {...other} = this.props;
    var classes = {
      "menu-item": true,
      selected: this.state.selected,
    };
    return (

        <Icon {...other} />
        {this.props.title}

    );
  }

  _onClick() {
    ContainerActions.mode(this.props.mode);
  }

  _onChange() {
    this.setState(getToolBarItemState(this.props.mode));
  }
}

class LinkItem extends React.Component {
  render() {
    return (

          <Icon icon={this.props.icon} fa={true} />

        {this.props.title}

    );
  }
}

function leftColumnState() {
  return {
    mode: ContainerStore.getMode(),
    hidden: LeftColumnStore.getIsHidden(),
  };
}

export default class LeftColumn extends React.Component {
  constructor(props) {
    super(props);

    this.state = leftColumnState();
    this._onChange = this._onChange.bind(this);
    this._onClickMenuToggle = this._onClickMenuToggle.bind(this);
  }

  componentDidMount() {
    ContainerStore.addChangeListener(this._onChange);
    LeftColumnStore.addChangeListener(this._onChange);
  }

  componentWillUnmount() {
    ContainerStore.removeChangeListener(this._onChange);
    LeftColumnStore.removeChangeListener(this._onChange);
  }

  render() {
    var classes = classNames("control-bar", {hidden: this.state.hidden});
    return (

            <ToolbarItem mode={ContainerConstants.ALL} icon="align-justify" title="All" />
            <ToolbarItem mode={ContainerConstants.ARTISTS} icon="list" title="Artists" />
            <ToolbarItem mode={ContainerConstants.COVERS} icon="th-large" title="Covers" />
            <ToolbarItem mode={ContainerConstants.RECENT} icon="time" title="Recently Added" />
            <ToolbarItem mode={ContainerConstants.RETRO} icon="cd" title="Retro" />
            <ToolbarItem mode={ContainerConstants.SETTINGS} icon="cog" title="Settings" />

            <LinkItem title="Github" href="https://github.com/tchaik/tchaik" icon="github" />

<StatusView />

<PlayerKeyView />

    );
  }

  _onChange() {
    this.setState(leftColumnState());
  }

  _onClickMenuToggle() {
    LeftColumnActions.toggleVisibility();
  }
}
<commit_msg>Rename All -> Library and use headphones icon.<commit_after>"use strict";

import React from "react";

import classNames from "classnames";

import Icon from "./Icon.js";
import StatusView from "./Status.js";
import PlayerKeyView from "./PlayerKey.js";

import ContainerActions from "../actions/ContainerActions.js";
import ContainerConstants from "../constants/ContainerConstants.js";
import ContainerStore from "../stores/ContainerStore.js";

import LeftColumnActions from "../actions/LeftColumnActions.js";
import LeftColumnStore from "../stores/LeftColumnStore.js";

function getToolBarItemState(mode) {
  return {selected: mode === ContainerStore.getMode()};
}

class ToolbarItem extends React.Component {
  constructor(props) {
    super(props);

    this.state = getToolBarItemState(this.props.mode);
    this._onClick = this._onClick.bind(this);
    this._onChange = this._onChange.bind(this);
  }

  componentDidMount() {
    ContainerStore.addChangeListener(this._onChange);
    LeftColumnStore.addChangeListener(this._onChange);
  }

  componentWillUnmount() {
    ContainerStore.removeChangeListener(this._onChange);
    LeftColumnStore.removeChangeListener(this._onChange);
  }

  render() {
    var {...other} = this.props;
    var classes = {
      "menu-item": true,
      selected: this.state.selected,
    };
    return (

        <Icon {...other} />
        {this.props.title}

    );
  }

  _onClick() {
    ContainerActions.mode(this.props.mode);
  }

  _onChange() {
    this.setState(getToolBarItemState(this.props.mode));
  }
}

class LinkItem extends React.Component {
  render() {
    return (

          <Icon icon={this.props.icon} fa={true} />

        {this.props.title}

    );
  }
}

function leftColumnState() {
  return {
    mode: ContainerStore.getMode(),
    hidden: LeftColumnStore.getIsHidden(),
  };
}

export default class LeftColumn extends React.Component {
  constructor(props) {
    super(props);

    this.state = leftColumnState();
    this._onChange = this._onChange.bind(this);
    this._onClickMenuToggle = this._onClickMenuToggle.bind(this);
  }

  componentDidMount() {
    ContainerStore.addChangeListener(this._onChange);
    LeftColumnStore.addChangeListener(this._onChange);
  }

  componentWillUnmount() {
    ContainerStore.removeChangeListener(this._onChange);
    LeftColumnStore.removeChangeListener(this._onChange);
  }

  render() {
    var classes = classNames("control-bar", {hidden: this.state.hidden});
    return (

            <ToolbarItem mode={ContainerConstants.ALL} icon="headphones" title="Library" />
            <ToolbarItem mode={ContainerConstants.ARTISTS} icon="list" title="Artists" />
            <ToolbarItem mode={ContainerConstants.COVERS} icon="th-large" title="Covers" />
            <ToolbarItem mode={ContainerConstants.RECENT} icon="time" title="Recently Added" />
            <ToolbarItem mode={ContainerConstants.RETRO} icon="cd" title="Retro" />
            <ToolbarItem mode={ContainerConstants.SETTINGS} icon="cog" title="Settings" />

            <LinkItem title="Github" href="https://github.com/tchaik/tchaik" icon="github" />

<StatusView />

<PlayerKeyView />

    );
  }

  _onChange() {
    this.setState(leftColumnState());
  }

  _onClickMenuToggle() {
    LeftColumnActions.toggleVisibility();
  }
}
<|endoftext|>