<commit_before>// Copyright 2013 Timothy J Fontaine <tjfontaine@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE

var stream = require('stream');
var util = require('util');

if (!stream.Transform)
  stream = require('readable-stream');

var LineStream = module.exports = function LineStream(opts) {
  if (!(this instanceof LineStream)) return new LineStream(opts);
  opts = opts || {};
  opts.objectMode = true;
  stream.Transform.call(this, opts);
  this._buff = '';
};
util.inherits(LineStream, stream.Transform);

LineStream.prototype._transform = function(chunk, encoding, done) {
  var data = this._buff + chunk.toString('utf8');
  var lines = data.split(/\r?\n|\r(?!\n)/);

  if (!data.match(/(\r?\n|\r(?!\n))$/))
    this._buff = lines.pop();
  else
    this._buff = '';

  var self = this;

  lines.forEach(function (line) {
    self._line(line);
  });

  done();
};

LineStream.prototype._flush = function(done) {
  if (this._buff) this._line(this._buff);
  done();
};

LineStream.prototype._line = function(line) {
  this.push(line);
  this.emit('line', line);
};
<commit_msg>don't emit extra new line<commit_after>// Copyright 2013 Timothy J Fontaine <tjfontaine@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE

var stream = require('stream');
var util = require('util');

if (!stream.Transform)
  stream = require('readable-stream');

var LineStream = module.exports = function LineStream(opts) {
  if (!(this instanceof LineStream)) return new LineStream(opts);
  opts = opts || {};
  opts.objectMode = true;
  stream.Transform.call(this, opts);
  this._buff = '';
};
util.inherits(LineStream, stream.Transform);

LineStream.prototype._transform = function(chunk, encoding, done) {
  var data = this._buff + chunk.toString('utf8');
  var lines = data.split(/\r?\n|\r(?!\n)/);

  this._buff = lines.pop();

  var self = this;

  lines.forEach(function (line) {
    self._line(line);
  });

  done();
};

LineStream.prototype._flush = function(done) {
  if (this._buff) this._line(this._buff);
  done();
};

LineStream.prototype._line = function(line) {
  this.push(line);
  this.emit('line', line);
};
<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore');

var ucfirst = function (property) {
	return property.charAt(0).toUpperCase() + property.substr(1, property.length - 1);
};

/**
 * @param {Object} data
 * @constructor
 */
var AbstractEntity = function (data) {
	if (!this.__init) {
		this.__init = true;
		return;
	}
	if (_(data).isObject()) {
		this.set(data);
	}
};

/**
 * @lends AbstractEntity
 */
AbstractEntity.prototype = {

	/**
	 * @private
	 */
	init: function () {},

	/**
	 * @param {String|Object} key
	 * @param {*|undefined} value
	 * @returns {AbstractEntity}
	 */
	set: function (key, value) {
		var data;

		if (_.isUndefined(value)) {
			data = key;
			if (!_.isObject(data)) {
				throw new Error('Data must be an object');
			}
		} else {
			data = {};
			data[key] = value;
		}

		_.each(_.keys(data), function (property) {

			var setter;
			if (!_.has(this, property)) {
				throw new Error('Trying to set non-existing property: ' + this.namespace + '.' + property);
			}

			if (this.validate(property, data[property])) {
				setter = 'set' + ucfirst(property);
				if (_.isFunction(this[setter])) {
					this[setter](data[property]);
				} else {
					this[property] = data[property];
				}
			} else {
				throw new Error('Value ' + data[property] + ' is not valid for ' + property);
			}

		}, this);

		return this;
	},

	/**
	 * @param {String} key
	 * @param {*} value
	 * @returns {AbstractEntity}
	 */
	push: function (key, value) {
		var old;
		if (!_.isArray(this[key])) {
			throw new Error('Property must be an array');
		}
		old = this.get(key);
		old.push(value);

		return this.set(key, old);
	},

	/**
	 * @param {String} property
	 * @returns {*}
	 */
	get: function (property) {

		var data, getter;

		if (_.isUndefined(property)) {

			data = {};
			_.each(_.keys(this), function (property) {
				if (!_.isFunction(this[property])) {
					data[property] = this[property];
				}
			}, this);

		} else {

			if (!_.has(this, property) || _.isFunction(this[property])) {
				throw new Error('Trying to access non-existing property: ' + this.namespace + '.' + property);
			}

			getter = 'get' + ucfirst(property);
			if (_.isFunction(this[getter])) {
				data = this[getter](property);
			} else {
				data = this[property];
			}

		}

		return data;
	},

	/**
	 *
	 * @private
	 * @param {String} property
	 * @param {*} value
	 * @returns {boolean}
	 */
	validate: function (property, value) {
		var validator, isValid = true;
		validator = 'validate' + ucfirst(property);
		if (_.isFunction(this[validator])) {
			isValid = this[validator](value);
		}
		return isValid;
	},

	toJSON: function () {
		var data = this.get();
		data.__ns = this.namespace;
		return data;
	}

};

exports.AbstractEntity = AbstractEntity;<commit_msg>Data setter refactored: data is validated first and only then assigned to entity, that allows to validate empty properties<commit_after>'use strict';

var _ = require('underscore');

function ucfirst(property) {
	return property.charAt(0).toUpperCase() + property.substr(1, property.length - 1);
}

/**
 * @param {Object} data
 * @constructor
 */
var AbstractEntity = function (data) {
	if (!this.__init) {
		this.__init = true;
		return;
	}
	if (_(data).isObject()) {
		this.set(data);
	}
};

/**
 * @lends AbstractEntity
 */
AbstractEntity.prototype = {

	/**
	 * @private
	 */
	init: function () {
	},

	/**
	 * @param {String|Object} key
	 * @param {*|undefined} value
	 * @returns {AbstractEntity}
	 */
	set: function (key, value) {
		var data;

		if (_.isUndefined(value)) {
			data = key;
			if (!_.isObject(data)) {
				throw new Error('Data must be an object');
			}
		} else {
			data = {};
			data[key] = value;
		}

		// Validate data
		_.each(_.keys(this.get()), function (property) {
			if (!this.validate(property, data[property])) {
				throw new Error('Value [' + data[property] + '] is not valid for [' + this.namespace + '.' + property + ']');
			}
		}, this);

		// Set data
		_.each(_.keys(data), function (property) {

			if (!_.has(this, property)) {
				throw new Error('Trying to set non-existing property [' + this.namespace + '.' + property + ']');
			}

			var setter = 'set' + ucfirst(property);
			if (_.isFunction(this[setter])) {
				this[setter](data[property]);
			} else {
				this[property] = data[property];
			}

		}, this);

		return this;
	},

	/**
	 * @param {String} key
	 * @param {*} value
	 * @returns {AbstractEntity}
	 */
	push: function (key, value) {
		var old;
		if (!_.isArray(this[key])) {
			throw new Error('Property must be an array');
		}
		old = this.get(key);
		old.push(value);

		return this.set(key, old);
	},

	/**
	 * @param {String} property
	 * @returns {*}
	 */
	get: function (property) {

		var data, getter;

		if (_.isUndefined(property)) {

			data = {};
			_.each(_.keys(this), function (property) {
				if (!_.isFunction(this[property])) {
					data[property] = this[property];
				}
			}, this);

		} else {

			if (!_.has(this, property) || _.isFunction(this[property])) {
				throw new Error('Trying to access non-existing property: ' + this.namespace + '.' + property);
			}

			getter = 'get' + ucfirst(property);
			if (_.isFunction(this[getter])) {
				data = this[getter](property);
			} else {
				data = this[property];
			}

		}

		return data;
	},

	/**
	 *
	 * @private
	 * @param {String} property
	 * @param {*} value
	 * @returns {boolean}
	 */
	validate: function (property, value) {
		var validator, isValid = true;
		validator = 'validate' + ucfirst(property);
		if (_.isFunction(this[validator])) {
			isValid = this[validator](value);
		}
		return isValid;
	},

	toJSON: function () {
		var data = this.get();
		data.__ns = this.namespace;
		return data;
	}

};

exports.AbstractEntity = AbstractEntity;<|endoftext|>


<commit_before>/*
** Module dependencies
*/
var _s = require('underscore.string');
var _ = require('lodash');
var ComputingError = require('./errors').ComputingError;

/*
** Entity
*/
function Entity(options) {
    this.id = options.id;
    this.situation = options.situation;
    this.userAttributes = {};
    this.computedAttributes = {};
}

/*
** Prototype
*/
Entity.prototype.setUserAttribute = function(name, value) {
    this.userAttributes[name] = value;
};

Entity.prototype.getUserAttribute = function(name) {
    return this.userAttributes[name];
};

Entity.prototype.hasUserAttribute = function(name) {
    return name in this.userAttributes;
};

Entity.prototype.setComputedAttribute = function(name, value) {
    this.computedAttributes[name] = value;
};

Entity.prototype.getComputedAttribute = function(name) {
    return this.computedAttributes[name];
};

Entity.prototype.hasComputedAttribute = function(name) {
    return name in this.computedAttributes;
};

Entity.prototype.set = function(name, value) {
    // Batch set
    if (_.isObject(name)) {
        _.forEach(name, function(value, name) {
            this.set(name, value);
        }, this);
        return this;
    }

    // Step 1: use build-in accessor
    var setterName = 'set' + _s.capitalize(name);
    if ((setterName in this) && _.isFunction(this[setterName])) this[setterName](value);
    // Step 2: set as user-defined attributes
    else this.setUserAttribute(name, value);
    return this;
};

Entity.prototype.get = function(name) {
    // Step 1: use user-defined attribute
    if (this.hasUserAttribute(name)) return this.getUserAttribute(name);
    // Step 2: use computed attribute
    if (this.hasComputedAttribute(name)) return this.getComputedAttribute(name);
    // Step 3: compute attribute
    var getterName = 'get' + _s.capitalize(name);
    if ((getterName in this) && _.isFunction(this[getterName])) {
        var result = this[getterName]();
        this.setComputedAttribute(name, result);
        return result;
    }
    // Step 4: throw an exception
    throw new ComputingError([name], this);
};

/*
** Exports
*/
module.exports = Entity;<commit_msg>Add read method<commit_after>/*
** Module dependencies
*/
var _s = require('underscore.string');
var _ = require('lodash');
var ComputingError = require('./errors').ComputingError;

/*
** Entity
*/
function Entity(options) {
    this.id = options.id;
    this.situation = options.situation;
    this.userAttributes = {};
    this.computedAttributes = {};
}

/*
** Prototype
*/
Entity.prototype.setUserAttribute = function(name, value) {
    this.userAttributes[name] = value;
};

Entity.prototype.getUserAttribute = function(name) {
    return this.userAttributes[name];
};

Entity.prototype.hasUserAttribute = function(name) {
    return name in this.userAttributes;
};

Entity.prototype.setComputedAttribute = function(name, value) {
    this.computedAttributes[name] = value;
};

Entity.prototype.getComputedAttribute = function(name) {
    return this.computedAttributes[name];
};

Entity.prototype.hasComputedAttribute = function(name) {
    return name in this.computedAttributes;
};

Entity.prototype.set = function(name, value) {
    // Batch set
    if (_.isObject(name)) {
        _.forEach(name, function(value, name) {
            this.set(name, value);
        }, this);
        return this;
    }

    // Step 1: use build-in accessor
    var setterName = 'set' + _s.capitalize(name);
    if ((setterName in this) && _.isFunction(this[setterName])) this[setterName](value);
    // Step 2: set as user-defined attributes
    else this.setUserAttribute(name, value);
    return this;
};

Entity.prototype.get = function(name) {
    // Step 1: use user-defined attribute
    if (this.hasUserAttribute(name)) return this.getUserAttribute(name);
    // Step 2: use computed attribute
    if (this.hasComputedAttribute(name)) return this.getComputedAttribute(name);
    // Step 3: compute attribute
    var getterName = 'get' + _s.capitalize(name);
    if ((getterName in this) && _.isFunction(this[getterName])) {
        var result = this[getterName]();
        this.setComputedAttribute(name, result);
        return result;
    }
    // Step 4: throw an exception
    throw new ComputingError([name], this);
};

Entity.prototype.read = function(name) {
    try {
        return this.get(name);
    } catch (e) {
        return undefined;
    }
};

/*
** Exports
*/
module.exports = Entity;<|endoftext|>


<commit_before>'use strict'

let cli = require('..')
let console = require('./console')
let linewrap = require('./linewrap')
let path = require('path')
let os = require('os')

function errtermwidth () {
  if (!process.stderr.isTTY) return 80
  let width = process.stderr.getWindowSize()[0]
  return width < 30 ? 30 : width
}

function wrap (msg) {
  return linewrap(6,
    errtermwidth(), {
      skipScheme: 'ansi-color',
      skip: /^\$ .*$/
    })(msg || '')
}

function bangify (msg, c) {
  let lines = msg.split('\n')
  for (let i = 0; i < lines.length; i++) {
    let line = lines[i]
    lines[i] = ' ' + c + line.substr(2, line.length)
  }
  return lines.join('\n')
}

function getErrorMessage (err) {
  if (err.body) {
    // API error
    if (err.body.message) {
      return err.body.message
    } else if (err.body.error) {
      return err.body.error
    }
  }
  // Unhandled error
  if (err.message && err.code) {
    return `${err.code}: ${err.message}`
  } else if (err.message) {
    return err.message
  }
  return err
}

let arrow = process.platform === 'win32' ? '!' : '▸'

function error (err) {
  console.error(bangify(wrap(getErrorMessage(err)), cli.color.red(arrow)))
}

function warn (msg) {
  console.error(renderWarning(msg))
}

function renderWarning (msg) {
  return bangify(wrap(msg), cli.color.yellow(arrow))
}

function logtimestamp () {
  return new Date().toISOString()
    .replace(/T/, ' ')
    .replace(/-/g, '/')
    .replace(/\..+/, '')
}

function cacheHome () {
  let base
  if (process.env.XDG_CACHE_HOME) base = process.env.XDG_CACHE_HOME
  if (!base) {
    if (process.platform === 'win32' && process.env.LOCALAPPDATA) {
      base = process.env.LOCALAPPDATA
    } else {
      base = path.join(os.homedir(), '.cache')
    }
  }
  return path.join(base, 'heroku')
}

function log (msg) {
  let fs = require('fs')
  let logPath = path.join(cacheHome(), 'error.log')
  fs.appendFileSync(logPath, logtimestamp() + ' ' + cli.color.stripColor(msg) + '\n')
}

function errorHandler (options) {
  options = options || {}
  function exit () {
    if (options.exit !== false) {
      process.exit(1)
    }
  }
  return function handleErr (err) {
    if (cli.raiseErrors) throw err
    try {
      if (err !== '') error(err)
      if (err.stack) {
        log(err.stack)
        if (options.debug) console.error(err.stack)
      }
      if (err.body) log(JSON.stringify(err.body))
      exit()
    } catch (err) {
      console.error(err.stack)
      process.exit(-1)
    }
  }
}

module.exports.error = error
module.exports.warn = warn
module.exports.errorHandler = errorHandler
module.exports.renderWarning = renderWarning
module.exports.errtermwidth = errtermwidth
<commit_msg>check for getWindowSize<commit_after>'use strict'

let cli = require('..')
let console = require('./console')
let linewrap = require('./linewrap')
let path = require('path')
let os = require('os')

function errtermwidth () {
  if (!process.stderr.isTTY || !process.stderr.getWindowSize) return 80
  let width = process.stderr.getWindowSize()[0]
  return width < 30 ? 30 : width
}

function wrap (msg) {
  return linewrap(6,
    errtermwidth(), {
      skipScheme: 'ansi-color',
      skip: /^\$ .*$/
    })(msg || '')
}

function bangify (msg, c) {
  let lines = msg.split('\n')
  for (let i = 0; i < lines.length; i++) {
    let line = lines[i]
    lines[i] = ' ' + c + line.substr(2, line.length)
  }
  return lines.join('\n')
}

function getErrorMessage (err) {
  if (err.body) {
    // API error
    if (err.body.message) {
      return err.body.message
    } else if (err.body.error) {
      return err.body.error
    }
  }
  // Unhandled error
  if (err.message && err.code) {
    return `${err.code}: ${err.message}`
  } else if (err.message) {
    return err.message
  }
  return err
}

let arrow = process.platform === 'win32' ? '!' : '▸'

function error (err) {
  console.error(bangify(wrap(getErrorMessage(err)), cli.color.red(arrow)))
}

function warn (msg) {
  console.error(renderWarning(msg))
}

function renderWarning (msg) {
  return bangify(wrap(msg), cli.color.yellow(arrow))
}

function logtimestamp () {
  return new Date().toISOString()
    .replace(/T/, ' ')
    .replace(/-/g, '/')
    .replace(/\..+/, '')
}

function cacheHome () {
  let base
  if (process.env.XDG_CACHE_HOME) base = process.env.XDG_CACHE_HOME
  if (!base) {
    if (process.platform === 'win32' && process.env.LOCALAPPDATA) {
      base = process.env.LOCALAPPDATA
    } else {
      base = path.join(os.homedir(), '.cache')
    }
  }
  return path.join(base, 'heroku')
}

function log (msg) {
  let fs = require('fs')
  let logPath = path.join(cacheHome(), 'error.log')
  fs.appendFileSync(logPath, logtimestamp() + ' ' + cli.color.stripColor(msg) + '\n')
}

function errorHandler (options) {
  options = options || {}
  function exit () {
    if (options.exit !== false) {
      process.exit(1)
    }
  }
  return function handleErr (err) {
    if (cli.raiseErrors) throw err
    try {
      if (err !== '') error(err)
      if (err.stack) {
        log(err.stack)
        if (options.debug) console.error(err.stack)
      }
      if (err.body) log(JSON.stringify(err.body))
      exit()
    } catch (err) {
      console.error(err.stack)
      process.exit(-1)
    }
  }
}

module.exports.error = error
module.exports.warn = warn
module.exports.errorHandler = errorHandler
module.exports.renderWarning = renderWarning
module.exports.errtermwidth = errtermwidth
<|endoftext|>


<commit_before>var util = require('util');

var BucketError = function (message) {
    Error.call(this);
    Error.captureStackTrace(this, this.constructor);
    this.name = this.constructor.name;
    this.message = message;
};

util.inherits(BucketError, Error);

exports.BucketError = BucketError;<commit_msg>Delete errors object for now.<commit_after><|endoftext|>


<commit_before>export const sym = id => `@@redux-saga/${id}`
export const TASK  = sym('TASK')
export const MATCH = sym('MATCH')
export const CANCEL = sym('cancelPromise')
export const konst = v => () => v
export const kTrue = konst(true)
export const kFalse = konst(false)
export const noop = () => {}
export const ident = v => v

export function check(value, predicate, error) {
  if(!predicate(value)) {
    log('error', 'uncaught at check', error)
    throw new Error(error)
  }
}

export const is = {
  undef     : v => v === null || v === undefined,
  notUndef  : v => v !== null && v !== undefined,
  func      : f => typeof f === 'function',
  number    : n => typeof n === 'number',
  array     : Array.isArray,
  promise   : p => p && is.func(p.then),
  iterator  : it => it && is.func(it.next) && is.func(it.throw),
  task      : t => t && t[TASK],
  take      : ch => ch && is.func(ch.take),
  put       : ch => ch && is.func(ch.put),
  observable: ob => ob && is.func(ob.subscribe),
  buffer    : buf => buf && is.func(buf.isEmpty) && is.func(buf.take) && is.func(buf.put),
  pattern   : pat => pat && ((typeof pat === 'string') || (typeof pat === 'symbol') || is.func(pat) || is.array(pat))
}

export function remove(array, item) {
  const index = array.indexOf(item)
  if(index >= 0) {
    array.splice(index, 1)
  }
}

export function deferred(props = {}) {
  let def = {...props}
  const promise = new Promise((resolve, reject) => {
    def.resolve = resolve
    def.reject = reject
  })
  def.promise = promise
  return def
}

export function arrayOfDeffered(length) {
  const arr = []
  for (let i = 0; i < length; i++) {
    arr.push(deferred())
  }
  return arr
}

export function delay(ms, val=true) {
  let timeoutId
  const promise = new Promise(resolve => {
    timeoutId = setTimeout(() => resolve(val), ms)
  })

  promise[CANCEL] = () => clearTimeout(timeoutId)

  return promise
}

export function createMockTask() {
  let running = true
  let result, error

  return {
    [TASK]: true,
    isRunning: () => running,
    result: () => result,
    error: () => error,

    setRunning : b => running = b,
    setResult  : r => result = r,
    setError   : e => error = e
  }
}

export function autoInc(seed = 0) {
  return () => ++seed
}

const kThrow = err => { throw err }
const kReturn = value => ({value, done: true})
export function makeIterator(next, thro = kThrow, name = '') {
  const iterator = {name, next, throw: thro, return: kReturn}
  if(typeof Symbol !== 'undefined') {
    iterator[Symbol.iterator] = () => iterator
  }
  return iterator
}

/**
  Print error in a useful way whether in a browser environment
  (with expandable error stack traces), or in a node.js environment
  (text-only log output)
 **/
export function log(level, message, error) {
  /*eslint-disable no-console*/
  if(typeof window === 'undefined') {
    console.log(`redux-saga ${level}: ${message}\n${(error && error.stack) || error}`)
  } else {
    console[level].call(console, message, error)
  }
}

export const internalErr = err => new Error(`
  redux-saga: Error checking hooks detected an inconsisten state. This is likely a bug
  in redux-saga code and not yours. Thanks for reporting this in the project's github repo.
  Error: ${err}
`)
<commit_msg>log() compatible with IE9<commit_after>export const sym = id => `@@redux-saga/${id}`
export const TASK  = sym('TASK')
export const MATCH = sym('MATCH')
export const CANCEL = sym('cancelPromise')
export const konst = v => () => v
export const kTrue = konst(true)
export const kFalse = konst(false)
export const noop = () => {}
export const ident = v => v

export function check(value, predicate, error) {
  if(!predicate(value)) {
    log('error', 'uncaught at check', error)
    throw new Error(error)
  }
}

export const is = {
  undef     : v => v === null || v === undefined,
  notUndef  : v => v !== null && v !== undefined,
  func      : f => typeof f === 'function',
  number    : n => typeof n === 'number',
  array     : Array.isArray,
  promise   : p => p && is.func(p.then),
  iterator  : it => it && is.func(it.next) && is.func(it.throw),
  task      : t => t && t[TASK],
  take      : ch => ch && is.func(ch.take),
  put       : ch => ch && is.func(ch.put),
  observable: ob => ob && is.func(ob.subscribe),
  buffer    : buf => buf && is.func(buf.isEmpty) && is.func(buf.take) && is.func(buf.put),
  pattern   : pat => pat && ((typeof pat === 'string') || (typeof pat === 'symbol') || is.func(pat) || is.array(pat))
}

export function remove(array, item) {
  const index = array.indexOf(item)
  if(index >= 0) {
    array.splice(index, 1)
  }
}

export function deferred(props = {}) {
  let def = {...props}
  const promise = new Promise((resolve, reject) => {
    def.resolve = resolve
    def.reject = reject
  })
  def.promise = promise
  return def
}

export function arrayOfDeffered(length) {
  const arr = []
  for (let i = 0; i < length; i++) {
    arr.push(deferred())
  }
  return arr
}

export function delay(ms, val=true) {
  let timeoutId
  const promise = new Promise(resolve => {
    timeoutId = setTimeout(() => resolve(val), ms)
  })

  promise[CANCEL] = () => clearTimeout(timeoutId)

  return promise
}

export function createMockTask() {
  let running = true
  let result, error

  return {
    [TASK]: true,
    isRunning: () => running,
    result: () => result,
    error: () => error,

    setRunning : b => running = b,
    setResult  : r => result = r,
    setError   : e => error = e
  }
}

export function autoInc(seed = 0) {
  return () => ++seed
}

const kThrow = err => { throw err }
const kReturn = value => ({value, done: true})
export function makeIterator(next, thro = kThrow, name = '') {
  const iterator = {name, next, throw: thro, return: kReturn}
  if(typeof Symbol !== 'undefined') {
    iterator[Symbol.iterator] = () => iterator
  }
  return iterator
}

/**
  Print error in a useful way whether in a browser environment
  (with expandable error stack traces), or in a node.js environment
  (text-only log output)
 **/
export function log(level, message, error) {
  /*eslint-disable no-console*/
  if(typeof window === 'undefined') {
    console.log(`redux-saga ${level}: ${message}\n${(error && error.stack) || error}`)
  } else {
    console[level](message, error)
  }
}

export const internalErr = err => new Error(`
  redux-saga: Error checking hooks detected an inconsisten state. This is likely a bug
  in redux-saga code and not yours. Thanks for reporting this in the project's github repo.
  Error: ${err}
`)
<|endoftext|>


<commit_before>var _ = require('lodash')

/**
 * generate_event_times
 *
 * given a group for a particular year, highway, direction, with each
 * row of the group a hash containing at least mints, maxts; generate
 * a new array in which each element is a group with active detectors.
 *
 * for example:
 * if you have some detectors and say you have records like
 * {id:a,mints:t1,maxts:t4}
 * {id:b,mints:t5,maxts:t6}
 * {id:c,mints:t1,maxts:t3}
 * {id:d,mints:t3,maxts:t5}
 *   ...
 *
 * then this will make an array of "active" detectors like so:
 *
 *        a b c d e f g h i j k l m
 *  t1    1   1     1
 *  t2    1   1   1 1 1   1   1
 *  t3    1   1 1 1 1 1 1 1 1 1
 *  t4    1     1 1 1 1 1   1 1
 *  t5      1   1 1 1   1   1   1 1
 *  t6      1     1 1   1       1 1
 *
 *
 * which when looked at edge-on (by time) gives an array of
 * {time:t1,detectors:[a,c,f]}
 * {time:t2,detectors:[a,c,e,f,g,i,k]}
 * {time:t3,detectors:[a,c,d,e,f,g,h,i,j,k]}
 *   ...
 *
 * So for each time stamp, you have the list of active detectors, so
 * you can determine the effective segment lengths between each
 * detector along the length of the freeway.
 *
 * @param {Object[]} group - The employees who are responsible for the project.
 * @param {string} group[].mints - The minimum active time for truck imputations.
 * @param {string} group[].maxts - The maximum active time for truck imputations.
 * @param {string} group[].id    - The detector id, either wim or vds.
 */
function generate_event_times(group){
    // simple little state machine.
    // detectors transition from holding, to active, to inactive
    var mintimes = []
    var maxtimes = []
    // parse min and max times into Dates

    // issue here is that max times are *active*  I need the next hour
    // also, be careful to not trip over stupid local time stuff by forcing all parsing to be UTC, and output to be UTC, and to strip off the .000Z at the end of the output string.  This gives a pretty accurate increment the hour by one
    _.each(group,function(row){
        mintimes.push(row.mints)
        // fiddle with the max ts to be one hour later, so as to
        // represent the time at which the detector is NOT active,
        // rather than the last time at which the detector IS active
        var ets = new Date( row.maxts + ' UTC')
        ets.setHours(ets.getHours()+1)
        ets = ets.toISOString().slice(0,-5) // drop .000Z
        ets = ets.replace(/T/,' ')
        maxtimes.push(ets)
        return null
    })
    var times = _.union(mintimes,maxtimes)
    times = times.sort()
    // console.log(times)
    var pending = _.clone(group,true)
    var active = []
    var states = []
    // this is inefficient in that I am pushing rows around, but it is
    // clearer than pushing pointers, and really a few instructions
    // aren't going to be noticeable here

    times.forEach(function(time,idx){
        // get rid of the T in the middle

        // remove from active all site that have expired
        // console.log('before pending',active.length)
        active = active.filter(function(row){
            return (row.maxts > time)
        })
        // console.log('after filter',active.length)

        // move from pending to active
        var next_pending = []
        pending.forEach(function(row){
            if(row.mints == time){
                active.push(row)
            }else{
                next_pending.push(row)
            }
        })
        // console.log('after pending',active.length)
        // for next iteration
        pending = next_pending

        // dump current active
        var detectors = (_.pluck(active,'id')).sort()
        if(detectors.length>0){

            states.push({
                'ts':time,
                'nextts':times[idx+1],
                'detectors': detectors
            })
        }

    })
    return states
}

module.exports=generate_event_times
<commit_msg>augment documentation<commit_after>var _ = require('lodash')

/**
 * generate_event_times
 *
 * given a group for a particular year, highway, direction, with each
 * row of the group a hash containing at least mints, maxts; generate
 * a new array in which each element is a group with active detectors.
 *
 * for example:
 * if you have some detectors a, b, c, and d, and say you know the
 * "active" ties for each detector in records like:
 *
 * {id:a,mints:t1,maxts:t4}
 * {id:b,mints:t5,maxts:t6}
 * {id:c,mints:t1,maxts:t3}
 * {id:d,mints:t3,maxts:t5}
 *   ...
 *
 * Which means detector "a" is up and running from t1 through t4, etc.
 *
 * Then combining these will make an array of "active" detectors
 * versus timestamp like so:
 *
 *        a b c d e f g h i j k l m
 *  t1    1   1     1
 *  t2    1   1   1 1 1   1   1
 *  t3    1   1 1 1 1 1 1 1 1 1
 *  t4    1     1 1 1 1 1   1 1
 *  t5      1   1 1 1   1   1   1 1
 *  t6      1     1 1   1       1 1
 *
 *
 * The idea is to look at this edge-on (by time) to get arrays of:
 *
 * {time:t1,detectors:[a,c,f]}
 * {time:t2,detectors:[a,c,e,f,g,i,k]}
 * {time:t3,detectors:[a,c,d,e,f,g,h,i,j,k]}
 *   ...
 *
 * These are then used to define the segment lengths.  So at time t1,
 * detector "c" has a segment that is from "a" to "f", but then at
 * time t2 the end-point of that segment changes to "e", because "e"
 * is now active.  The segment triplets are thus [a,c,f] for all
 * imputations from t1 through t2 and then [a,c,e] for imputations
 * from t2 through t3 (when "d" becomes active)
 *
 * So for each time stamp, you have a triplet list of active
 * detectors, so you can determine the effective segment lengths
 * between each detector along the length of the freeway.  Of course,
 * other code is used to compute these distances.
 *
 * @param {Object[]} group - The employees who are responsible for the project.
 * @param {string} group[].mints - The minimum active time for truck imputations.
 * @param {string} group[].maxts - The maximum active time for truck imputations.
 * @param {string} group[].id    - The detector id, either wim or vds.
 */
function generate_event_times(group){
    // simple little state machine.
    // detectors transition from holding, to active, to inactive
    var mintimes = []
    var maxtimes = []
    // parse min and max times into Dates

    // issue here is that max times are *active*  I need the next hour
    // also, be careful to not trip over stupid local time stuff by forcing all parsing to be UTC, and output to be UTC, and to strip off the .000Z at the end of the output string.  This gives a pretty accurate increment the hour by one
    _.each(group,function(row){
        mintimes.push(row.mints)
        // fiddle with the max ts to be one hour later, so as to
        // represent the time at which the detector is NOT active,
        // rather than the last time at which the detector IS active
        var ets = new Date( row.maxts + ' UTC')
        ets.setHours(ets.getHours()+1)
        ets = ets.toISOString().slice(0,-5) // drop .000Z
        ets = ets.replace(/T/,' ')
        maxtimes.push(ets)
        return null
    })
    var times = _.union(mintimes,maxtimes)
    times = times.sort()
    // console.log(times)
    var pending = _.clone(group,true)
    var active = []
    var states = []
    // this is inefficient in that I am pushing rows around, but it is
    // clearer than pushing pointers, and really a few instructions
    // aren't going to be noticeable here

    times.forEach(function(time,idx){
        // get rid of the T in the middle

        // remove from active all site that have expired
        // console.log('before pending',active.length)
        active = active.filter(function(row){
            return (row.maxts > time)
        })
        // console.log('after filter',active.length)

        // move from pending to active
        var next_pending = []
        pending.forEach(function(row){
            if(row.mints == time){
                active.push(row)
            }else{
                next_pending.push(row)
            }
        })
        // console.log('after pending',active.length)
        // for next iteration
        pending = next_pending

        // dump current active
        var detectors = (_.pluck(active,'id')).sort()
        if(detectors.length>0){

            states.push({
                'ts':time,
                'nextts':times[idx+1],
                'detectors': detectors
            })
        }

    })
    return states
}

module.exports=generate_event_times
<|endoftext|>


<commit_before>var EventYoshi = require('eventyoshi')
  , XMLFeedParser = require('./xmlfeedparser')
  , JSONFeedParser = require('./jsonfeedparser')

module.exports = function(buffer) {
  var yoshi = new EventYoshi()
    , parser

  // make yoshi behave stream like
  yoshi.writable = true;

  // first find out what type of feed this is
  yoshi.write = function(data) {
    var str = data.toString();
    var startParsing = false;

    if (/^\s*</.test(str)) {
      startParsing = true;
      parser = XMLFeedParser(buffer);

    } else if (/^\s*{/.test(str)) {
      startParsing = true;
      parser = JSONFeedParser(buffer);
      yoshi.emit('type', 'json');

    } else if (str.replace(/\s/g, '').length !== 0) {
      yoshi.emit('error', new Error('Not a correctly formatted feed'));
    }

    if (startParsing) {
      yoshi.add(parser);
      yoshi.proxy('write', 'end', 'done');
      parser.write(data);
    }

  };

  return yoshi;
};
<commit_msg>[fix] add an `end` method to begin state of parser<commit_after>var EventYoshi = require('eventyoshi')
  , XMLFeedParser = require('./xmlfeedparser')
  , JSONFeedParser = require('./jsonfeedparser')

module.exports = function(buffer) {
  var yoshi = new EventYoshi()
    , parser

  // make yoshi behave stream like
  yoshi.writable = true;

  // first find out what type of feed this is
  yoshi.write = function(data) {
    var str = data.toString();
    var startParsing = false;

    if (/^\s*</.test(str)) {
      startParsing = true;
      parser = XMLFeedParser(buffer);

    } else if (/^\s*{/.test(str)) {
      startParsing = true;
      parser = JSONFeedParser(buffer);
      yoshi.emit('type', 'json');

    } else if (str.replace(/\s/g, '').length !== 0) {
      yoshi.emit('error', new Error('Not a correctly formatted feed'));
    }

    if (startParsing) {
      yoshi.add(parser);
      yoshi.proxy('write', 'end', 'done');
      parser.write(data);
    }

  };

  // in case `end` is called right away
  yoshi.end = function(data) {
    if (data && data.length) {
      yoshi.write(data);
    } else {
      yoshi.emit('end');
    }
  };

  return yoshi;
};
<|endoftext|>


<commit_before>const {
  Transform
} = require('stream');

/**
 * Filters the object stream
 *
 * @property {Filter~Callback} filterCallback
 */
class Filter extends Transform {
  /**
   * @constructor
   * @param {Filter~Callback} filterCallback
   */
  constructor(filterCallback) {
    super({
      objectMode: true
    });

    this.filterCallback = filterCallback;
  }

  /**
   * https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback
   * @override
   */
  _transform(chunk, encoding, callback) {
    let accepted;
    try {
      accepted = !this.filterCallback || this.filterCallback(chunk);
    } catch (error) {
      callback(error, null);
      return;
    }
    if (accepted) {
      callback(null, chunk);
    }
  }
}

module.exports = Filter;
<commit_msg>Fix filter<commit_after>const {
  Transform
} = require('stream');

/**
 * Filters the object stream
 *
 * @property {Filter~Callback} filterCallback
 */
class Filter extends Transform {
  /**
   * @constructor
   * @param {Filter~Callback} filterCallback
   */
  constructor(filterCallback) {
    super({
      objectMode: true
    });

    this.filterCallback = filterCallback;
  }

  /**
   * https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback
   * @override
   */
  _transform(chunk, encoding, callback) {
    let accepted;
    try {
      accepted = !this.filterCallback || this.filterCallback(chunk);
    } catch (error) {
      callback(error, null);
      return;
    }
    callback(null, accepted ? chunk : null);
  }
}

module.exports = Filter;
<|endoftext|>


<commit_before>var fs = require('fs');
var glob = require('glob');
var path = require('path');
var readline = require('readline');
var spawn = require('child_process').spawn;

function FixMe() {}

FixMe.prototype.runEngine = function() {
  var config = {
    include_paths: ['./'],
    strings: ['FIXME', 'TODO', 'HACK', 'XXX', 'BUG']
  };

  if (fs.existsSync('/config.json')) {
    var userConfig = JSON.parse(fs.readFileSync('/config.json'));

    config.include_paths = userConfig.include_paths;

    if (userConfig.config) {
      for (var prop in userConfig.config) {
        config[prop] = userConfig.config[prop];
      }
    }
  }

  this.find(config.include_paths, config.strings);
}

FixMe.prototype.find = function(files, strings) {
  var fixmeStrings = '(' + strings.join('|') + ')';
  var args = ['--line-number', '--with-filename', '--word-regexp',
    '--only-matching', '--extended-regexp', '--recursive',
    '--binary-files=without-match', fixmeStrings];
  var grep = spawn('grep', args.concat(files));

  readline.createInterface({ input: grep.stdout }).on('line', function(line) {
    var cols = line.split(':');
    var fileName = cols[0].replace(/^\/code\//, '');
    var lineNum = parseInt(cols[1]);
    var matchedString = cols[2];

    if (matchedString !== undefined){
      var issue = JSON.stringify({
        'type': 'issue',
        'check_name': matchedString,
        'description': matchedString + ' found',
        'categories': ['Bug Risk'],
        'location':{
          'path': fileName,
          'lines': {
            'begin': lineNum,
            'end': lineNum
          }
        }
      });

      console.log(issue + '\0');
    }
  });
}

module.exports = FixMe;
<commit_msg>Remove unnecessary modules<commit_after>var fs = require('fs');
var readline = require('readline');
var spawn = require('child_process').spawn;

function FixMe() {}

FixMe.prototype.runEngine = function() {
  var config = {
    include_paths: ['./'],
    strings: ['FIXME', 'TODO', 'HACK', 'XXX', 'BUG']
  };

  if (fs.existsSync('/config.json')) {
    var userConfig = JSON.parse(fs.readFileSync('/config.json'));

    config.include_paths = userConfig.include_paths;

    if (userConfig.config) {
      for (var prop in userConfig.config) {
        config[prop] = userConfig.config[prop];
      }
    }
  }

  this.find(config.include_paths, config.strings);
}

FixMe.prototype.find = function(files, strings) {
  var fixmeStrings = '(' + strings.join('|') + ')';
  var args = ['--line-number', '--with-filename', '--word-regexp',
    '--only-matching', '--extended-regexp', '--recursive',
    '--binary-files=without-match', fixmeStrings];
  var grep = spawn('grep', args.concat(files));

  readline.createInterface({ input: grep.stdout }).on('line', function(line) {
    var cols = line.split(':');
    var fileName = cols[0].replace(/^\/code\//, '');
    var lineNum = parseInt(cols[1]);
    var matchedString = cols[2];

    if (matchedString !== undefined){
      var issue = JSON.stringify({
        'type': 'issue',
        'check_name': matchedString,
        'description': matchedString + ' found',
        'categories': ['Bug Risk'],
        'location':{
          'path': fileName,
          'lines': {
            'begin': lineNum,
            'end': lineNum
          }
        }
      });

      console.log(issue + '\0');
    }
  });
}

module.exports = FixMe;
<|endoftext|>


<commit_before>/**
 * NeoTabs - jQuery plugin
 *
 * source: http://github.com/PascalPrecht/jquery.neotabs.js/
 * site: http://pascalprecht.github.com/jquery.neotabs.js/
 *
 * @author: Pascal Precht <pascal.precht@gmail.com>
 * Released under the MIT and GPL Licenses.
 */
;(function ($, window, undefined) {

  var pluginName = 'neoTabs',
      document = window.document,

      defaults = {
        wrapperClass: 'content',
        activeClass: 'active',
        tabHeadClass: 'tabhead',
        tabBodyClass: 'tabbody',
        firstTabClass: 'first',
        lastTabClass: 'last',
        clearfixClass: 'group',
        tabsListClass: 'tabs-list',
        tabHeadElement: 'h4',
        tabsPosition: 'top',
        cssClassAvailable: true,
        fx: 'show',
        fxSpeed: 0,
        autoAnchor: true,
        wrapInnerTabs: '',
        dropdownTabLabel: '▾',
        dropdownTabClass: 'dropdown',
        dropdownTabsListClass: 'tabs-list',
        dropdownTabsClearfixClass: 'group'
      },
      tabsCount = 0,
      keyCodes = {
        37: -1,
        38: -1,
        39: +1,
        40: +1
      },
      positions = {
        top: 'prepend',
        bottom: 'append'
      };

  // Helper function to check exclusively for an HTML5 data-attribute. Thanks to
  // @cburgdorf for typing down this gist for me: (https://gist.github.com/3979912)
  $.fn.hasDataAttr = function (attr) {
    var value = this.attr('data-' + attr);
    return typeof value !== 'undefined' && value !== false;
  };

  if ($('body').data('accessibleTabsCount') !== undefined) {
    tabsCount = $('body').data('accessibleTabsCount');
  }

  $('body').data('accessibleTabsCount', tabsCount);

  function NeoTabs(element, options) {
    var _this = this;

    $.extend(_this, {
      $el: element,
      opts: $.extend({}, defaults, options),
      keyCodes: keyCodes,
      hasDropdown: false,
      hasPreActiveTab: false,
      tabsList: null,
      dropdownTabsList: null
    });

    _this.tabsList = new TabsList({
      clearfixClass: _this.opts.clearfixClass,
      tabsListClass: _this.opts.tabsListClass
    });

    _this.$el.wrapInner('

');

    _this.$el.find(_this.opts.tabHeadElement).each(function (i) {

      var $tabHeadElement = $(this);

      if (!_this.hasDropdown && $tabHeadElement.hasDataAttr('neotabs-dropdown')) {
        _this.dropdownTabsList = new TabsList({
          clearfixClass: _this.opts.dropdownTabsClearfixClass,
          tabsListClass: _this.opts.dropdownTabsListClass
        });
        _this.hasDropdown = true;
      }

      if (!_this.hasPreActiveTab && $tabHeadElement.hasDataAttr('neotabs-active')) {
        $tabHeadElement.addClass(_this.opts.activeClass);
        _this.hasPreActiveTab = true;
      }

      var tab = new Tab({
        label: $tabHeadElement.html(),
        id: _this.generateTabId('accessibletabscontent', tabsCount, i),
        tabsList: null,
        cssClass: (_this.opts.cssClassAvailable) ?
          (($tabHeadElement.attr('class') || '') + ' ' + _this.opts.tabHeadClass) :
          _this.opts.tabHeadClass
      });

      if (_this.hasDropdown) {
        _this.dropdownTabsList.addTab(tab);
      } else {
        _this.tabsList.addTab(tab);
      }

      $tabHeadElement.attr({
        'id': tab.id,
        'class': _this.opts.tabHeadClass,
        'tab-index': '-1'
      });
    });

    // Generate dropdown tab if hasDropdown flag is true
    if (_this.hasDropdown) {
      _this.tabsList.addTab(new Tab({
        label: _this.opts.dropdownTabLabel,
        id: '',
        tabsList: _this.dropdownTabsList,
        cssClass: _this.opts.tabHeadClass + ' ' + _this.opts.dropdownTabClass
      }));
    }

    if (!_this.$el.find('.' + _this.opts.tabsListClass).length) {
      _this.$el[positions[_this.opts.tabsPosition]](_this.tabsList.toHtml());
    }

    var $content = _this.$el.find('.' + _this.opts.tabBodyClass),
        $tabsList = _this.$el.find('.' + _this.opts.tabsListClass);

    // Show the first tab content by default
    if ($content.length > 0) {
      $content.hide();
      $($content[0]).show();
    }

    // Which tab should be active?
    $tabsList.find(' > li:first')
      .addClass(_this.opts.firstTabClass + ((!_this.hasPreActiveTab) ? ' ' + _this.opts.activeClass : ''))
      .closest('ul').find('> li:last')
      .addClass(_this.opts.lastTabClass);

    if (_this.opts.wrapInnerTabs) {
      $tabsList.find('> li > a').wrapInner(_this.opts.wrapInnerTabs);
    }

    $tabsList.find('> li a').each(function (i) {
      var $tab = $(this);

      $tab.on('click', function (e) {
        e.preventDefault();

        $tabsList
          .find('> li.' + _this.opts.activeClass)
          .removeClass(_this.opts.activeClass);

        $(this).parent().addClass(_this.opts.activeClass);

        if (!$(this).parent().hasClass(_this.opts.dropdownTabClass)) {
          _this.$el.find('.' + _this.opts.tabBodyClass + ':visible').hide();

          var j = i;

          // little hack to because we have more tabHead then tabBodys
          if ($(this).closest('.' + _this.opts.dropdownTabClass).length) {
            j = i-1;
          }

          _this.$el.find('.' + _this.opts.tabBodyClass).eq(j)[_this.opts.fx](_this.opts.fxSpeed);
        }
      });
    });

    // If we have an anchor in our url, trigger click event on the right tab
    if (_this.opts.autoAnchor && window.location.hash) {
      var $anchorTab = $('.' + _this.opts.tabsListClass).find(window.location.hash);
      if ($anchorTab.size()) {
        $anchorTab.click();
      }
    }

    if (_this.hasPreActiveTab) {
      $('.' + _this.opts.tabsListClass + ' .' + _this.opts.activeClass + ' a').click();
    }
    tabsCount++;
  }

  NeoTabs.prototype.generateTabId = function (name, tabsCount, tabCount) {
    return 'accessibletabscontent' + tabsCount + '-' + tabCount;
  };

  function TabsList(options) {
    this.tabs = [];
    this.clearfixClass = options.clearfixClass;
    this.tabsListClass = options.tabsListClass;
  }

  TabsList.prototype.addTab = function (tab) {
    this.tabs.push(tab);
  };

  TabsList.prototype.toHtml = function () {
    var len = this.tabs.length,
        i = 0,
        html = '
';

    for (; i < len; i++) {
      html += this.tabs[i].toHtml();
    }
    return html;
  };

  function Tab(options) {
    this.label = options.label;
    this.id = options.id;
    this.tabsList = options.tabsList;
    this.cssClass = options.cssClass;
  }

  Tab.prototype.toHtml = function () {
    var html = '
' + this.label + '';

    if (this.tabsList) {
      html += this.tabsList.toHtml();
    }
    html += '
';
    return html;
  };

  $.fn[pluginName] = function (options) {
    return this.each(function () {
      if (!$.data(this, 'plugin_' + pluginName)) {
        $.data(this, 'plugin_' + pluginName, new NeoTabs($(this), options ));
      }
    });
  };
}(jQuery, window));
<commit_msg>Started implementing keyboard support<commit_after>/**
 * NeoTabs - jQuery plugin
 *
 * source: http://github.com/PascalPrecht/jquery.neotabs.js/
 * site: http://pascalprecht.github.com/jquery.neotabs.js/
 *
 * @author: Pascal Precht <pascal.precht@gmail.com>
 * Released under the MIT and GPL Licenses.
 */
;(function ($, window, undefined) {

  var pluginName = 'neoTabs',
      document = window.document,

      defaults = {
        wrapperClass: 'content',
        activeClass: 'active',
        tabHeadClass: 'tabhead',
        tabBodyClass: 'tabbody',
        firstTabClass: 'first',
        lastTabClass: 'last',
        clearfixClass: 'group',
        tabsListClass: 'tabs-list',
        tabHeadElement: 'h4',
        tabsPosition: 'top',
        cssClassAvailable: true,
        fx: 'show',
        fxSpeed: 0,
        autoAnchor: true,
        wrapInnerTabs: '',
        dropdownTabLabel: '▾',
        dropdownTabClass: 'dropdown',
        dropdownTabsListClass: 'tabs-list',
        dropdownTabsClearfixClass: 'group'
      },
      tabsCount = 0,
      keyCodes = {
        37: -1,
        38: -1,
        39: +1,
        40: +1
      },
      positions = {
        top: 'prepend',
        bottom: 'append'
      };

  // Helper function to check exclusively for an HTML5 data-attribute. Thanks to
  // @cburgdorf for typing down this gist for me: (https://gist.github.com/3979912)
  $.fn.hasDataAttr = function (attr) {
    var value = this.attr('data-' + attr);
    return typeof value !== 'undefined' && value !== false;
  };

  if ($('body').data('accessibleTabsCount') !== undefined) {
    tabsCount = $('body').data('accessibleTabsCount');
  }

  $('body').data('accessibleTabsCount', tabsCount);

  function NeoTabs(element, options) {
    var _this = this;

    $.extend(_this, {
      $el: element,
      opts: $.extend({}, defaults, options),
      keyCodes: keyCodes,
      hasDropdown: false,
      hasPreActiveTab: false,
      tabsList: null,
      dropdownTabsList: null
    });

    _this.tabsList = new TabsList({
      clearfixClass: _this.opts.clearfixClass,
      tabsListClass: _this.opts.tabsListClass
    });

    _this.$el.wrapInner('

');

    _this.$el.find(_this.opts.tabHeadElement).each(function (i) {

      var $tabHeadElement = $(this);

      if (!_this.hasDropdown && $tabHeadElement.hasDataAttr('neotabs-dropdown')) {
        _this.dropdownTabsList = new TabsList({
          clearfixClass: _this.opts.dropdownTabsClearfixClass,
          tabsListClass: _this.opts.dropdownTabsListClass
        });
        _this.hasDropdown = true;
      }

      if (!_this.hasPreActiveTab && $tabHeadElement.hasDataAttr('neotabs-active')) {
        $tabHeadElement.addClass(_this.opts.activeClass);
        _this.hasPreActiveTab = true;
      }

      var tab = new Tab({
        label: $tabHeadElement.html(),
        id: _this.generateTabId(tabsCount, i),
        tabsList: null,
        cssClass: (_this.opts.cssClassAvailable) ?
          (($tabHeadElement.attr('class') || '') + ' ' + _this.opts.tabHeadClass) :
          _this.opts.tabHeadClass
      });

      if (_this.hasDropdown) {
        _this.dropdownTabsList.addTab(tab);
      } else {
        _this.tabsList.addTab(tab);
      }

      $tabHeadElement.attr({
        'id': tab.id,
        'class': _this.opts.tabHeadClass,
        'tab-index': '-1'
      });
    });

    // Generate dropdown tab if hasDropdown flag is true
    if (_this.hasDropdown) {
      _this.tabsList.addTab(new Tab({
        label: _this.opts.dropdownTabLabel,
        id: '',
        tabsList: _this.dropdownTabsList,
        cssClass: _this.opts.tabHeadClass + ' ' + _this.opts.dropdownTabClass
      }));
    }

    if (!_this.$el.find('.' + _this.opts.tabsListClass).length) {
      _this.$el[positions[_this.opts.tabsPosition]](_this.tabsList.toHtml());
    }

    var $content = _this.$el.find('.' + _this.opts.tabBodyClass),
        $tabsList = _this.$el.find('.' + _this.opts.tabsListClass);

    // Show the first tab content by default
    if ($content.length > 0) {
      $content.hide();
      $($content[0]).show();
    }

    // Which tab should be active?
    $tabsList.find(' > li:first')
      .addClass(_this.opts.firstTabClass + ((!_this.hasPreActiveTab) ? ' ' + _this.opts.activeClass : ''))
      .closest('ul').find('> li:last')
      .addClass(_this.opts.lastTabClass);

    if (_this.opts.wrapInnerTabs) {
      $tabsList.find('> li > a').wrapInner(_this.opts.wrapInnerTabs);
    }

    $tabsList.find('> li a').each(function (i) {
      var $tab = $(this);

      $tab.on('click', function (e) {
        e.preventDefault();

        $tabsList
          .find('> li.' + _this.opts.activeClass)
          .removeClass(_this.opts.activeClass);

        $(this).parent().addClass(_this.opts.activeClass);

        if (!$(this).parent().hasClass(_this.opts.dropdownTabClass)) {
          _this.$el.find('.' + _this.opts.tabBodyClass + ':visible').hide();

          var j = i;

          // little hack to because we have more tabHead then tabBodys
          if ($(this).closest('.' + _this.opts.dropdownTabClass).length) {
            j = i-1;
          }

          _this.$el.find('.' + _this.opts.tabBodyClass).eq(j)[_this.opts.fx](_this.opts.fxSpeed);
        }
      });

      $tab.focus(function () {
        $(document).keyup(function (e) {
          if (_this.keyCodes[e.keyCode]) {
            _this.activateTab(0, (i+_this.keyCodes[e.keyCode]));
          }
        });
      });
    });

    // If we have an anchor in our url, trigger click event on the right tab
    if (_this.opts.autoAnchor && window.location.hash) {
      var $anchorTab = $('.' + _this.opts.tabsListClass).find(window.location.hash);
      if ($anchorTab.size()) {
        $anchorTab.click();
      }
    }

    if (_this.hasPreActiveTab) {
      $('.' + _this.opts.tabsListClass + ' .' + _this.opts.activeClass + ' a').click();
    }

    tabsCount++;
  }

  NeoTabs.prototype.activateTab = function (tabsCount, tabCount) {
   $tab = $('#' + this.generateTabId(tabsCount, tabCount));
   console.log($tab);
   $tab.click();
  };

  NeoTabs.prototype.generateTabId = function (tabsCount, tabCount) {
    return 'accessibletabscontent' + tabsCount + '-' + tabCount;
  };

  function TabsList(options) {
    this.tabs = [];
    this.clearfixClass = options.clearfixClass;
    this.tabsListClass = options.tabsListClass;
  }

  TabsList.prototype.addTab = function (tab) {
    this.tabs.push(tab);
  };

  TabsList.prototype.toHtml = function () {
    var len = this.tabs.length,
        i = 0,
        html = '
';

    for (; i < len; i++) {
      html += this.tabs[i].toHtml();
    }
    return html;
  };

  function Tab(options) {
    this.label = options.label;
    this.id = options.id;
    this.tabsList = options.tabsList;
    this.cssClass = options.cssClass;
  }

  Tab.prototype.toHtml = function () {
    var html = '
' + this.label + '';

    if (this.tabsList) {
      html += this.tabsList.toHtml();
    }
    html += '
';
    return html;
  };

  $.fn[pluginName] = function (options) {
    return this.each(function () {
      if (!$.data(this, 'plugin_' + pluginName)) {
        $.data(this, 'plugin_' + pluginName, new NeoTabs($(this), options ));
      }
    });
  };
}(jQuery, window));
<|endoftext|>


<commit_before>/*
 * onetree
 * https://github.com/xuejp/onetree
 *
 * Copyright (c) 2015 xuejp
 * Licensed under the APL license.
 */

( function ( factory ) {
	if ( typeof define === 'function' && define.amd ) {
		define( 'onetree', [ 'jquery' ], factory );
	} else {
		factory( jQuery );
	}
}( function ( $ ) {
	'use strict';

	$.fn.extend( {
		onetree: function ( options ) {
			var element = this,
				dataList = [];
			options = $.extend( true, {}, $.onetree.options, options );
			dataList = $.onetree.generateLinkedList( options.data, function ( result ) {
				result.sort( options.sortCallback );
			} );
			if ( options.root.append ) {
				dataList = [ {
					node: options.root.node,
					subnode: dataList
                } ];
			}
			$( element )
				.empty()
				.append( $.onetree.generateHtml( dataList,
					options.wrapOutTag,
					options.wrapInnerTag,
					options.contentTemplate,
					options.callback ) );

			return $.fn.menutree;
		}
	} );

	$.extend( {
		onetree: {
			options: {
				data: [],
				root: {
					append: false,
					node: {
						ID: 0,
						PID: -1
					}
				},
				sortCallback: null,
				wrapOutTag: 'ul',
				wrapInnerTag: 'li',
				contentTemplate: '',
				callback: null
			},
			generateLinkedList: function ( data, callback ) {
				var result = [],
					i,
					rootNode = this.findRootNodes( data );
				for ( i = 0; i < rootNode.length; i++ ) {
					result.push( this._generateSubTree( rootNode[ i ], data, callback ) );
				}
				if ( 'function' === typeof callback ) {
					callback( result );
				}
				return result;
			},
			convertToDictionary: function ( data ) {
				var result = [],
					i;
				for ( i = 0; i < data.length; i++ ) {
					result[ data[ i ].ID.toString() ] = data[ i ];
				}
				return result;
			},
			findRootNodes: function ( data ) {
				var result = [],
					key,
					dictionary = this.convertToDictionary( data );
				for ( key in dictionary ) {
					if ( dictionary.hasOwnProperty( key ) && dictionary[ dictionary[ key ].PID.toString() ] === undefined ) {
						result.push( dictionary[ key ] );
					}
				}
				return result;
			},
			_generateSubTree: function ( fNode, data, callback ) {
				var result = [],
					i;
				for ( i = 0; i < data.length; i++ ) {
					if ( data[ i ].PID === fNode.ID ) {
						result.push( this._generateSubTree( data[ i ], data ) );
					}
				}
				if ( 'function' === typeof callback ) {
					callback( result );
				}
				return {
					node: fNode,
					subnode: result
				};
			},
			generateHtml: function ( linkedList, wrapOutTag, wrapInnerTag, contentTemplate, callback ) {
				var $html,
					i;
				$html = $( document.createElement( wrapOutTag ) );
				for ( i = 0; i < linkedList.length; i++ ) {
					$html.append( this._generateNodeHtml( linkedList[ i ], wrapOutTag, wrapInnerTag, contentTemplate, callback ) );
				}
				return $html;
			},
			_generateNodeHtml: function ( node, wrapOutTag, wrapInnerTag, contentTemplate, callback ) {
				var $nodeHtml,
					$nodelistHtml,
					i;
				$nodeHtml = $( document.createElement( wrapInnerTag ) )
					.append( this._generateContentHtml( node.node, contentTemplate, callback ) );
				if ( callback !== null ) {
					callback( $nodeHtml, node.node );
				}
				if ( node.subnode.length > 0 ) {
					$nodelistHtml = $( document.createElement( wrapOutTag ) );
					for ( i = 0; i < node.subnode.length; i++ ) {
						$nodelistHtml.append( this._generateNodeHtml( node.subnode[ i ], wrapOutTag, wrapInnerTag, contentTemplate, callback ) );
					}
					$nodeHtml.append( $nodelistHtml );
				}
				return $nodeHtml;
			},
			_generateContentHtml: function ( node, contentTemplate ) {
				var strHtml = contentTemplate,
					key;
				for ( key in node ) {
					if ( node.hasOwnProperty( key ) ) {
						strHtml = strHtml.replace( new RegExp( '\\{' + key + '\\}', 'gi' ), node[ key ] );
					}
				}
				return $( strHtml );
			},
			traverseParent: function ( node, callback ) {
				var parentNode = node.parent()
					.parent( this.options.wrapInnerTag );
				if ( parentNode.html() === undefined ) {
					return;
				}
				callback.apply( parentNode );
				this.traverseParent( parentNode, callback );
			},
			traverseChildren: function ( node, callback ) {
				var childNodes = $( node )
					.children( this.options.wrapOutTag )
					.children(),
					i;
				if ( childNodes.html() === undefined ) {
					return;
				}
				for ( i = 0; i < childNodes.length; i++ ) {
					callback.apply( childNodes[ i ] );
					this.traverseChildren( childNodes[ i ], callback );
				}
			},
			traverseBrother: function ( node, callback ) {
				var brotherNodes = $( node )
					.parent()
					.children( this.options.wrapInnerTag ),
					i;
				for ( i = 0; i < brotherNodes.length; i++ ) {
					if ( brotherNodes[ i ] === node ) {
						continue;
					}
					callback.apply( brotherNodes[ i ] );
				}
			}
		}
	} );
} ) );
<commit_msg>Correct bug in the IE brower<commit_after>/*
 * onetree
 * https://github.com/xuejp/onetree
 *
 * Copyright (c) 2015 xuejp
 * Licensed under the APL license.
 */

(function (factory) {
	if (typeof define === 'function' && define.amd) {
		define('onetree', ['jquery'], factory);
	} else {
		factory(jQuery);
	}
}(function ($) {
	'use strict';

	$.fn.extend({
		onetree: function (options) {
			var element = this,
				dataList = [];
			options = $.extend(true, {}, $.onetree.options, options);
			dataList = $.onetree.generateLinkedList(options.data, function (result) {
				if ('function' === typeof options.sortCallback) {
					result.sort(options.sortCallback);
				}
			});
			if (options.root.append) {
				dataList = [{
					node: options.root.node,
					subnode: dataList
                }];
			}
			$(element)
				.empty()
				.append($.onetree.generateHtml(dataList,
					options.wrapOutTag,
					options.wrapInnerTag,
					options.contentTemplate,
					options.callback));

			return $.fn.menutree;
		}
	});

	$.extend({
		onetree: {
			options: {
				data: [],
				root: {
					append: false,
					node: {
						ID: 0,
						PID: -1
					}
				},
				sortCallback: null,
				wrapOutTag: 'ul',
				wrapInnerTag: 'li',
				contentTemplate: '',
				callback: null
			},
			generateLinkedList: function (data, callback) {
				var result = [],
					i,
					rootNode = this.findRootNodes(data);
				for (i = 0; i < rootNode.length; i++) {
					result.push(this._generateSubTree(rootNode[i], data, callback));
				}
				if ('function' === typeof callback) {
					callback(result);
				}
				return result;
			},
			convertToDictionary: function (data) {
				var result = [],
					i;
				for (i = 0; i < data.length; i++) {
					result[data[i].ID.toString()] = data[i];
				}
				return result;
			},
			findRootNodes: function (data) {
				var result = [],
					key,
					dictionary = this.convertToDictionary(data);
				for (key in dictionary) {
					if (dictionary.hasOwnProperty(key) && dictionary[dictionary[key].PID.toString()] === undefined) {
						result.push(dictionary[key]);
					}
				}
				return result;
			},
			_generateSubTree: function (fNode, data, callback) {
				var result = [],
					i;
				for (i = 0; i < data.length; i++) {
					if (data[i].PID === fNode.ID) {
						result.push(this._generateSubTree(data[i], data));
					}
				}
				if ('function' === typeof callback) {
					callback(result);
				}
				return {
					node: fNode,
					subnode: result
				};
			},
			generateHtml: function (linkedList, wrapOutTag, wrapInnerTag, contentTemplate, callback) {
				var $html,
					i;
				$html = $(document.createElement(wrapOutTag));
				for (i = 0; i < linkedList.length; i++) {
					$html.append(this._generateNodeHtml(linkedList[i], wrapOutTag, wrapInnerTag, contentTemplate, callback));
				}
				return $html;
			},
			_generateNodeHtml: function (node, wrapOutTag, wrapInnerTag, contentTemplate, callback) {
				var $nodeHtml,
					$nodelistHtml,
					i;
				$nodeHtml = $(document.createElement(wrapInnerTag))
					.append(this._generateContentHtml(node.node, contentTemplate, callback));
				if (callback !== null) {
					callback($nodeHtml, node.node);
				}
				if (node.subnode.length > 0) {
					$nodelistHtml = $(document.createElement(wrapOutTag));
					for (i = 0; i < node.subnode.length; i++) {
						$nodelistHtml.append(this._generateNodeHtml(node.subnode[i], wrapOutTag, wrapInnerTag, contentTemplate, callback));
					}
					$nodeHtml.append($nodelistHtml);
				}
				return $nodeHtml;
			},
			_generateContentHtml: function (node, contentTemplate) {
				var strHtml = contentTemplate,
					key;
				for (key in node) {
					if (node.hasOwnProperty(key)) {
						strHtml = strHtml.replace(new RegExp('\\{' + key + '\\}', 'gi'), node[key]);
					}
				}
				return $(strHtml);
			},
			traverseParent: function (node, callback) {
				var parentNode = node.parent()
					.parent(this.options.wrapInnerTag);
				if (parentNode.html() === undefined) {
					return;
				}
				callback.apply(parentNode);
				this.traverseParent(parentNode, callback);
			},
			traverseChildren: function (node, callback) {
				var childNodes = $(node)
					.children(this.options.wrapOutTag)
					.children(),
					i;
				if (childNodes.html() === undefined) {
					return;
				}
				for (i = 0; i < childNodes.length; i++) {
					callback.apply(childNodes[i]);
					this.traverseChildren(childNodes[i], callback);
				}
			},
			traverseBrother: function (node, callback) {
				var brotherNodes = $(node)
					.parent()
					.children(this.options.wrapInnerTag),
					i;
				for (i = 0; i < brotherNodes.length; i++) {
					if (brotherNodes[i] === node) {
						continue;
					}
					callback.apply(brotherNodes[i]);
				}
			}
		}
	});
}));
<|endoftext|>


<commit_before>class ContextMenu {
    constructor (player) {
        this.player = player;

        [...this.player.template.menuItem].map((item, index) => {
            if (this.player.options.contextmenu[index].click) {
                item.addEventListener('click', () => {
                    this.player.options.contextmenu[index].click(this.player);
                    this.hide();
                });
            }
            return item;
        });

        this.player.container.addEventListener('contextmenu', (e) => {
            const event = e || window.event;
            event.preventDefault();

            const clientRect = this.player.container.getBoundingClientRect();
            this.show(event.clientX - clientRect.left, event.clientY - clientRect.top);

            this.player.template.mask.addEventListener('click', () => {
                this.hide();
            });
        });
    }

    show (x, y) {
        this.player.template.menu.classList.add('dplayer-menu-show');

        const clientRect = this.player.container.getBoundingClientRect();
        if (x + this.player.template.menu.offsetWidth >= clientRect.width) {
            this.player.template.menu.style.right = clientRect.width - x + 'px';
            this.player.template.menu.style.left = 'initial';
        }
        else {
            this.player.template.menu.style.left = x + 'px';
            this.player.template.menu.style.right = 'initial';
        }
        if (y + this.player.template.menu.offsetHeight >= clientRect.height) {
            this.player.template.menu.style.bottom = clientRect.height - y + 'px';
            this.player.template.menu.style.top = 'initial';
        }
        else {
            this.player.template.menu.style.top = y + 'px';
            this.player.template.menu.style.bottom = 'initial';
        }

        this.player.template.mask.classList.add('dplayer-mask-show');

        this.player.events.trigger('contextmenu_show');
    }

    hide () {
        this.player.template.mask.classList.remove('dplayer-mask-show');
        this.player.template.menu.classList.remove('dplayer-menu-show');

        this.player.events.trigger('contextmenu_hide');
    }
}

export default ContextMenu;<commit_msg>Fix es5 compatibility<commit_after>class ContextMenu {
    constructor (player) {
        this.player = player;

        Array.prototype.slice.call(this.player.template.menuItem).forEach((item, index) => {
            if (this.player.options.contextmenu[index].click) {
                item.addEventListener('click', () => {
                    this.player.options.contextmenu[index].click(this.player);
                    this.hide();
                });
            }
        });

        this.player.container.addEventListener('contextmenu', (e) => {
            const event = e || window.event;
            event.preventDefault();

            const clientRect = this.player.container.getBoundingClientRect();
            this.show(event.clientX - clientRect.left, event.clientY - clientRect.top);

            this.player.template.mask.addEventListener('click', () => {
                this.hide();
            });
        });
    }

    show (x, y) {
        this.player.template.menu.classList.add('dplayer-menu-show');

        const clientRect = this.player.container.getBoundingClientRect();
        if (x + this.player.template.menu.offsetWidth >= clientRect.width) {
            this.player.template.menu.style.right = clientRect.width - x + 'px';
            this.player.template.menu.style.left = 'initial';
        }
        else {
            this.player.template.menu.style.left = x + 'px';
            this.player.template.menu.style.right = 'initial';
        }
        if (y + this.player.template.menu.offsetHeight >= clientRect.height) {
            this.player.template.menu.style.bottom = clientRect.height - y + 'px';
            this.player.template.menu.style.top = 'initial';
        }
        else {
            this.player.template.menu.style.top = y + 'px';
            this.player.template.menu.style.bottom = 'initial';
        }

        this.player.template.mask.classList.add('dplayer-mask-show');

        this.player.events.trigger('contextmenu_show');
    }

    hide () {
        this.player.template.mask.classList.remove('dplayer-mask-show');
        this.player.template.menu.classList.remove('dplayer-menu-show');

        this.player.events.trigger('contextmenu_hide');
    }
}

export default ContextMenu;
<|endoftext|>


<commit_before>import { $ } from '../util/index';

export default function (UIkit) {

    UIkit.component('margin', {

        props: {
            margin: String,
            firstColumn: Boolean
        },

        defaults: {
            margin: 'uk-margin-small-top',
            firstColumn: 'uk-first-column'
        },

        update: {

            read() {

                if (this.$el[0].offsetHeight === 0) {
                    this.hidden = true;
                    return;
                }

                this.hidden = false;
                this.stacks = true;

                var columns = this.$el.children().filter((_, el) => el.offsetHeight > 0);

                this.rows = [[columns.get(0)]];

                columns.slice(1).each((_, el) => {

                    var top = Math.ceil(el.offsetTop), bottom = top + el.offsetHeight;

                    for (var index = this.rows.length - 1; index >= 0; index--) {
                        var row = this.rows[index], rowTop = Math.ceil(row[0].offsetTop);

                        if (top >= rowTop + row[0].offsetHeight) {
                            this.rows.push([el]);
                            break;
                        }

                        if (bottom > rowTop) {

                            this.stacks = false;

                            if (el.offsetLeft < row[0].offsetLeft) {
                                row.unshift(el);
                                break;
                            }

                            row.push(el);
                            break;
                        }

                        if (index === 0) {
                            this.rows.splice(index, 0, [el]);
                            break;
                        }

                    }

                });

            },

            write() {

                if (this.hidden) {
                    return;
                }

                this.rows.forEach((row, i) =>
                    row.forEach((el, j) =>
                        $(el)
                            .toggleClass(this.margin, i !== 0)
                            .toggleClass(this.firstColumn, j === 0)
                    )
                )

            },

            events: ['load', 'resize', 'orientationchange']

        }

    });

}
<commit_msg>fixed grid jumping<commit_after>import { $ } from '../util/index';

export default function (UIkit) {

    UIkit.component('margin', {

        props: {
            margin: String,
            firstColumn: Boolean
        },

        defaults: {
            margin: 'uk-margin-small-top',
            firstColumn: 'uk-first-column'
        },

        connected() {
            this._callUpdate();
        },

        update: {

            read() {

                if (this.$el[0].offsetHeight === 0) {
                    this.hidden = true;
                    return;
                }

                this.hidden = false;
                this.stacks = true;

                var columns = this.$el.children().filter((_, el) => el.offsetHeight > 0);

                this.rows = [[columns.get(0)]];

                columns.slice(1).each((_, el) => {

                    var top = Math.ceil(el.offsetTop), bottom = top + el.offsetHeight;

                    for (var index = this.rows.length - 1; index >= 0; index--) {
                        var row = this.rows[index], rowTop = Math.ceil(row[0].offsetTop);

                        if (top >= rowTop + row[0].offsetHeight) {
                            this.rows.push([el]);
                            break;
                        }

                        if (bottom > rowTop) {

                            this.stacks = false;

                            if (el.offsetLeft < row[0].offsetLeft) {
                                row.unshift(el);
                                break;
                            }

                            row.push(el);
                            break;
                        }

                        if (index === 0) {
                            this.rows.splice(index, 0, [el]);
                            break;
                        }

                    }

                });

            },

            write() {

                if (this.hidden) {
                    return;
                }

                this.rows.forEach((row, i) =>
                    row.forEach((el, j) =>
                        $(el)
                            .toggleClass(this.margin, i !== 0)
                            .toggleClass(this.firstColumn, j === 0)
                    )
                )

            },

            events: ['load', 'resize', 'orientationchange']

        }

    });

}
<|endoftext|>


<commit_before><commit_msg>Formatting<commit_after><|endoftext|>


<commit_before>"use strict";

webvowl.graph = function (graphContainerSelector) {
	var graph = {},
		CARDINALITY_HDISTANCE = 20,
		CARDINALITY_VDISTANCE = 10,
		curveFunction = d3.svg.line()
			.x(function (d) {
				return d.x;
			})
			.y(function (d) {
				return d.y;
			})
			.interpolate("cardinal"),
		options,
		parser = webvowl.parser(graph),
		linkCreator = webvowl.parsing.linkCreator(),
		language = "default",
	// Container for visual elements
		graphContainer,
		nodeContainer,
		labelContainer,
		cardinalityContainer,
		linkContainer,
	// Visual elements
		nodeElements,
		labelGroupElements,
		linkGroups,
		linkPathElements,
		cardinalityElements,
	// Internal data
		nodes,
		properties,
		unfilteredNodes,
		unfilteredProperties,
		links,
	// Graph behaviour
		force,
		dragBehaviour,
		zoom;

	/**
	 * Recalculates the positions of nodes, links, ... and updates them.
	 */
	function recalculatePositions() {
		// Set node positions
		nodeElements.attr("transform", function (node) {
			return "translate(" + node.x + "," + node.y + ")";
		});

		// Set link paths and calculate additional informations
		linkPathElements.attr("d", function (l) {
			if (l.domain() === l.range()) {
				return webvowl.util.math().calculateLoopPath(l);
			}

			// Calculate these every time to get nicer curved paths
			var pathStart = webvowl.util.math().calculateIntersection(l.range(), l.domain(), 1),
				pathEnd = webvowl.util.math().calculateIntersection(l.domain(), l.range(), 1),
				linkDistance = getVisibleLinkDistance(l),
				curvePoint = webvowl.util.math().calculateCurvePoint(pathStart, pathEnd, l,
					linkDistance / options.defaultLinkDistance());

			l.curvePoint(curvePoint);

			return curveFunction([webvowl.util.math().calculateIntersection(l.curvePoint(), l.domain(), 1),
				curvePoint, webvowl.util.math().calculateIntersection(l.curvePoint(), l.range(), 1)]);
		});

		// Set label group positions
		labelGroupElements.attr("transform", function (link) {
			var posX = link.curvePoint().x,
				posY = link.curvePoint().y;

			return "translate(" + posX + "," + posY + ")";
		});

		// Set cardinality positions
		cardinalityElements.attr("transform", function (p) {
			var curve = p.link().curvePoint(),
				pos = webvowl.util.math().calculateIntersection(curve, p.range(), CARDINALITY_HDISTANCE),
				normalV = webvowl.util.math().calculateNormalVector(curve, p.domain(), CARDINALITY_VDISTANCE);

			return "translate(" + (pos.x + normalV.x) + "," + (pos.y + normalV.y) + ")";
		});
	}

	/**
	 * Adjusts the containers current scale and position.
	 */
	function zoomed() {
		graphContainer.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
	}

	/**
	 * Initializes the graph.
	 */
	function initializeGraph() {
		options = webvowl.options();
		options.graphContainerSelector(graphContainerSelector);

		force = d3.layout.force()
			.on("tick", recalculatePositions);

		dragBehaviour = d3.behavior.drag()
			.origin(function (d) {
				return d;
			})
			.on("dragstart", function (d) {
				d3.event.sourceEvent.stopPropagation(); // Prevent panning
				d.locked(true);
			})
			.on("drag", function (d) {
				d.px = d3.event.x;
				d.py = d3.event.y;
				force.resume();
			})
			.on("dragend", function (d) {
				d.locked(false);
			});

		// Apply the zooming factor.
		zoom = d3.behavior.zoom()
			.scaleExtent([options.minMagnification(), options.maxMagnification()])
			.on("zoom", zoomed);

	}

	initializeGraph();

	/**
	 * Returns the graph options of this graph (readonly).
	 * @returns {webvowl.options} a graph options object
	 */
	graph.graphOptions = function () {
		return options;
	};

	/**
	 * Loads all settings, removes the old graph (if it exists) and draws a new one.
	 */
	graph.start = function () {
		force.stop();
		loadGraphData();
		redrawGraph();
		graph.update();
	};

	/**
	 * Updates only the style of the graph.
	 */
	graph.updateStyle = function () {
		refreshGraphStyle();
		force.start();
	};

	graph.reload = function () {
		loadGraphData();
		this.update();
	};

	/**
	 * Updates the graphs displayed data and style.
	 */
	graph.update = function () {
		refreshGraphData();
		refreshGraphStyle();
		force.start();
		redrawContent();
	};

	/**
	 * Stops the influence of the force directed layout on all nodes. They are still manually movable.
	 */
	graph.freeze = function () {
		nodes.forEach(function (n) {
			n.frozen(true);
		});
	};

	/**
	 * Allows the influence of the force directed layout on all nodes.
	 */
	graph.unfreeze = function () {
		nodes.forEach(function (n) {
			n.frozen(false);
		});
		force.resume();
	};

	/**
	 * Resets visual settings like zoom or panning.
	 */
	graph.reset = function () {
		zoom.translate([0, 0])
			.scale(1);
	};

	/**
	 * Calculate the complete link distance. The visual link distance does
	 * not contain e.g. radii of round nodes.
	 * @param link the link
	 * @returns {*}
	 */
	function calculateLinkDistance(link) {
		var distance = getVisibleLinkDistance(link);
		distance += link.domain().actualRadius();
		distance += link.range().actualRadius();
		return distance;
	}

	function getVisibleLinkDistance(link) {
		function isDatatype(node) {
			if (node instanceof webvowl.nodes.rdfsdatatype ||
				node instanceof webvowl.nodes.rdfsliteral) {
				return true;
			}
			return false;
		}

		if (isDatatype(link.domain()) || isDatatype(link.range())) {
			return options.datatypeDistance();
		} else {
			return options.classDistance();
		}
	}

	/**
	 * Empties the last graph container and draws a new one with respect to the
	 * value the graph container selector has.
	 */
	function redrawGraph() {
		remove();

		graphContainer = d3.selectAll(options.graphContainerSelector())
			.append("svg")
			.classed("vowlGraph", true)
			.attr("width", options.width())
			.attr("height", options.height())
			.call(zoom)
			.append("g");
	}

	/**
	 * Redraws all elements like nodes, links, ...
	 */
	function redrawContent() {
		var markerContainer;

		// Empty the graph container
		graphContainer.selectAll("*").remove();

		// Last container -> elements of this container overlap others
		linkContainer = graphContainer.append("g").classed("linkContainer", true);
		cardinalityContainer = graphContainer.append("g").classed("cardinalityContainer", true);
		labelContainer = graphContainer.append("g").classed("labelContainer", true);
		nodeContainer = graphContainer.append("g").classed("nodeContainer", true);

		// Add an extra container for all markers
		markerContainer = linkContainer.append("defs");

		// Draw nodes
		nodeElements = nodeContainer.selectAll(".node")
			.data(nodes).enter()
			.append("g")
			.classed("node", true)
			.attr("id", function (d) {
				return d.id();
			})
			.call(dragBehaviour);

		nodeElements.each(function (d) {
			d.drawNode(d3.select(this));
		});

		// Draw label groups (property + inverse)
		labelGroupElements = labelContainer.selectAll(".labelGroup")
			.data(links).enter()
			.append("g")
			.classed("labelGroup", true);

		labelGroupElements.each(function (link) {
			var success = link.property().drawProperty(d3.select(this));
			// Remove empty groups without a label.
			if (!success) {
				d3.select(this).remove();
			}
		});

		// Draw cardinalities
		cardinalityElements = cardinalityContainer.selectAll(".cardinality")
			.data(properties).enter()
			.append("g")
			.classed("cardinality", true);

		cardinalityElements.each(function (property) {
			var success = property.drawCardinality(d3.select(this));

			// Remove empty groups without a label.
			if (!success) {
				d3.select(this).remove();
			}
		});

		// Draw links
		linkGroups = linkContainer.selectAll(".link")
			.data(links).enter()
			.append("g")
			.classed("link", true);

		linkGroups.each(function (link) {
			link.drawLink(d3.select(this), markerContainer);
		});

		// Select the path for direct access to receive a better performance
		linkPathElements = linkGroups.selectAll("path");

		addClickEvents();
	}

	/**
	 * Applies click listeneres to nodes and properties.
	 */
	function addClickEvents() {
		function executeModules(selectedElement) {
			options.selectionModules().forEach(function (module) {
				module.handle(selectedElement);
			});
		}

		nodeElements.on("click", function (clickedNode) {
			executeModules(clickedNode);
		});

		labelGroupElements.selectAll(".label").on("click", function (clickedProperty) {
			executeModules(clickedProperty);
		});
	}

	function loadGraphData() {
		parser.parse(options.data());

		unfilteredNodes = parser.nodes();
		unfilteredProperties = parser.properties();
	}

	/**
	 * Applies the data of the graph options object and parses it. The graph is not redrawn.
	 */
	function refreshGraphData() {
		var preprocessedNodes = unfilteredNodes,
			preprocessedProperties = unfilteredProperties;

		// Filter the data
		options.filterModules().forEach(function (module) {
			module.filter(preprocessedNodes, preprocessedProperties);
			preprocessedNodes = module.filteredNodes();
			preprocessedProperties = module.filteredProperties();
		});

		nodes = preprocessedNodes;
		properties = preprocessedProperties;
		links = linkCreator.createLinks(properties);

		storeLinksOnNodes(nodes, links);

		force.nodes(nodes)
			.links(links);
	}

	function storeLinksOnNodes(nodes, links) {
		for (var i = 0, nodesLength = nodes.length; i < nodesLength; i++) {
			var node = nodes[i],
				connectedLinks = [];

			// look for properties where this node is the domain or range
			for (var j = 0, linksLength = links.length; j < linksLength; j++) {
				var link = links[j];

				if (link.domain() === node || link.range() === node) {
					connectedLinks.push(link);
				}
			}

			node.links(connectedLinks);
		}
	}

	/**
	 * Applies all options that don't change the graph data.
	 */
	function refreshGraphStyle() {
		zoom = zoom.scaleExtent([options.minMagnification(), options.maxMagnification()]);
		zoom.event(graphContainer);

		force.charge(options.charge())
			.size([options.width(), options.height()])
			.linkDistance(calculateLinkDistance)
			.gravity(options.gravity())
			.linkStrength(options.linkStrength()); // Flexibility of links
	}

	/**
	 * Removes all elements from the graph container.
	 */
	function remove() {
		if (graphContainer) {
			// Select the parent element because the graph container is a group (e.g. for zooming)
			d3.select(graphContainer.node().parentNode).remove();
		}
	}

	graph.setLanguage = function (l) {
		if (language !== l) {
			language = l || "default";
			graph.update();
		}
	};

	graph.getLanguage = function () {
		return language;
	};

	return graph;
};
<commit_msg>Optimize redrawing after language change<commit_after>"use strict";

webvowl.graph = function (graphContainerSelector) {
	var graph = {},
		CARDINALITY_HDISTANCE = 20,
		CARDINALITY_VDISTANCE = 10,
		curveFunction = d3.svg.line()
			.x(function (d) {
				return d.x;
			})
			.y(function (d) {
				return d.y;
			})
			.interpolate("cardinal"),
		options,
		parser = webvowl.parser(graph),
		linkCreator = webvowl.parsing.linkCreator(),
		language = "default",
	// Container for visual elements
		graphContainer,
		nodeContainer,
		labelContainer,
		cardinalityContainer,
		linkContainer,
	// Visual elements
		nodeElements,
		labelGroupElements,
		linkGroups,
		linkPathElements,
		cardinalityElements,
	// Internal data
		nodes,
		properties,
		unfilteredNodes,
		unfilteredProperties,
		links,
	// Graph behaviour
		force,
		dragBehaviour,
		zoom;

	/**
	 * Recalculates the positions of nodes, links, ... and updates them.
	 */
	function recalculatePositions() {
		// Set node positions
		nodeElements.attr("transform", function (node) {
			return "translate(" + node.x + "," + node.y + ")";
		});

		// Set link paths and calculate additional informations
		linkPathElements.attr("d", function (l) {
			if (l.domain() === l.range()) {
				return webvowl.util.math().calculateLoopPath(l);
			}

			// Calculate these every time to get nicer curved paths
			var pathStart = webvowl.util.math().calculateIntersection(l.range(), l.domain(), 1),
				pathEnd = webvowl.util.math().calculateIntersection(l.domain(), l.range(), 1),
				linkDistance = getVisibleLinkDistance(l),
				curvePoint = webvowl.util.math().calculateCurvePoint(pathStart, pathEnd, l,
					linkDistance / options.defaultLinkDistance());

			l.curvePoint(curvePoint);

			return curveFunction([webvowl.util.math().calculateIntersection(l.curvePoint(), l.domain(), 1),
				curvePoint, webvowl.util.math().calculateIntersection(l.curvePoint(), l.range(), 1)]);
		});

		// Set label group positions
		labelGroupElements.attr("transform", function (link) {
			var posX = link.curvePoint().x,
				posY = link.curvePoint().y;

			return "translate(" + posX + "," + posY + ")";
		});

		// Set cardinality positions
		cardinalityElements.attr("transform", function (p) {
			var curve = p.link().curvePoint(),
				pos = webvowl.util.math().calculateIntersection(curve, p.range(), CARDINALITY_HDISTANCE),
				normalV = webvowl.util.math().calculateNormalVector(curve, p.domain(), CARDINALITY_VDISTANCE);

			return "translate(" + (pos.x + normalV.x) + "," + (pos.y + normalV.y) + ")";
		});
	}

	/**
	 * Adjusts the containers current scale and position.
	 */
	function zoomed() {
		graphContainer.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
	}

	/**
	 * Initializes the graph.
	 */
	function initializeGraph() {
		options = webvowl.options();
		options.graphContainerSelector(graphContainerSelector);

		force = d3.layout.force()
			.on("tick", recalculatePositions);

		dragBehaviour = d3.behavior.drag()
			.origin(function (d) {
				return d;
			})
			.on("dragstart", function (d) {
				d3.event.sourceEvent.stopPropagation(); // Prevent panning
				d.locked(true);
			})
			.on("drag", function (d) {
				d.px = d3.event.x;
				d.py = d3.event.y;
				force.resume();
			})
			.on("dragend", function (d) {
				d.locked(false);
			});

		// Apply the zooming factor.
		zoom = d3.behavior.zoom()
			.scaleExtent([options.minMagnification(), options.maxMagnification()])
			.on("zoom", zoomed);

	}

	initializeGraph();

	/**
	 * Returns the graph options of this graph (readonly).
	 * @returns {webvowl.options} a graph options object
	 */
	graph.graphOptions = function () {
		return options;
	};

	/**
	 * Loads all settings, removes the old graph (if it exists) and draws a new one.
	 */
	graph.start = function () {
		force.stop();
		loadGraphData();
		redrawGraph();
		graph.update();
	};

	/**
	 * Updates only the style of the graph.
	 */
	graph.updateStyle = function () {
		refreshGraphStyle();
		force.start();
	};

	graph.reload = function () {
		loadGraphData();
		this.update();
	};

	/**
	 * Updates the graphs displayed data and style.
	 */
	graph.update = function () {
		refreshGraphData();
		refreshGraphStyle();
		force.start();
		redrawContent();
	};

	/**
	 * Stops the influence of the force directed layout on all nodes. They are still manually movable.
	 */
	graph.freeze = function () {
		nodes.forEach(function (n) {
			n.frozen(true);
		});
	};

	/**
	 * Allows the influence of the force directed layout on all nodes.
	 */
	graph.unfreeze = function () {
		nodes.forEach(function (n) {
			n.frozen(false);
		});
		force.resume();
	};

	/**
	 * Resets visual settings like zoom or panning.
	 */
	graph.reset = function () {
		zoom.translate([0, 0])
			.scale(1);
	};

	/**
	 * Calculate the complete link distance. The visual link distance does
	 * not contain e.g. radii of round nodes.
	 * @param link the link
	 * @returns {*}
	 */
	function calculateLinkDistance(link) {
		var distance = getVisibleLinkDistance(link);
		distance += link.domain().actualRadius();
		distance += link.range().actualRadius();
		return distance;
	}

	function getVisibleLinkDistance(link) {
		function isDatatype(node) {
			if (node instanceof webvowl.nodes.rdfsdatatype ||
				node instanceof webvowl.nodes.rdfsliteral) {
				return true;
			}
			return false;
		}

		if (isDatatype(link.domain()) || isDatatype(link.range())) {
			return options.datatypeDistance();
		} else {
			return options.classDistance();
		}
	}

	/**
	 * Empties the last graph container and draws a new one with respect to the
	 * value the graph container selector has.
	 */
	function redrawGraph() {
		remove();

		graphContainer = d3.selectAll(options.graphContainerSelector())
			.append("svg")
			.classed("vowlGraph", true)
			.attr("width", options.width())
			.attr("height", options.height())
			.call(zoom)
			.append("g");
	}

	/**
	 * Redraws all elements like nodes, links, ...
	 */
	function redrawContent() {
		var markerContainer;

		// Empty the graph container
		graphContainer.selectAll("*").remove();

		// Last container -> elements of this container overlap others
		linkContainer = graphContainer.append("g").classed("linkContainer", true);
		cardinalityContainer = graphContainer.append("g").classed("cardinalityContainer", true);
		labelContainer = graphContainer.append("g").classed("labelContainer", true);
		nodeContainer = graphContainer.append("g").classed("nodeContainer", true);

		// Add an extra container for all markers
		markerContainer = linkContainer.append("defs");

		// Draw nodes
		nodeElements = nodeContainer.selectAll(".node")
			.data(nodes).enter()
			.append("g")
			.classed("node", true)
			.attr("id", function (d) {
				return d.id();
			})
			.call(dragBehaviour);

		nodeElements.each(function (d) {
			d.drawNode(d3.select(this));
		});

		// Draw label groups (property + inverse)
		labelGroupElements = labelContainer.selectAll(".labelGroup")
			.data(links).enter()
			.append("g")
			.classed("labelGroup", true);

		labelGroupElements.each(function (link) {
			var success = link.property().drawProperty(d3.select(this));
			// Remove empty groups without a label.
			if (!success) {
				d3.select(this).remove();
			}
		});

		// Draw cardinalities
		cardinalityElements = cardinalityContainer.selectAll(".cardinality")
			.data(properties).enter()
			.append("g")
			.classed("cardinality", true);

		cardinalityElements.each(function (property) {
			var success = property.drawCardinality(d3.select(this));

			// Remove empty groups without a label.
			if (!success) {
				d3.select(this).remove();
			}
		});

		// Draw links
		linkGroups = linkContainer.selectAll(".link")
			.data(links).enter()
			.append("g")
			.classed("link", true);

		linkGroups.each(function (link) {
			link.drawLink(d3.select(this), markerContainer);
		});

		// Select the path for direct access to receive a better performance
		linkPathElements = linkGroups.selectAll("path");

		addClickEvents();
	}

	/**
	 * Applies click listeneres to nodes and properties.
	 */
	function addClickEvents() {
		function executeModules(selectedElement) {
			options.selectionModules().forEach(function (module) {
				module.handle(selectedElement);
			});
		}

		nodeElements.on("click", function (clickedNode) {
			executeModules(clickedNode);
		});

		labelGroupElements.selectAll(".label").on("click", function (clickedProperty) {
			executeModules(clickedProperty);
		});
	}

	function loadGraphData() {
		parser.parse(options.data());

		unfilteredNodes = parser.nodes();
		unfilteredProperties = parser.properties();
	}

	/**
	 * Applies the data of the graph options object and parses it. The graph is not redrawn.
	 */
	function refreshGraphData() {
		var preprocessedNodes = unfilteredNodes,
			preprocessedProperties = unfilteredProperties;

		// Filter the data
		options.filterModules().forEach(function (module) {
			module.filter(preprocessedNodes, preprocessedProperties);
			preprocessedNodes = module.filteredNodes();
			preprocessedProperties = module.filteredProperties();
		});

		nodes = preprocessedNodes;
		properties = preprocessedProperties;
		links = linkCreator.createLinks(properties);

		storeLinksOnNodes(nodes, links);

		force.nodes(nodes)
			.links(links);
	}

	function storeLinksOnNodes(nodes, links) {
		for (var i = 0, nodesLength = nodes.length; i < nodesLength; i++) {
			var node = nodes[i],
				connectedLinks = [];

			// look for properties where this node is the domain or range
			for (var j = 0, linksLength = links.length; j < linksLength; j++) {
				var link = links[j];

				if (link.domain() === node || link.range() === node) {
					connectedLinks.push(link);
				}
			}

			node.links(connectedLinks);
		}
	}

	/**
	 * Applies all options that don't change the graph data.
	 */
	function refreshGraphStyle() {
		zoom = zoom.scaleExtent([options.minMagnification(), options.maxMagnification()]);
		zoom.event(graphContainer);

		force.charge(options.charge())
			.size([options.width(), options.height()])
			.linkDistance(calculateLinkDistance)
			.gravity(options.gravity())
			.linkStrength(options.linkStrength()); // Flexibility of links
	}

	/**
	 * Removes all elements from the graph container.
	 */
	function remove() {
		if (graphContainer) {
			// Select the parent element because the graph container is a group (e.g. for zooming)
			d3.select(graphContainer.node().parentNode).remove();
		}
	}

	graph.setLanguage = function (l) {
		if (language !== l) {
			language = l || "default";
			redrawContent();
			recalculatePositions();
		}
	};

	graph.getLanguage = function () {
		return language;
	};

	return graph;
};
<|endoftext|>