<commit_before>(function() {
	"use strict";

	var ContentEditableUtils = function() {
	};

	ContentEditableUtils.prototype.getTextFromContentEditable = function(contentEditable) {
		var pre = $("
").html(contentEditable.html());
		pre.find("div").replaceWith(function() { return "\n" + this.innerHTML; });
		pre.find("p").replaceWith(function() { return this.innerHTML + "
"; });
		pre.find("br").replaceWith("\n");
		var tempParagraphs = pre.text().trim().split("\n");
		var resultParagraphs = [];
		$.each(tempParagraphs, function(index, value) {
			value = value.trim();
			if (value !== "") {
				resultParagraphs.push("
" + value + "
");
			}
		});
		return resultParagraphs.join("");
	};

	// Export
	window.hikeio.ContentEditableUtils = ContentEditableUtils;
}
)();<commit_msg>Handle spans in large contenteditable divs.<commit_after>(function() {
	"use strict";

	var ContentEditableUtils = function() {
	};

	ContentEditableUtils.prototype.getTextFromContentEditable = function(contentEditable) {
		var pre = $("
").html(contentEditable.html());
		pre.find("div").replaceWith(function() { return "\n" + this.innerHTML; });
		pre.find("p").replaceWith(function() { return this.innerHTML + "
"; });
		pre.find("br").replaceWith("\n");
		pre.find("span").replaceWith(function() { return "\n" + this.innerHTML; });
		var tempParagraphs = pre.text().trim().split("\n");
		var resultParagraphs = [];
		$.each(tempParagraphs, function(index, value) {
			value = value.trim();
			if (value !== "") {
				resultParagraphs.push("
" + value + "
");
			}
		});
		return resultParagraphs.join("");
	};

	// Export
	window.hikeio.ContentEditableUtils = ContentEditableUtils;
}
)();<|endoftext|>


<commit_before>/* jshint node: true */

module.exports = function(environment) {
  var ENV = {
    modulePrefix: 'my-portfolio',
    environment: environment,
    baseURL: '/',
    locationType: 'auto',
    EmberENV: {
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      }
    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    }
  };

  if (environment === 'development') {
    // ENV.APP.LOG_RESOLVER = true;
    // ENV.APP.LOG_ACTIVE_GENERATION = true;
    // ENV.APP.LOG_TRANSITIONS = true;
    // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
    // ENV.APP.LOG_VIEW_LOOKUPS = true;
  }

  if (environment === 'test') {
    // Testem prefers this...
    ENV.baseURL = '/';
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
  }

  if (environment === 'production') {

  }

  return ENV;
};
<commit_msg>Changes locationType to hash<commit_after>/* jshint node: true */

module.exports = function(environment) {
  var ENV = {
    modulePrefix: 'my-portfolio',
    environment: environment,
    baseURL: '/',
    locationType: 'hash',
    EmberENV: {
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      }
    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    }
  };

  if (environment === 'development') {
    // ENV.APP.LOG_RESOLVER = true;
    // ENV.APP.LOG_ACTIVE_GENERATION = true;
    // ENV.APP.LOG_TRANSITIONS = true;
    // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
    // ENV.APP.LOG_VIEW_LOOKUPS = true;
  }

  if (environment === 'test') {
    // Testem prefers this...
    ENV.baseURL = '/';
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
  }

  if (environment === 'production') {

  }

  return ENV;
};
<|endoftext|>


<commit_before>'use strict';

var aFrom           = require('es5-ext/array/from')
  , compact         = require('es5-ext/array/#/compact')
  , isCopy          = require('es5-ext/array/#/is-copy')
  , pluck           = require('es5-ext/function/pluck')
  , copy            = require('es5-ext/object/copy')
  , assign          = require('es5-ext/object/assign')
  , isObject        = require('es5-ext/object/is-object')
  , callable        = require('es5-ext/object/valid-callable')
  , toArray         = require('es5-ext/array/to-array')
  , isMap           = require('es6-map/is-map')
  , d               = require('d')
  , autoBind        = require('d/auto-bind')
  , memoize         = require('memoizee/plain')
  , memoizeMethods  = require('memoizee/methods-plain')
  , getNormalizer   = require('memoizee/normalizers/get-1')
  , makeEl          = require('dom-ext/document/#/make-element')
  , append          = require('dom-ext/element/#/append')
  , clear           = require('dom-ext/element/#/clear')
  , remove          = require('dom-ext/element/#/remove')
  , replaceCont     = require('dom-ext/element/#/replace-content')
  , dispatchEvnt    = require('dom-ext/html-element/#/dispatch-event-2')
  , isNested        = require('dbjs/is-dbjs-nested-object')
  , resolveOptions  = require('../utils/resolve-options')
  , DOMInput        = require('../_controls/input')
  , eventOpts       = require('../_event-options')
  , setup           = require('../')

  , getMapValue = pluck(1)
  , isArray = Array.isArray, map = Array.prototype.map
  , defineProperty = Object.defineProperty
  , defineProperties = Object.defineProperties
  , getName = Object.getOwnPropertyDescriptor(DOMInput.prototype, 'name').get
  , Input, render, renderItem, getTempForm, getForceReset;

getForceReset = memoize(function (document) {
	var form = document.createElement('form');
	return function (input) {
		var parent = input.parentNode, nextSibling = input.nextSibling;
		form.appendChild(input);
		form.reset();
		parent.insertBefore(input, nextSibling);
	};
}, { normalizer: getNormalizer() });

getTempForm = memoize(function (document) {
	var form = document.createElement('form');
	form.setAttribute('method', 'post');
	form.setAttribute('enctype', 'multipart/form-data');
	form.setAttribute('style', 'display: none');
	return form;
}, { normalizer: getNormalizer() });

render = function (options) {
	var el = this.make;
	return el('div', { class: 'dbjs-file' },
		this.valueDOM = this.multiple ? el('ul') : el('span'),
		el('label', { class: 'dbjs-file-input' }, options.label,
			this.control = el('input', { type: 'file' })));
};

renderItem = function (file) {
	var el = this.make, data = {}, name;
	data.dom = el(this.multiple ? 'li' : 'span', { 'data-id': file.__id__ });
	if (isNested(file)) name = file.__id__;
	else name = this.descriptor.__valueId__ + '*7' + file.__id__;
	append.call(data.dom,
		el('a', { href: file._url, target: '_blank' }, file._name), " ",
		el('label', { class: 'clear' },
			el('input', { type: 'checkbox', name: name, value: '' }), "x"));
	return data;
};

var byNameLastModified = function (f1, f2) {
	f1 = this.getById(f1);
	if (f1) f1 = f1.getDescriptor('name')._lastOwnModified_;
	f2 = this.getById(f2);
	if (f2) f2 = f2.getDescriptor('name')._lastOwnModified_;
	return (f1 || Infinity) - (f2 || Infinity);
};

Input = function (document, type/*, options*/) {
	var options = arguments[2], action;
	this.make = makeEl.bind(document);
	this.controls = [];
	this.type = type;
	options = resolveOptions(options, type);
	if (options.multiple) this.multiple = true;
	((options.render == null) || callable(options.render));
	defineProperty(this, 'renderItem', d((options.renderItem == null)
		? renderItem : callable(options.renderItem)));
	DOMInput.call(this, document, type, options);
	if (this.multiple) this.control.setAttribute('multiple', 'multiple');
	this.control.setAttribute('accept', toArray(type.accept).join(','));

	if (options.autoSubmit != null) {
		action = options.autoSubmit;
		this.dom.classList.add('auto-submit');
		this.on('change', function () {
			var form, parent, sibling;
			if (!this.changed) return;
			form = getTempForm(document);
			parent = this.dom.parentNode;
			sibling = this.dom.nextSibling;
			form.setAttribute('action', action);
			document.body.appendChild(form);
			form.appendChild(this.dom);
			dispatchEvnt.call(form, 'submit');
			parent.insertBefore(this.dom, sibling);
			if (form.parentNode) form.parentNode.removeChild(form);
		});
	}
	if (this._required) this.castControlAttribute('required', true);
	this.valueDOM.addEventListener('change', this.onChange, false);
};

Input.prototype = Object.create(DOMInput.prototype, assign({
	constructor: d(Input),
	multiple: d(false),
	_value: d(null),
	controlAttributes: d(assign(copy(DOMInput.prototype.controlAttributes),
		{ required: true })),
	dbAttributes: d(assign(copy(DOMInput.prototype.dbAttributes),
		{ required: true })),
	_render: d(function (options) {
		this.dom = (options.render || render).call(this, options);
		this.controls.push(this.control);
	}),
	name: d.gs(getName, function (name) {
		this._name = name;
		name = this.name;
		this.controls.forEach(function (input) { input.name = name; });
	}),
	inputValue: d.gs(function () {
		var value, item;
		if (!this.multiple) {
			if (this.control.files && this.control.files[0]) return this.control.files[0];
			item = this.valueDOM.firstElementChild;
			if (!item) return null;
			if (item.classList.contains('empty')) return null;
			if (item.querySelector('input[type=checkbox]').checked) return null;
			return this.valueDOM.firstElementChild.getAttribute('data-id');
		}
		value = compact.call(map.call(this.valueDOM.childNodes, function (item) {
			var id;
			if (item.classList.contains('empty')) return null;
			if (item.querySelector('input[type=checkbox]').checked) return null;
			id = item.getAttribute('data-id');
			if (!id) throw new TypeError("Missing id (data-id attribute) on file item");
			return id;
		})).concat(this.control.files ? aFrom(this.control.files) : []);
		return value.length ? value : null;
	}, function (nu) {
		var old = this.inputValue, changed;
		this._value = nu;
		if (this.multiple) {
			if (nu) {
				if (!old || !isCopy.call(nu, old)) {
					replaceCont.call(this.valueDOM,
						nu.sort(byNameLastModified.bind(this.type)).map(this._renderItem));
					if (this._required) this.castControlAttribute('required', false);
					changed = true;
					this.dom.classList.add('filled');
				}
			} else {
				clear.call(this.valueDOM);
				if (this._required) this.castControlAttribute('required', true);
				this.dom.classList.remove('filled');
			}
		} else if (nu !== old) {
			this.control.value = null;
			if (nu) {
				replaceCont.call(this.valueDOM, this._renderItem(nu));
				this.dom.classList.add('filled');
			} else {
				clear.call(this.valueDOM);
				this.dom.classList.remove('filled');
			}
			changed = true;
		}
		if (changed) {
			try {
				dispatchEvnt.call(this.control, 'change', eventOpts);
			} catch (ignore) {}
		} else {
			this.onChange();
		}
		this.updateRequired();
	}),
	value: d.gs(function () {
		var value = this.inputValue;
		if (value == null) return null;
		if (this.multiple) return value.map(this.type.toInputValue, this.type);
		return this.type.toInputValue(value);
	}, function (value) {
		if (value == null) {
			value = null;
		} else if (this.multiple) {
			if (isMap(value)) value = toArray(value).map(getMapValue);
			else value = toArray(value);
			if (value.length) {
				value = compact.call(value.map(this.type.toInputValue, this.type));
			}
			if (!value.length) value = null;
		} else {
			if (this.observable.descriptor.nested) value._name.on('change', this.onChange);
			value = this.type.toInputValue(value);
		}

		this.inputValue = value;
	}),
	updateRequired: d(function () {
		if (!this._required) return;
		this.castControlAttribute('required',
			aFrom(this.valueDOM.querySelectorAll('input[type=checkbox]')).every(function (input) {
				return input.checked;
			}));
	}),
	onChange: d(function () {
		var value, changed, valid, emitChanged, emitValid;
		if (this.control.form) {
			if (this.form !== this.control.form) {
				if (this.form) this.form.removeEventListener('reset', this._onReset, false);
				this.form = this.control.form;
				this.form.addEventListener('reset', this._onReset, false);
			}
		}
		value = this.inputValue;
		changed = aFrom(this.valueDOM.querySelectorAll('input[type=checkbox]')).some(function (input) {
			return input.checked;
		});
		changed = (this.multiple && (this._value != null) && (value != null))
			? isCopy.call(value, this._value) : (value !== this._value);
		valid = this.required ? (value != null) : true;

		if (this.changed !== changed) {
			this.changed = changed;
			emitChanged = true;
		}
		if (this.valid !== valid) {
			this.valid = valid;
			emitValid = true;
		}
		this.updateRequired();
		this.emit('change', value);
		if (emitChanged) this.emit('change:changed', this.changed);
		if (emitValid) this.emit('change:valid', this.valid);
	}),
	removeItem: d(function (dom) {
		remove.call(dom);
		if (!this.multiple) this.dom.classList.remove('filled');
		dispatchEvnt.call(this.control, 'change', eventOpts);
	})
}, autoBind({
	_onReset: d(function () {
		this.control.value = null;
		if (this.control.files && this.control.files.length) {
			// In Opera control is not reset properly, force it with hack
			getForceReset(this.document)(this.control);
		}
		aFrom(this.valueDOM.querySelectorAll('input[type=checkbox]')).every(function (input) {
			input.checked = false;
		});
		this.onChange();
	})
}), memoizeMethods({
	_renderItem: d(function (file) {
		var data;
		file = this.type.getById(file);
		data = this.renderItem(file);
		if (data.control) this.controls.push(data.control);
		return data.dom;
	})
})));

module.exports = memoize(function (db) {
	defineProperties(setup(db).File, {
		fromInputValue: d(function (value) {
			if (value == null) return null;
			if (value === '') return null;
			if (isArray(value) && (value.length === 2)) {
				if (typeof value[0] === 'string') {
					if (isObject(value[1])) return value[1];
				} else if (typeof value[1] === 'string') {
					if (isObject(value[0])) return value[0];
				}
				return value;
			}
			if (isObject(value)) return value;
			value = value.trim();
			if (!value) return null;
			return this.getById(value);
		}),
		DOMInput: d(Input),
		toDOMInput: d(function (document/*, options*/) {
			var options = Object(arguments[1]);
			if (options.multiple || (options.type !== 'checkbox')) {
				return new this.DOMInput(document, this, options);
			}
			return db.Object.toDOMInput(document, options);
		})
	});
}, { normalizer: getNormalizer() });

exports.Input = Input;
<commit_msg>Fix map value resolution<commit_after>'use strict';

var aFrom           = require('es5-ext/array/from')
  , compact         = require('es5-ext/array/#/compact')
  , isCopy          = require('es5-ext/array/#/is-copy')
  , pluck           = require('es5-ext/function/pluck')
  , copy            = require('es5-ext/object/copy')
  , assign          = require('es5-ext/object/assign')
  , isObject        = require('es5-ext/object/is-object')
  , callable        = require('es5-ext/object/valid-callable')
  , toArray         = require('es5-ext/array/to-array')
  , isMap           = require('es6-map/is-map')
  , d               = require('d')
  , autoBind        = require('d/auto-bind')
  , memoize         = require('memoizee/plain')
  , memoizeMethods  = require('memoizee/methods-plain')
  , getNormalizer   = require('memoizee/normalizers/get-1')
  , makeEl          = require('dom-ext/document/#/make-element')
  , append          = require('dom-ext/element/#/append')
  , clear           = require('dom-ext/element/#/clear')
  , remove          = require('dom-ext/element/#/remove')
  , replaceCont     = require('dom-ext/element/#/replace-content')
  , dispatchEvnt    = require('dom-ext/html-element/#/dispatch-event-2')
  , isNested        = require('dbjs/is-dbjs-nested-object')
  , resolveOptions  = require('../utils/resolve-options')
  , DOMInput        = require('../_controls/input')
  , eventOpts       = require('../_event-options')
  , setup           = require('../')

  , getMapValue = pluck(1)
  , isArray = Array.isArray, map = Array.prototype.map
  , defineProperty = Object.defineProperty
  , defineProperties = Object.defineProperties
  , getName = Object.getOwnPropertyDescriptor(DOMInput.prototype, 'name').get
  , filterEmpty = function (file) { return file.path; }
  , Input, render, renderItem, getTempForm, getForceReset;

getForceReset = memoize(function (document) {
	var form = document.createElement('form');
	return function (input) {
		var parent = input.parentNode, nextSibling = input.nextSibling;
		form.appendChild(input);
		form.reset();
		parent.insertBefore(input, nextSibling);
	};
}, { normalizer: getNormalizer() });

getTempForm = memoize(function (document) {
	var form = document.createElement('form');
	form.setAttribute('method', 'post');
	form.setAttribute('enctype', 'multipart/form-data');
	form.setAttribute('style', 'display: none');
	return form;
}, { normalizer: getNormalizer() });

render = function (options) {
	var el = this.make;
	return el('div', { class: 'dbjs-file' },
		this.valueDOM = this.multiple ? el('ul') : el('span'),
		el('label', { class: 'dbjs-file-input' }, options.label,
			this.control = el('input', { type: 'file' })));
};

renderItem = function (file) {
	var el = this.make, data = {}, name;
	data.dom = el(this.multiple ? 'li' : 'span', { 'data-id': file.__id__ });
	if (isNested(file)) name = file.__id__;
	else name = this.descriptor.__valueId__ + '*7' + file.__id__;
	append.call(data.dom,
		el('a', { href: file._url, target: '_blank' }, file._name), " ",
		el('label', { class: 'clear' },
			el('input', { type: 'checkbox', name: name, value: '' }), "x"));
	return data;
};

var byNameLastModified = function (f1, f2) {
	f1 = this.getById(f1);
	if (f1) f1 = f1.getDescriptor('name')._lastOwnModified_;
	f2 = this.getById(f2);
	if (f2) f2 = f2.getDescriptor('name')._lastOwnModified_;
	return (f1 || Infinity) - (f2 || Infinity);
};

Input = function (document, type/*, options*/) {
	var options = arguments[2], action;
	this.make = makeEl.bind(document);
	this.controls = [];
	this.type = type;
	options = resolveOptions(options, type);
	if (options.multiple) this.multiple = true;
	((options.render == null) || callable(options.render));
	defineProperty(this, 'renderItem', d((options.renderItem == null)
		? renderItem : callable(options.renderItem)));
	DOMInput.call(this, document, type, options);
	if (this.multiple) this.control.setAttribute('multiple', 'multiple');
	this.control.setAttribute('accept', toArray(type.accept).join(','));

	if (options.autoSubmit != null) {
		action = options.autoSubmit;
		this.dom.classList.add('auto-submit');
		this.on('change', function () {
			var form, parent, sibling;
			if (!this.changed) return;
			form = getTempForm(document);
			parent = this.dom.parentNode;
			sibling = this.dom.nextSibling;
			form.setAttribute('action', action);
			document.body.appendChild(form);
			form.appendChild(this.dom);
			dispatchEvnt.call(form, 'submit');
			parent.insertBefore(this.dom, sibling);
			if (form.parentNode) form.parentNode.removeChild(form);
		});
	}
	if (this._required) this.castControlAttribute('required', true);
	this.valueDOM.addEventListener('change', this.onChange, false);
};

Input.prototype = Object.create(DOMInput.prototype, assign({
	constructor: d(Input),
	multiple: d(false),
	_value: d(null),
	controlAttributes: d(assign(copy(DOMInput.prototype.controlAttributes),
		{ required: true })),
	dbAttributes: d(assign(copy(DOMInput.prototype.dbAttributes),
		{ required: true })),
	_render: d(function (options) {
		this.dom = (options.render || render).call(this, options);
		this.controls.push(this.control);
	}),
	name: d.gs(getName, function (name) {
		this._name = name;
		name = this.name;
		this.controls.forEach(function (input) { input.name = name; });
	}),
	inputValue: d.gs(function () {
		var value, item;
		if (!this.multiple) {
			if (this.control.files && this.control.files[0]) return this.control.files[0];
			item = this.valueDOM.firstElementChild;
			if (!item) return null;
			if (item.classList.contains('empty')) return null;
			if (item.querySelector('input[type=checkbox]').checked) return null;
			return this.valueDOM.firstElementChild.getAttribute('data-id');
		}
		value = compact.call(map.call(this.valueDOM.childNodes, function (item) {
			var id;
			if (item.classList.contains('empty')) return null;
			if (item.querySelector('input[type=checkbox]').checked) return null;
			id = item.getAttribute('data-id');
			if (!id) throw new TypeError("Missing id (data-id attribute) on file item");
			return id;
		})).concat(this.control.files ? aFrom(this.control.files) : []);
		return value.length ? value : null;
	}, function (nu) {
		var old = this.inputValue, changed;
		this._value = nu;
		if (this.multiple) {
			if (nu) {
				if (!old || !isCopy.call(nu, old)) {
					replaceCont.call(this.valueDOM,
						nu.sort(byNameLastModified.bind(this.type)).map(this._renderItem));
					if (this._required) this.castControlAttribute('required', false);
					changed = true;
					this.dom.classList.add('filled');
				}
			} else {
				clear.call(this.valueDOM);
				if (this._required) this.castControlAttribute('required', true);
				this.dom.classList.remove('filled');
			}
		} else if (nu !== old) {
			this.control.value = null;
			if (nu) {
				replaceCont.call(this.valueDOM, this._renderItem(nu));
				this.dom.classList.add('filled');
			} else {
				clear.call(this.valueDOM);
				this.dom.classList.remove('filled');
			}
			changed = true;
		}
		if (changed) {
			try {
				dispatchEvnt.call(this.control, 'change', eventOpts);
			} catch (ignore) {}
		} else {
			this.onChange();
		}
		this.updateRequired();
	}),
	value: d.gs(function () {
		var value = this.inputValue;
		if (value == null) return null;
		if (this.multiple) return value.map(this.type.toInputValue, this.type);
		return this.type.toInputValue(value);
	}, function (value) {
		if (value == null) {
			value = null;
		} else if (this.multiple) {
			if (isMap(value)) value = toArray(value).map(getMapValue).filter(filterEmpty);
			else value = toArray(value);
			if (value.length) {
				value = compact.call(value.map(this.type.toInputValue, this.type));
			}
			if (!value.length) value = null;
		} else {
			if (this.observable.descriptor.nested) value._name.on('change', this.onChange);
			value = this.type.toInputValue(value);
		}

		this.inputValue = value;
	}),
	updateRequired: d(function () {
		if (!this._required) return;
		this.castControlAttribute('required',
			aFrom(this.valueDOM.querySelectorAll('input[type=checkbox]')).every(function (input) {
				return input.checked;
			}));
	}),
	onChange: d(function () {
		var value, changed, valid, emitChanged, emitValid;
		if (this.control.form) {
			if (this.form !== this.control.form) {
				if (this.form) this.form.removeEventListener('reset', this._onReset, false);
				this.form = this.control.form;
				this.form.addEventListener('reset', this._onReset, false);
			}
		}
		value = this.inputValue;
		changed = aFrom(this.valueDOM.querySelectorAll('input[type=checkbox]')).some(function (input) {
			return input.checked;
		});
		changed = (this.multiple && (this._value != null) && (value != null))
			? isCopy.call(value, this._value) : (value !== this._value);
		valid = this.required ? (value != null) : true;

		if (this.changed !== changed) {
			this.changed = changed;
			emitChanged = true;
		}
		if (this.valid !== valid) {
			this.valid = valid;
			emitValid = true;
		}
		this.updateRequired();
		this.emit('change', value);
		if (emitChanged) this.emit('change:changed', this.changed);
		if (emitValid) this.emit('change:valid', this.valid);
	}),
	removeItem: d(function (dom) {
		remove.call(dom);
		if (!this.multiple) this.dom.classList.remove('filled');
		dispatchEvnt.call(this.control, 'change', eventOpts);
	})
}, autoBind({
	_onReset: d(function () {
		this.control.value = null;
		if (this.control.files && this.control.files.length) {
			// In Opera control is not reset properly, force it with hack
			getForceReset(this.document)(this.control);
		}
		aFrom(this.valueDOM.querySelectorAll('input[type=checkbox]')).every(function (input) {
			input.checked = false;
		});
		this.onChange();
	})
}), memoizeMethods({
	_renderItem: d(function (file) {
		var data;
		file = this.type.getById(file);
		data = this.renderItem(file);
		if (data.control) this.controls.push(data.control);
		return data.dom;
	})
})));

module.exports = memoize(function (db) {
	defineProperties(setup(db).File, {
		fromInputValue: d(function (value) {
			if (value == null) return null;
			if (value === '') return null;
			if (isArray(value) && (value.length === 2)) {
				if (typeof value[0] === 'string') {
					if (isObject(value[1])) return value[1];
				} else if (typeof value[1] === 'string') {
					if (isObject(value[0])) return value[0];
				}
				return value;
			}
			if (isObject(value)) return value;
			value = value.trim();
			if (!value) return null;
			return this.getById(value);
		}),
		DOMInput: d(Input),
		toDOMInput: d(function (document/*, options*/) {
			var options = Object(arguments[1]);
			if (options.multiple || (options.type !== 'checkbox')) {
				return new this.DOMInput(document, this, options);
			}
			return db.Object.toDOMInput(document, options);
		})
	});
}, { normalizer: getNormalizer() });

exports.Input = Input;
<|endoftext|>


<commit_before>import autobind from "autobind-decorator"
import ButtonToggleGroup from "components/ButtonToggleGroup"
import Leaflet from "components/Leaflet"
import ReportSummary from "components/ReportSummary"
import ReportTable from "components/ReportTable"
import UltimatePagination from "components/UltimatePagination"
import _escape from "lodash/escape"
import _get from "lodash/get"
import { Location, Person, Report } from "models"
import PropTypes from "prop-types"
import React, { Component } from "react"
import { Button } from "react-bootstrap"
import Calendar from "components/Calendar"
import moment from "moment"

export const FORMAT_CALENDAR = "calendar"
export const FORMAT_SUMMARY = "summary"
export const FORMAT_TABLE = "table"
export const FORMAT_MAP = "map"

export const GQL_REPORT_FIELDS = /* GraphQL */ `
  uuid, intent, engagementDate, duration, keyOutcomes, nextSteps, cancelledReason
  atmosphere, atmosphereDetails, state
  author { uuid, name, rank, role }
  primaryAdvisor { uuid, name, rank, role },
  primaryPrincipal { uuid, name, rank, role },
  advisorOrg { uuid, shortName },
  principalOrg { uuid, shortName },
  location { uuid, name, lat, lng },
  tasks { uuid, shortName },
  tags { uuid, name, description }
  workflow {
    type, createdAt
    step { uuid, name
      approvers { uuid, name, person { uuid, name, rank, role } }
    },
    person { uuid, name, rank, role }
  }
  updatedAt
`

export const GQL_BASIC_REPORT_FIELDS = /* GraphQL */ `
  uuid
  intent
  state
  location { uuid name lat lng }
`

export default class ReportCollection extends Component {
  static propTypes = {
    width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    marginBottom: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    reports: PropTypes.array,
    paginatedReports: PropTypes.shape({
      totalCount: PropTypes.number,
      pageNum: PropTypes.number,
      pageSize: PropTypes.number,
      list: PropTypes.array
    }),
    goToPage: PropTypes.func,
    mapId: PropTypes.string,
    viewFormats: PropTypes.arrayOf(PropTypes.string),
    hideButtons: PropTypes.bool
  }

  static defaultProps = {
    viewFormats: [FORMAT_CALENDAR, FORMAT_SUMMARY, FORMAT_TABLE, FORMAT_MAP]
  }
  static VIEW_FORMATS_WITH_PAGINATION = [FORMAT_SUMMARY, FORMAT_TABLE]

  calendarComponentRef = React.createRef()

  constructor(props) {
    super(props)

    this.state = {
      viewFormat: this.props.viewFormats[0]
    }
  }

  render() {
    var reports = []
    const viewWithPagination =
      ReportCollection.VIEW_FORMATS_WITH_PAGINATION.includes(
        this.state.viewFormat
      ) && this.props.paginatedReports !== null
    if (viewWithPagination) {
      var { pageSize, pageNum, totalCount } = this.props.paginatedReports
      var numPages = pageSize <= 0 ? 1 : Math.ceil(totalCount / pageSize)
      reports = this.props.paginatedReports.list
      pageNum++
    } else if (this.props.reports) {
      reports = this.props.reports
    }
    const reportsExist = _get(reports, "length", 0) > 0
    const showHeader = this.props.viewFormats.length > 1 || numPages > 1
    return (

          {showHeader && (

              {reportsExist && this.props.viewFormats.length > 1 && (
                <ButtonToggleGroup
                  value={this.state.viewFormat}
                  onChange={this.changeViewFormat}
                  className="hide-for-print"
                >
                  {this.props.viewFormats.includes(FORMAT_CALENDAR) && (
                    <Button value={FORMAT_CALENDAR}>Calendar</Button>
                  )}
                  {this.props.viewFormats.includes(FORMAT_SUMMARY) && (
                    <Button value={FORMAT_SUMMARY}>Summary</Button>
                  )}
                  {this.props.viewFormats.includes(FORMAT_TABLE) && (
                    <Button value={FORMAT_TABLE}>Table</Button>
                  )}
                  {this.props.viewFormats.includes(FORMAT_MAP) && (
                    <Button value={FORMAT_MAP}>Map</Button>
                  )}
                </ButtonToggleGroup>
              )}

              {viewWithPagination && numPages > 1 && (
                <UltimatePagination
                  className="pull-right"
                  currentPage={pageNum}
                  totalPages={numPages}
                  boundaryPagesRange={1}
                  siblingPagesRange={2}
                  hideEllipsis={false}
                  hidePreviousAndNextPageLinks={false}
                  hideFirstAndLastPageLinks
                  onChange={value => this.props.goToPage(value - 1)}
                />
              )}

              {this.props.reportsFilter && (

                  Filter: {this.props.reportsFilter}

              )}

          )}

          {reportsExist && (

              {this.state.viewFormat === FORMAT_CALENDAR &&
                this.renderCalendar(reports)}
              {this.state.viewFormat === FORMAT_TABLE &&
                this.renderTable(reports)}
              {this.state.viewFormat === FORMAT_SUMMARY &&
                this.renderSummary(reports)}
              {this.state.viewFormat === FORMAT_MAP && this.renderMap(reports)}

          )}

          {viewWithPagination && numPages > 1 && (

              <UltimatePagination
                className="pull-right"
                currentPage={pageNum}
                totalPages={numPages}
                boundaryPagesRange={1}
                siblingPagesRange={2}
                hideEllipsis={false}
                hidePreviousAndNextPageLinks={false}
                hideFirstAndLastPageLinks
                onChange={value => this.props.goToPage(value - 1)}
              />

          )}

        {!reportsExist && No reports found}

    )
  }

  renderTable(reports) {
    return <ReportTable showAuthors reports={reports} />
  }

  renderSummary(reports) {
    return (

        {reports.map(report => (
          <ReportSummary report={report} key={report.uuid} />
        ))}

    )
  }

  renderMap(reports) {
    let markers = []
    reports.forEach(report => {
      if (Location.hasCoordinates(report.location)) {
        let label = _escape(report.intent || "<undefined>") // escape HTML in intent!
        label += `<br/>@ <b>${_escape(report.location.name)}</b>` // escape HTML in locationName!
        markers.push({
          id: report.uuid,
          lat: report.location.lat,
          lng: report.location.lng,
          name: label
        })
      }
    })
    return (
      <Leaflet
        markers={markers}
        mapId={this.props.mapId}
        width={this.props.width}
        height={this.props.height}
        marginBottom={this.props.marginBottom}
      />
    )
  }

  getEvents = reports => {
    if (reports) {
      return reports.map(r => {
        const who =
          (r.primaryAdvisor && new Person(r.primaryAdvisor).toString()) || ""
        const where =
          (r.principalOrg && r.principalOrg.shortName) ||
          (r.location && r.location.name) ||
          ""

        return {
          title: who + "@" + where,
          start: moment(r.engagementDate).format("YYYY-MM-DD HH:mm"),
          end: moment(r.engagementDate)
            .add(r.duration, "minutes")
            .format("YYYY-MM-DD HH:mm"),
          url: Report.pathFor(r),
          classNames: ["event-" + r.state.toLowerCase()],
          extendedProps: { ...r },
          allDay: !!r.duration
        }
      })
    } else {
      return []
    }
  }

  renderCalendar(reports) {
    return (
      <Calendar
        events={this.getEvents(reports)}
        calendarComponentRef={this.calendarComponentRef}
      />
    )
  }

  @autobind
  changeViewFormat(value) {
    this.setState({ viewFormat: value })
  }
}

ReportCollection.GQL_REPORT_FIELDS = GQL_REPORT_FIELDS
<commit_msg>nci-agency/anet#1723: Add missing GraphQL fields needed for calendar in report collections<commit_after>import autobind from "autobind-decorator"
import ButtonToggleGroup from "components/ButtonToggleGroup"
import Leaflet from "components/Leaflet"
import ReportSummary from "components/ReportSummary"
import ReportTable from "components/ReportTable"
import UltimatePagination from "components/UltimatePagination"
import _escape from "lodash/escape"
import _get from "lodash/get"
import { Location, Person, Report } from "models"
import PropTypes from "prop-types"
import React, { Component } from "react"
import { Button } from "react-bootstrap"
import Calendar from "components/Calendar"
import moment from "moment"

export const FORMAT_CALENDAR = "calendar"
export const FORMAT_SUMMARY = "summary"
export const FORMAT_TABLE = "table"
export const FORMAT_MAP = "map"

export const GQL_REPORT_FIELDS = /* GraphQL */ `
  uuid, intent, engagementDate, duration, keyOutcomes, nextSteps, cancelledReason
  atmosphere, atmosphereDetails, state
  author { uuid, name, rank, role }
  primaryAdvisor { uuid, name, rank, role },
  primaryPrincipal { uuid, name, rank, role },
  advisorOrg { uuid, shortName },
  principalOrg { uuid, shortName },
  location { uuid, name, lat, lng },
  tasks { uuid, shortName },
  tags { uuid, name, description }
  workflow {
    type, createdAt
    step { uuid, name
      approvers { uuid, name, person { uuid, name, rank, role } }
    },
    person { uuid, name, rank, role }
  }
  updatedAt
`

export const GQL_BASIC_REPORT_FIELDS = /* GraphQL */ `
  uuid
  intent
  primaryAdvisor { name }
  principalOrg { shortName }
  engagementDate, duration
  state
  location { uuid name lat lng }
`

export default class ReportCollection extends Component {
  static propTypes = {
    width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    marginBottom: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    reports: PropTypes.array,
    paginatedReports: PropTypes.shape({
      totalCount: PropTypes.number,
      pageNum: PropTypes.number,
      pageSize: PropTypes.number,
      list: PropTypes.array
    }),
    goToPage: PropTypes.func,
    mapId: PropTypes.string,
    viewFormats: PropTypes.arrayOf(PropTypes.string),
    hideButtons: PropTypes.bool
  }

  static defaultProps = {
    viewFormats: [FORMAT_CALENDAR, FORMAT_SUMMARY, FORMAT_TABLE, FORMAT_MAP]
  }
  static VIEW_FORMATS_WITH_PAGINATION = [FORMAT_SUMMARY, FORMAT_TABLE]

  calendarComponentRef = React.createRef()

  constructor(props) {
    super(props)

    this.state = {
      viewFormat: this.props.viewFormats[0]
    }
  }

  render() {
    var reports = []
    const viewWithPagination =
      ReportCollection.VIEW_FORMATS_WITH_PAGINATION.includes(
        this.state.viewFormat
      ) && this.props.paginatedReports !== null
    if (viewWithPagination) {
      var { pageSize, pageNum, totalCount } = this.props.paginatedReports
      var numPages = pageSize <= 0 ? 1 : Math.ceil(totalCount / pageSize)
      reports = this.props.paginatedReports.list
      pageNum++
    } else if (this.props.reports) {
      reports = this.props.reports
    }
    const reportsExist = _get(reports, "length", 0) > 0
    const showHeader = this.props.viewFormats.length > 1 || numPages > 1
    return (

          {showHeader && (

              {reportsExist && this.props.viewFormats.length > 1 && (
                <ButtonToggleGroup
                  value={this.state.viewFormat}
                  onChange={this.changeViewFormat}
                  className="hide-for-print"
                >
                  {this.props.viewFormats.includes(FORMAT_CALENDAR) && (
                    <Button value={FORMAT_CALENDAR}>Calendar</Button>
                  )}
                  {this.props.viewFormats.includes(FORMAT_SUMMARY) && (
                    <Button value={FORMAT_SUMMARY}>Summary</Button>
                  )}
                  {this.props.viewFormats.includes(FORMAT_TABLE) && (
                    <Button value={FORMAT_TABLE}>Table</Button>
                  )}
                  {this.props.viewFormats.includes(FORMAT_MAP) && (
                    <Button value={FORMAT_MAP}>Map</Button>
                  )}
                </ButtonToggleGroup>
              )}

              {viewWithPagination && numPages > 1 && (
                <UltimatePagination
                  className="pull-right"
                  currentPage={pageNum}
                  totalPages={numPages}
                  boundaryPagesRange={1}
                  siblingPagesRange={2}
                  hideEllipsis={false}
                  hidePreviousAndNextPageLinks={false}
                  hideFirstAndLastPageLinks
                  onChange={value => this.props.goToPage(value - 1)}
                />
              )}

              {this.props.reportsFilter && (

                  Filter: {this.props.reportsFilter}

              )}

          )}

          {reportsExist && (

              {this.state.viewFormat === FORMAT_CALENDAR &&
                this.renderCalendar(reports)}
              {this.state.viewFormat === FORMAT_TABLE &&
                this.renderTable(reports)}
              {this.state.viewFormat === FORMAT_SUMMARY &&
                this.renderSummary(reports)}
              {this.state.viewFormat === FORMAT_MAP && this.renderMap(reports)}

          )}

          {viewWithPagination && numPages > 1 && (

              <UltimatePagination
                className="pull-right"
                currentPage={pageNum}
                totalPages={numPages}
                boundaryPagesRange={1}
                siblingPagesRange={2}
                hideEllipsis={false}
                hidePreviousAndNextPageLinks={false}
                hideFirstAndLastPageLinks
                onChange={value => this.props.goToPage(value - 1)}
              />

          )}

        {!reportsExist && No reports found}

    )
  }

  renderTable(reports) {
    return <ReportTable showAuthors reports={reports} />
  }

  renderSummary(reports) {
    return (

        {reports.map(report => (
          <ReportSummary report={report} key={report.uuid} />
        ))}

    )
  }

  renderMap(reports) {
    let markers = []
    reports.forEach(report => {
      if (Location.hasCoordinates(report.location)) {
        let label = _escape(report.intent || "<undefined>") // escape HTML in intent!
        label += `<br/>@ <b>${_escape(report.location.name)}</b>` // escape HTML in locationName!
        markers.push({
          id: report.uuid,
          lat: report.location.lat,
          lng: report.location.lng,
          name: label
        })
      }
    })
    return (
      <Leaflet
        markers={markers}
        mapId={this.props.mapId}
        width={this.props.width}
        height={this.props.height}
        marginBottom={this.props.marginBottom}
      />
    )
  }

  getEvents = reports => {
    if (reports) {
      return reports.map(r => {
        const who =
          (r.primaryAdvisor && new Person(r.primaryAdvisor).toString()) || ""
        const where =
          (r.principalOrg && r.principalOrg.shortName) ||
          (r.location && r.location.name) ||
          ""

        return {
          title: who + "@" + where,
          start: moment(r.engagementDate).format("YYYY-MM-DD HH:mm"),
          end: moment(r.engagementDate)
            .add(r.duration, "minutes")
            .format("YYYY-MM-DD HH:mm"),
          url: Report.pathFor(r),
          classNames: ["event-" + r.state.toLowerCase()],
          extendedProps: { ...r },
          allDay: !!r.duration
        }
      })
    } else {
      return []
    }
  }

  renderCalendar(reports) {
    return (
      <Calendar
        events={this.getEvents(reports)}
        calendarComponentRef={this.calendarComponentRef}
      />
    )
  }

  @autobind
  changeViewFormat(value) {
    this.setState({ viewFormat: value })
  }
}

ReportCollection.GQL_REPORT_FIELDS = GQL_REPORT_FIELDS
<|endoftext|>


<commit_before>/**
 * Created by Michael on 16/07/15.
 */
console.log('Loading function');
var colors = require('colors');
var request = require('request');
var async = require('async');
var aws = require('aws-sdk');
var s3 = new aws.S3();//{apiVersion: '2006-03-01'});
var JSZip = require("jszip");
var path = require("path");
var getFileType = require('file-type');
var crypto = require('crypto');
var uuid = require('uuid');
var fs = require('fs');

var settings = {
    endpoints : {
        auth : "http://api.local.comiccloud.io/v0.1/oauth/access_token",
        images : "http://api.local.comiccloud.io/v0.1/images",
        s3_base : "https://s3.amazonaws.com"
    },
    param: {
        grant_type : "client_credentials",//TODO: Move to environment variables
        client_id : "test_processor_id",
        client_secret : "test_processor_secret",
        scope: "processor"
    },
    access_token : null
};

exports.handler = function(event, context) {

    console.log( "Running index.handler" );

    var user_upload_bucket = process.env.AWS_S3_Uploads;//event.bucket_name;//TODO:Change this back before posting!
    var user_upload_key = event.file_name;
    var cba_id = event.cba_id;

    async.waterfall([
        function(callback) {//1 - Authorise
            console.log("Authenticating Client".green);

            request.post(settings.endpoints.auth , {form: settings.param}, function (error, response, body) {//TODO: This should eventually be a JSON raw body not a form
                body = JSON.parse(body);
                if (!error && response.statusCode == 200) {
                    settings.access_token = body.access_token;
                    console.log("Client successfully authenticated".green)
                    callback();
                }else{
                    context.fail(("Client authentication failed: " + JSON.parse(error)).red);
                }
            });
        },
        function(callback) {//2 - Download Archive
            console.log("Retrieving file".green);
            s3.getObject({Bucket: user_upload_bucket, Key: user_upload_key}, function(err, data) {//Retrieve Upload
                if (err) {
                    console.log("Error getting object " + user_upload_key + " from bucket " + user_upload_bucket +
                    ".\nMake sure they exist and your bucket is in the same region as this function.".red);
                    context.fail("Error getting file: " + JSON.stringify(err).red);
                } else {
                    console.log('File successfully retrieved.');
                    callback(null, data);
                }
            });
        },
        function(filestream, callback){//3 - Process Archive
            console.log('Processing Comic Book Archive'.green);

            var zip = new JSZip(filestream.Body);//Load archive into JSZip

            var pages = [];

            async.forEachOf(zip.files, function (file, filename, callback) {
                console.log("Processing file: ".green + filename.blue);
                if(file.dir === true){
                    console.log('Directory found.');
                    return callback();
                }

                var fileExt = path.extname(filename).split('.').join('');
                var acceptedExtensions = ['jpg', 'jpeg'];

                if(!acceptedExtensions.hasObject(fileExt)){
                    console.log('Unaccepted File type \'' + fileExt + '\' found.');
                    return callback();
                }

                var fileType = getFileType(file.asNodeBuffer());
                var basename = path.basename(filename, path.extname(filename));
                var fileSize = 1;//TODO: File size check.

                var user_images_uploads = process.env.AWS_S3_Images;
                var user_images_uploads_key_without_ext = uuid.v4();
                var user_images_uploads_key = user_images_uploads_key_without_ext + "." + fileExt;
                var user_images_uploads_body = file.asNodeBuffer();

                var fileHash = crypto.createHash('md5').update(user_images_uploads_body).digest('hex');
                var image_exists = false;

                var image_id = "";

                async.waterfall([
                    function(callback){//Check if image exists
                        request.get(settings.endpoints.images + "?image_hash=" + fileHash, { headers : {'Authorization' : settings.access_token}}, function (error, response, body) {
                            if (error) {
                                console.log("Error getting object " + user_upload_key + " from bucket " + user_upload_bucket +
                                ".\nMake sure they exist and your bucket is in the same region as this function.".red);
                                context.fail("Error getting file: " + JSON.stringify(err).red);
                            }else {
                                callback(null, JSON.parse(body))
                            }
                        });

                    },
                    function(response, callback){
                        if(response.total == 0){//Post Image to Storage

                            console.log("Image Match Not Found".blue);

                            var params = {
                                Bucket: user_images_uploads,
                                Key: user_images_uploads_key,
                                Body: user_images_uploads_body,
                                ACL: 'public-read' //TODO: Change to 'authenticated-read' on production. Also maybe extract to variable
                            };

                            s3.putObject(params, function(err, data) {
                                if (err) {
                                    console.log(("Error putting object " + user_images_uploads_key + " into bucket " + user_images_uploads +
                                    ".\nMake sure they exist and your bucket is in the same region as this function.").red);
                                    context.fail(("Error getting file: " + JSON.stringify(err)).red);
                                } else {
                                    console.log("Image successfully uploaded".green);

                                    var upload_url = settings.endpoints.s3_base + "/"+ user_images_uploads + "/" +user_images_uploads_key; //TODO: This ideally needs to something returned from S3's upload
                                    var new_image_request = {
                                        "image_slug" : user_images_uploads_key_without_ext,
                                        "image_hash" : fileHash,
                                        "image_url" : upload_url,
                                        "image_size" : 1,
                                        "related_comic_book_archive_id" : cba_id
                                    };
                                    request.post(settings.endpoints.images , {body : new_image_request, json : true, headers : {'Authorization' : settings.access_token}}, function (error, response, body) {//TODO: This should eventually be a JSON raw body not a form
                                        console.log(error);
                                        console.log(body);
                                        callback();
                                    });

                                }

                            });

                        }else{
                            /*console.log('Image Match Found'.green);
                            dupe_image = response.images[0];

                            image_exists = true;

                            callback(null, pivot_entry);*/
                            callback();
                        }

                    }
                ], function(err, result){
                    callback();
                });
            }, function(err){
                callback(null, pages);

            });
        }
    ],
    function(err, results){
        context.succeed('Comic Book Archive successfully processed.'.green);

    });

};

Array.prototype.hasObject = (
    !Array.indexOf ? function (o)
    {
        var l = this.length + 1;
        while (l -= 1)
        {
            if (this[l - 1] === o)
            {
                return true;
            }
        }
        return false;
    } : function (o)
    {
        return (this.indexOf(o) !== -1);
    }
);
Array.prototype.toObject = function(){
    var arr = this;
    var rv = {};
    for (var i = 0; i < arr.length; ++i)
        rv[i] = arr[i];
    return rv;
};
<commit_msg>Added cba route. Begun implementing put method to attach duplicates<commit_after>/**
 * Created by Michael on 16/07/15.
 */
console.log('Loading function');
var colors = require('colors');
var request = require('request');
var async = require('async');
var aws = require('aws-sdk');
var s3 = new aws.S3();//{apiVersion: '2006-03-01'});
var JSZip = require("jszip");
var path = require("path");
var getFileType = require('file-type');
var crypto = require('crypto');
var uuid = require('uuid');
var fs = require('fs');

var settings = {
    endpoints : {
        auth : "http://api.local.comiccloud.io/v0.1/oauth/access_token",
        images : "http://api.local.comiccloud.io/v0.1/images",
        cba : "http://api.local.comiccloud.io/v0.1/comicbookarchives",
        s3_base : "https://s3.amazonaws.com"
    },
    param: {
        grant_type : "client_credentials",//TODO: Move to environment variables
        client_id : "test_processor_id",
        client_secret : "test_processor_secret",
        scope: "processor"
    },
    access_token : null
};

exports.handler = function(event, context) {

    console.log( "Running index.handler" );

    var user_upload_bucket = process.env.AWS_S3_Uploads;//event.bucket_name;//TODO:Change this back before posting!
    var user_upload_key = event.file_name;
    var cba_id = event.cba_id;

    async.waterfall([
        function(callback) {//1 - Authorise
            console.log("Authenticating Client".green);

            request.post(settings.endpoints.auth , {form: settings.param}, function (error, response, body) {//TODO: This should eventually be a JSON raw body not a form
                body = JSON.parse(body);
                if (!error && response.statusCode == 200) {
                    settings.access_token = body.access_token;
                    console.log("Client successfully authenticated".green)
                    callback();
                }else{
                    context.fail(("Client authentication failed: " + JSON.parse(error)).red);
                }
            });
        },
        function(callback) {//2 - Download Archive
            console.log("Retrieving file".green);
            s3.getObject({Bucket: user_upload_bucket, Key: user_upload_key}, function(err, data) {//Retrieve Upload
                if (err) {
                    console.log("Error getting object " + user_upload_key + " from bucket " + user_upload_bucket +
                    ".\nMake sure they exist and your bucket is in the same region as this function.".red);
                    context.fail("Error getting file: " + JSON.stringify(err).red);
                } else {
                    console.log('File successfully retrieved.');
                    callback(null, data);
                }
            });
        },
        function(filestream, callback){//3 - Process Archive
            console.log('Processing Comic Book Archive'.green);

            var zip = new JSZip(filestream.Body);//Load archive into JSZip

            var pages = [];

            async.forEachOf(zip.files, function (file, filename, callback) {
                console.log("Processing file: ".green + filename.blue);
                if(file.dir === true){
                    console.log('Directory found.');
                    return callback();
                }

                var fileExt = path.extname(filename).split('.').join('');
                var acceptedExtensions = ['jpg', 'jpeg'];

                if(!acceptedExtensions.hasObject(fileExt)){
                    console.log('Unaccepted File type \'' + fileExt + '\' found.');
                    return callback();
                }

                var fileType = getFileType(file.asNodeBuffer());
                var basename = path.basename(filename, path.extname(filename));
                var fileSize = 1;//TODO: File size check.

                var user_images_uploads = process.env.AWS_S3_Images;
                var user_images_uploads_key_without_ext = uuid.v4();
                var user_images_uploads_key = user_images_uploads_key_without_ext + "." + fileExt;
                var user_images_uploads_body = file.asNodeBuffer();

                var fileHash = crypto.createHash('md5').update(user_images_uploads_body).digest('hex');
                var image_exists = false;

                var image_id = "";

                async.waterfall([
                    function(callback){//Check if image exists
                        request.get(settings.endpoints.images + "?image_hash=" + fileHash, { headers : {'Authorization' : settings.access_token}}, function (error, response, body) {
                            if (error) {
                                console.log("Error getting object " + user_upload_key + " from bucket " + user_upload_bucket +
                                ".\nMake sure they exist and your bucket is in the same region as this function.".red);
                                context.fail("Error getting file: " + JSON.stringify(err).red);
                            }else {
                                callback(null, JSON.parse(body))
                            }
                        });

                    },
                    function(response, callback){
                        if(response.total == 0){//Post Image to Storage

                            console.log("Image Match Not Found".green);

                            var params = {
                                Bucket: user_images_uploads,
                                Key: user_images_uploads_key,
                                Body: user_images_uploads_body,
                                ACL: 'public-read' //TODO: Change to 'authenticated-read' on production. Also maybe extract to variable
                            };

                            s3.putObject(params, function(err, data) {
                                if (err) {
                                    console.log(("Error putting object " + user_images_uploads_key + " into bucket " + user_images_uploads +
                                    ".\nMake sure they exist and your bucket is in the same region as this function.").red);
                                    context.fail(("Error getting file: " + JSON.stringify(err)).red);
                                } else {
                                    console.log("Image successfully uploaded".green);

                                    var upload_url = settings.endpoints.s3_base + "/"+ user_images_uploads + "/" +user_images_uploads_key; //TODO: This ideally needs to something returned from S3's upload
                                    var new_image_request = {
                                        "image_slug" : user_images_uploads_key_without_ext,
                                        "image_hash" : fileHash,
                                        "image_url" : upload_url,
                                        "image_size" : 1,
                                        "related_comic_book_archive_id" : cba_id
                                    };
                                    request.post(settings.endpoints.images , {body : new_image_request, json : true, headers : {'Authorization' : settings.access_token}}, function (error, response, body) {//TODO: This should eventually be a JSON raw body not a form
                                        console.log(error);
                                        console.log(body);
                                        callback();
                                    });

                                }

                            });

                        }else{
                            console.log('Image Match Found'.blue);
                            console.log(response.images[0].id);
                            /*request.put(settings.endpoints.cba , {body : { "attach_image_id" : ""}, json : true, headers : {'Authorization' : settings.access_token}}, function (error, response, body) {//TODO: This should eventually be a JSON raw body not a form
                                console.log(error);
                                console.log(body);
                                callback();
                            });*/
                            callback();
                        }

                    }
                ], function(err, result){
                    callback();
                });
            }, function(err){
                callback(null, pages);

            });
        }
    ],
    function(err, results){
        context.succeed('Comic Book Archive successfully processed.'.green);

    });

};

Array.prototype.hasObject = (
    !Array.indexOf ? function (o)
    {
        var l = this.length + 1;
        while (l -= 1)
        {
            if (this[l - 1] === o)
            {
                return true;
            }
        }
        return false;
    } : function (o)
    {
        return (this.indexOf(o) !== -1);
    }
);
Array.prototype.toObject = function(){
    var arr = this;
    var rv = {};
    for (var i = 0; i < arr.length; ++i)
        rv[i] = arr[i];
    return rv;
};
<|endoftext|>


<commit_before>/*****************************************************************************/
/* PagesShow: Event Handlers and Helpersss .js*/
/*****************************************************************************/
Template.PagesShow.events({
  /*
   * Example:
   *  'click .selector': function (e, tmpl) {
   *
   *  }
   */
  'click #new-paragraph-action': function (e) {
    e.preventDefault();

    Session.set('newParagraph', this._id);
  }
});

Template.PagesShow.helpers({
  /*
   * Example:
   *  items: function () {
   *    return Items.find();
   *  }
   */

  paragraphs: function () {
    var paragraphsOrder = this.paragraphsOrder || 1;
    return Paragraphs.find({}, { sort: { rank: paragraphsOrder } });
  },

  editTitle: function () {
    if (Meteor.user() && Session.get('editTitle') === this._id) {
      return true;
    } else {
      return false;
    }
  },

  editParagraph: function () {
    if (Meteor.user() && Session.get('editParagraph') === this._id) {
      return true;
    } else {
      return false;
    }
  },

  showComments: function () {
    var settings = Settings.findOne();
    var page = Pages.findOne();

    if (settings.disqusShortname && page.disqus) {
      return true;
    } else {
      return false;
    }
  },

  liveBlogging: function () {
    var page = Pages.findOne();

    if (page.paragraphsOrder === -1) {
      return true;
    } else {
      return false;
    }
  }
});

/*****************************************************************************/
/* PagesShow: Lifecycle Hooks */
/*****************************************************************************/
Template.PagesShow.created = function () {
};

Template.PagesShow.rendered = function () {
  Session.set('editTitle', null);
  Session.set('newParagraph', null);
  Session.set('editParagraph', null);
  Session.set('pageSettings', null);

  if (Session.get('smartEditor') === undefined) {
    Session.set('smartEditor', true);
  }

  // set up Google Analytics for pages
  var settings = Settings.findOne();
  var controller = Iron.controller();

  console.dir(controller);
  console.log(controller.url);

  if (settings.googleTrackingId) {
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', settings.googleTrackingId, 'auto');
    ga('send', 'pageview', {
      'page': controller.url
    });
  }

};

Template.PagesShow.destroyed = function () {
};
<commit_msg>Use directly the params._id<commit_after>/*****************************************************************************/
/* PagesShow: Event Handlers and Helpersss .js*/
/*****************************************************************************/
Template.PagesShow.events({
  /*
   * Example:
   *  'click .selector': function (e, tmpl) {
   *
   *  }
   */
  'click #new-paragraph-action': function (e) {
    e.preventDefault();

    Session.set('newParagraph', this._id);
  }
});

Template.PagesShow.helpers({
  /*
   * Example:
   *  items: function () {
   *    return Items.find();
   *  }
   */

  paragraphs: function () {
    var paragraphsOrder = this.paragraphsOrder || 1;
    return Paragraphs.find({}, { sort: { rank: paragraphsOrder } });
  },

  editTitle: function () {
    if (Meteor.user() && Session.get('editTitle') === this._id) {
      return true;
    } else {
      return false;
    }
  },

  editParagraph: function () {
    if (Meteor.user() && Session.get('editParagraph') === this._id) {
      return true;
    } else {
      return false;
    }
  },

  showComments: function () {
    var settings = Settings.findOne();
    var page = Pages.findOne();

    if (settings.disqusShortname && page.disqus) {
      return true;
    } else {
      return false;
    }
  },

  liveBlogging: function () {
    var page = Pages.findOne();

    if (page.paragraphsOrder === -1) {
      return true;
    } else {
      return false;
    }
  }
});

/*****************************************************************************/
/* PagesShow: Lifecycle Hooks */
/*****************************************************************************/
Template.PagesShow.created = function () {
};

Template.PagesShow.rendered = function () {
  Session.set('editTitle', null);
  Session.set('newParagraph', null);
  Session.set('editParagraph', null);
  Session.set('pageSettings', null);

  if (Session.get('smartEditor') === undefined) {
    Session.set('smartEditor', true);
  }

  // set up Google Analytics for pages
  var settings = Settings.findOne();
  var controller = Iron.controller();

  if (settings.googleTrackingId) {
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', settings.googleTrackingId, 'auto');
    ga('send', 'pageview', {
      'page': '/pages/' + controller.params._id
    });
  }

};

Template.PagesShow.destroyed = function () {
};
<|endoftext|>


<commit_before>(function($){
  'use strict';

  /* Plugin constants. */
  var ENTER_KEY_CODE = 13;
  var SPACE_KEY_CODE = 32;

  /* Plugin variables. */
  var pluginName  = 'contentToggle';
  var instances = {};
  var defaultOptions = {};
  var $global = $(document);
  var isIthing = navigator.userAgent.match(/iPad|iPhone/i);
  var sanitize = /[^a-z0-9_-]/gi;
  var uid = 0;
  var gid = 0;

  /* Plugin default options. */
  defaultOptions = {
    defaultState: null,
    globalClose: false,
    independent: false,
    beforeCallback: null,
    triggerSelector: '.js-contentToggle__trigger',
    triggerSelectorContext: true,
    contentSelector: '.js-contentToggle__content',
    contentSelectorContext: true,
    elementClass: 'is-open',
    triggerClass: 'is-active',
    toggleProperties: ['height'],
    toggleOptions: {
      duration: 0
    }
  };

  /**
   * Plugin Constructor.
   *
   * @param {Node|jQuery} element
   *   Main DOM element.
   * @param {string} selector
   *   Element initial selector.
   * @param {object} options
   *   Instance specific options.
   */
  function Plugin(element, selector, options) {
    var data;

    // Merge specific and default options.
    this.options = {
      group: selector
    };
    $.extend(this.options, defaultOptions, options);

    // Initialize data.
    this.$element = (element instanceof $)? element: $(element);
    this.uid = ++uid;

    // Data initialization.
    this.setup();

    // Empty object initialization.
    data = this.$element.data(pluginName);
    if (!instances[this.options.group]) {
      instances[this.options.group] = {};
    }
    if (!data) {
      data = {};
    }

    // Check if instance has not been already initialized.
    if (!data[this.options.group]) {
      // Save the new instance.
      instances[this.options.group][this.uid] = this;
      data[this.options.group] = this;
      this.$element.data(pluginName, data);

      // Plugin initialization.
      this.bind();
      this.init();
    }
  }

  /**
   * Setup plugin.
   * e.g. Get DOM elements, setup data...
   */
  Plugin.prototype.setup = function() {
    this.setupDataOptions();

    // Sanitize group name.
    if (this.options.group) {
      this.options.group = this.options.group.toString().replace(sanitize, '');
    }

    // Parse JSON options.
    if (typeof this.options.toggleProperties == 'string') {
      this.options.toggleProperties = JSON.parse(this.options.toggleProperties);
    }
    if (typeof this.options.toggleOptions == 'string') {
      this.options.toggleOptions = JSON.parse(this.options.toggleOptions);
    }

    // Get trigger elements.
    if (this.options.triggerSelectorContext) {
      this.$triggers = $(this.options.triggerSelector, this.$element);
    } else {
      this.$triggers = $(this.options.triggerSelector);
    }
    if (this.$triggers.length === 0) {
      this.$triggers = this.$element;
    }

    // Get content elements.
    if (this.options.contentSelectorContext) {
      this.$contents = $(this.options.contentSelector, this.$element);
    } else {
      this.$contents = $(this.options.contentSelector);
    }

    // Get callback.
    if (typeof this.options.beforeCallback == 'string' &&
        window[this.options.beforeCallback] &&
        typeof window[this.options.beforeCallback] == 'function') {
      this.options.beforeCallback = window[this.options.beforeCallback].bind(this);
    } else if (typeof this.options.beforeCallback == 'function') {
      this.options.beforeCallback = this.options.beforeCallback.bind(this);
    }
  };

  /**
   * Setup plugin specific data.
   * e.g. Get DOM elements, setup data...
   */
  Plugin.prototype.setupDataOptions = function() {
    $.each(
      this.$element.data(),
      function(index, value){
        if (index in defaultOptions) {
          this.options[index] = value;
        }
      }.bind(this)
    );
  };

  /**
   * Bind events.
   */
  Plugin.prototype.bind = function() {
    var namespaces = '.' + pluginName + '.' + this.options.group;
    var eventName = (isIthing && this.options.globalClose)? 'touchstart': 'click';
    var $all = this.$element.add(this.$triggers).add(this.$contents);

    // Bind custom events on all elements.
    $all.on('destroy' + namespaces, this.destroy.bind(this));
    $all.on('toggle' + namespaces, $.proxy(this.toggle, this, null));
    $all.on('close' + namespaces, $.proxy(this.toggle, this, false));
    $all.on('open' + namespaces, $.proxy(this.toggle, this, true));
    $all.on('isOpen' + namespaces, function(){
      return this.isOpen;
    }.bind(this));

    // Bind native events on triggers.
    this.$triggers.on(eventName + namespaces, function(event){
      event.preventDefault();
      this.toggle(null, event);
    }.bind(this));
    this.$triggers.on('keydown' + namespaces, function(event){
      if (event.keyCode == ENTER_KEY_CODE || event.keyCode == SPACE_KEY_CODE) {
        event.preventDefault();
        this.toggle(null, event);
      }
    }.bind(this));

    // Bind native events on contents (avoid triggers click event).
    this.$contents.on(eventName + namespaces, function(event){
      event.stopPropagation();
    });
  };

  /**
   * Initialize default plugin state.
   */
  Plugin.prototype.init = function() {
    // Initialize triggers IDs.
    this.tid = [];
    this.$triggers.each($.proxy(this.initId, this, this.tid, 'contentToggle__trigger'));

    // Initialize contents IDs.
    this.cid = [];
    this.$contents.each($.proxy(this.initId, this, this.cid, 'contentToggle__content'));

    // Initialize triggers attributes.
    this.$triggers.each(function(index, element){
      if (element.tagName != 'BUTTON') {
        this.$triggers.eq(index).attr('role', 'button');
      }
    });
    this.$triggers.attr('tabindex', '0');
    this.$triggers.attr('aria-controls', this.cid.join(' '));

    // Default plugin state.
    if ($.inArray(this.options.defaultState, ['open', 'close']) !== -1) {
      this.$element.trigger(this.options.defaultState + '.' + pluginName);
    } else {
      this.isOpen = this.$contents.is(':visible');
      this.update();
    }
  };

  /**
   * Initialize element id.
   */
  Plugin.prototype.initId = function(ids, prefix, index, element) {
    var $element = $(element);
    ids[index] = $element.attr('id');
    if (!ids[index]) {
      ids[index] = prefix + '-' + this.uid + '-' + index;
      $element.attr('id', ids[index]);
    }
  };

  /**
   * Toggle content.
   *
   * @param {boolean} state
   *   The state of the wanted display.
   * @param {Event} event
   *   The event object.
   */
  Plugin.prototype.toggle = function(state, event) {
    event.stopPropagation();

    if (typeof state != 'boolean') {
      state = !this.isOpen;
    }

    this.$currentTrigger = null;
    if (this.$triggers.is(event.currentTarget)) {
      this.$currentTrigger = $(event.currentTarget);
    }

    if (!this.options.beforeCallback ||
        (typeof this.options.beforeCallback == 'function' &&
         this.options.beforeCallback(event))) {
      if (state) {
        this.open();
      } else {
        this.close();
      }
    }
  };

  /**
   * Open content.
   */
  Plugin.prototype.open = function() {
    var eventName;
    if (this.isOpen !== true) {
      this.isOpen = true;
      this.do();
      this.closeAll(true);
      if (this.options.globalClose) {
        eventName = isIthing? 'touchstart': 'click';
        $global.on(eventName + '.' + pluginName + this.uid, function(){
          this.closeAll();
        }.bind(this));
      }
    }
  };

  /**
   * Close content.
   */
  Plugin.prototype.close = function() {
    if (this.isOpen !== false) {
      this.isOpen = false;
      this.do();
      $global.off('.' + pluginName + this.uid);
    }
  };

  /**
   * Close all binded instances.
   *
   * @param {boolean} butItself
   *   Close all but itself or not.
   */
  Plugin.prototype.closeAll = function(butItself) {
    if (!this.options.independent) {
      $.each(instances[this.options.group], function(uid, instance){
        if (uid != this.uid) {
          instance.close();
        }
      }.bind(this));
    }
    if (!butItself) {
      this.close();
    }
  };

  /**
   * Perform toggle action.
   */
  Plugin.prototype.do = function() {
    var toggleProperties = {};
    var action = this.isOpen? 'show': 'hide';

    this.update();

    $.each(
      this.options.toggleProperties,
      function(index, value){
        toggleProperties[value] = action;
      }
    );

    this.$contents.stop().animate(
      toggleProperties,
      this.options.toggleOptions
    );
  };

  /**
   * Update classes and aria data.
   */
  Plugin.prototype.update = function() {
    if (this.isOpen) {
      this.$element.addClass(this.options.elementClass);
      this.$contents.attr('aria-hidden', false);
      this.$triggers.attr('aria-expanded', true);
      if (this.$currentTrigger) {
        this.$currentTrigger.addClass(this.options.triggerClass);
      } else {
        this.$triggers.addClass(this.options.triggerClass);
      }
    } else {
      this.$element.removeClass(this.options.elementClass);
      this.$contents.attr('aria-hidden', true);
      this.$triggers.attr('aria-expanded', false);
      this.$triggers.removeClass(this.options.triggerClass);
    }
  };

  /**
   * Destroy events.
   */
  Plugin.prototype.destroy = function() {
    this.$element.removeData(pluginName);
    this.$element.off('.' + pluginName);
    this.$triggers.off('.' + pluginName);
    this.$contents.off('.' + pluginName);
    $global.off('.' + pluginName + this.uid);
  };

  /* Expose jQuery plugin. */
  $.fn[pluginName] = function(options) {
    var selector = this.selector;
    return this.each(function() {
      new Plugin(this, selector, options);
    });
  };
})(jQuery);
<commit_msg>Correction for firefox when using the space key.<commit_after>(function($){
  'use strict';

  /* Plugin constants. */
  var ENTER_KEY_CODE = 13;
  var SPACE_KEY_CODE = 32;

  /* Plugin variables. */
  var pluginName  = 'contentToggle';
  var instances = {};
  var defaultOptions = {};
  var $global = $(document);
  var isIthing = navigator.userAgent.match(/iPad|iPhone/i);
  var sanitize = /[^a-z0-9_-]/gi;
  var uid = 0;
  var gid = 0;

  /* Plugin default options. */
  defaultOptions = {
    defaultState: null,
    globalClose: false,
    independent: false,
    beforeCallback: null,
    triggerSelector: '.js-contentToggle__trigger',
    triggerSelectorContext: true,
    contentSelector: '.js-contentToggle__content',
    contentSelectorContext: true,
    elementClass: 'is-open',
    triggerClass: 'is-active',
    toggleProperties: ['height'],
    toggleOptions: {
      duration: 0
    }
  };

  /**
   * Plugin Constructor.
   *
   * @param {Node|jQuery} element
   *   Main DOM element.
   * @param {string} selector
   *   Element initial selector.
   * @param {object} options
   *   Instance specific options.
   */
  function Plugin(element, selector, options) {
    var data;

    // Merge specific and default options.
    this.options = {
      group: selector
    };
    $.extend(this.options, defaultOptions, options);

    // Initialize data.
    this.$element = (element instanceof $)? element: $(element);
    this.uid = ++uid;

    // Data initialization.
    this.setup();

    // Empty object initialization.
    data = this.$element.data(pluginName);
    if (!instances[this.options.group]) {
      instances[this.options.group] = {};
    }
    if (!data) {
      data = {};
    }

    // Check if instance has not been already initialized.
    if (!data[this.options.group]) {
      // Save the new instance.
      instances[this.options.group][this.uid] = this;
      data[this.options.group] = this;
      this.$element.data(pluginName, data);

      // Plugin initialization.
      this.bind();
      this.init();
    }
  }

  /**
   * Setup plugin.
   * e.g. Get DOM elements, setup data...
   */
  Plugin.prototype.setup = function() {
    this.setupDataOptions();

    // Sanitize group name.
    if (this.options.group) {
      this.options.group = this.options.group.toString().replace(sanitize, '');
    }

    // Parse JSON options.
    if (typeof this.options.toggleProperties == 'string') {
      this.options.toggleProperties = JSON.parse(this.options.toggleProperties);
    }
    if (typeof this.options.toggleOptions == 'string') {
      this.options.toggleOptions = JSON.parse(this.options.toggleOptions);
    }

    // Get trigger elements.
    if (this.options.triggerSelectorContext) {
      this.$triggers = $(this.options.triggerSelector, this.$element);
    } else {
      this.$triggers = $(this.options.triggerSelector);
    }
    if (this.$triggers.length === 0) {
      this.$triggers = this.$element;
    }

    // Get content elements.
    if (this.options.contentSelectorContext) {
      this.$contents = $(this.options.contentSelector, this.$element);
    } else {
      this.$contents = $(this.options.contentSelector);
    }

    // Get callback.
    if (typeof this.options.beforeCallback == 'string' &&
        window[this.options.beforeCallback] &&
        typeof window[this.options.beforeCallback] == 'function') {
      this.options.beforeCallback = window[this.options.beforeCallback].bind(this);
    } else if (typeof this.options.beforeCallback == 'function') {
      this.options.beforeCallback = this.options.beforeCallback.bind(this);
    }
  };

  /**
   * Setup plugin specific data.
   * e.g. Get DOM elements, setup data...
   */
  Plugin.prototype.setupDataOptions = function() {
    $.each(
      this.$element.data(),
      function(index, value){
        if (index in defaultOptions) {
          this.options[index] = value;
        }
      }.bind(this)
    );
  };

  /**
   * Bind events.
   */
  Plugin.prototype.bind = function() {
    var namespaces = '.' + pluginName + '.' + this.options.group;
    var eventName = (isIthing && this.options.globalClose)? 'touchstart': 'click';
    var $all = this.$element.add(this.$triggers).add(this.$contents);

    // Bind custom events on all elements.
    $all.on('destroy' + namespaces, this.destroy.bind(this));
    $all.on('toggle' + namespaces, $.proxy(this.toggle, this, null));
    $all.on('close' + namespaces, $.proxy(this.toggle, this, false));
    $all.on('open' + namespaces, $.proxy(this.toggle, this, true));
    $all.on('isOpen' + namespaces, function(){
      return this.isOpen;
    }.bind(this));

    // Bind native events on triggers.
    this.$triggers.on(eventName + namespaces, function(event){
      event.preventDefault();
      event.timeStamp && this.toggle(null, event);
    }.bind(this));
    this.$triggers.on('keydown' + namespaces, function(event){
      if (event.keyCode == ENTER_KEY_CODE || event.keyCode == SPACE_KEY_CODE) {
        event.preventDefault();
        this.toggle(null, event);
      }
    }.bind(this));

    // Bind native events on contents (avoid triggers click event).
    this.$contents.on(eventName + namespaces, function(event){
      event.stopPropagation();
    });
  };

  /**
   * Initialize default plugin state.
   */
  Plugin.prototype.init = function() {
    // Initialize triggers IDs.
    this.tid = [];
    this.$triggers.each($.proxy(this.initId, this, this.tid, 'contentToggle__trigger'));

    // Initialize contents IDs.
    this.cid = [];
    this.$contents.each($.proxy(this.initId, this, this.cid, 'contentToggle__content'));

    // Initialize triggers attributes.
    this.$triggers.each(function(index, element){
      if (element.tagName != 'BUTTON') {
        this.$triggers.eq(index).attr('role', 'button');
      }
    });
    this.$triggers.attr('tabindex', '0');
    this.$triggers.attr('aria-controls', this.cid.join(' '));

    // Default plugin state.
    if ($.inArray(this.options.defaultState, ['open', 'close']) !== -1) {
      this.$element.trigger(this.options.defaultState + '.' + pluginName);
    } else {
      this.isOpen = this.$contents.is(':visible');
      this.update();
    }
  };

  /**
   * Initialize element id.
   */
  Plugin.prototype.initId = function(ids, prefix, index, element) {
    var $element = $(element);
    ids[index] = $element.attr('id');
    if (!ids[index]) {
      ids[index] = prefix + '-' + this.uid + '-' + index;
      $element.attr('id', ids[index]);
    }
  };

  /**
   * Toggle content.
   *
   * @param {boolean} state
   *   The state of the wanted display.
   * @param {Event} event
   *   The event object.
   */
  Plugin.prototype.toggle = function(state, event) {
    event.stopPropagation();

    if (typeof state != 'boolean') {
      state = !this.isOpen;
    }

    this.$currentTrigger = null;
    if (this.$triggers.is(event.currentTarget)) {
      this.$currentTrigger = $(event.currentTarget);
    }

    if (!this.options.beforeCallback ||
        (typeof this.options.beforeCallback == 'function' &&
         this.options.beforeCallback(event))) {
      if (state) {
        this.open();
      } else {
        this.close();
      }
    }
  };

  /**
   * Open content.
   */
  Plugin.prototype.open = function() {
    var eventName;
    if (this.isOpen !== true) {
      this.isOpen = true;
      this.do();
      this.closeAll(true);
      if (this.options.globalClose) {
        eventName = isIthing? 'touchstart': 'click';
        $global.on(eventName + '.' + pluginName + this.uid, function(){
          this.closeAll();
        }.bind(this));
      }
    }
  };

  /**
   * Close content.
   */
  Plugin.prototype.close = function() {
    if (this.isOpen !== false) {
      this.isOpen = false;
      this.do();
      $global.off('.' + pluginName + this.uid);
    }
  };

  /**
   * Close all binded instances.
   *
   * @param {boolean} butItself
   *   Close all but itself or not.
   */
  Plugin.prototype.closeAll = function(butItself) {
    if (!this.options.independent) {
      $.each(instances[this.options.group], function(uid, instance){
        if (uid != this.uid) {
          instance.close();
        }
      }.bind(this));
    }
    if (!butItself) {
      this.close();
    }
  };

  /**
   * Perform toggle action.
   */
  Plugin.prototype.do = function() {
    var toggleProperties = {};
    var action = this.isOpen? 'show': 'hide';

    this.update();

    $.each(
      this.options.toggleProperties,
      function(index, value){
        toggleProperties[value] = action;
      }
    );

    this.$contents.stop().animate(
      toggleProperties,
      this.options.toggleOptions
    );
  };

  /**
   * Update classes and aria data.
   */
  Plugin.prototype.update = function() {
    if (this.isOpen) {
      this.$element.addClass(this.options.elementClass);
      this.$contents.attr('aria-hidden', false);
      this.$triggers.attr('aria-expanded', true);
      if (this.$currentTrigger) {
        this.$currentTrigger.addClass(this.options.triggerClass);
      } else {
        this.$triggers.addClass(this.options.triggerClass);
      }
    } else {
      this.$element.removeClass(this.options.elementClass);
      this.$contents.attr('aria-hidden', true);
      this.$triggers.attr('aria-expanded', false);
      this.$triggers.removeClass(this.options.triggerClass);
    }
  };

  /**
   * Destroy events.
   */
  Plugin.prototype.destroy = function() {
    this.$element.removeData(pluginName);
    this.$element.off('.' + pluginName);
    this.$triggers.off('.' + pluginName);
    this.$contents.off('.' + pluginName);
    $global.off('.' + pluginName + this.uid);
  };

  /* Expose jQuery plugin. */
  $.fn[pluginName] = function(options) {
    var selector = this.selector;
    return this.each(function() {
      new Plugin(this, selector, options);
    });
  };
})(jQuery);
<|endoftext|>


<commit_before>$(function() {

  var $form = $("form.search-form");
  var $input = $form.find("input");
  var $results = $(".results");
  var $resultTpl = $("#result-template");
  var $greetings = $(".greetings");
  var xhr;

  // put request query in the search input
  if (query = getParameterByName("q")) $input.val(query);

  // instant search
  $input.bind("keyup", function() {
    if (xhr) xhr.abort();
    if (query = $input.val()) search(query); else toggle("greetings");
  });

  // first search: jump to url hash if possible
  if (query = $input.val()) {
    search(query, {
      callback: function() {
        if (window.location.hash && ($fun = $(window.location.hash)).length) {
          activate($fun);
          $('html,body').animate({"scrollTop": $fun.offset().top}, 300);
        }
      }
    });
  } else toggle("greetings");

  // expand search results
  $results.delegate(".signature", "click", function() { activate($(this).closest(".result")); });

  // transform code examples to search links
  $greetings.find('code').each(function() { $(this).wrap(''); });

  // toggle between greetings and search results
  function toggle(s) {
    $(window).unbind("smartscroll");
    $greetings.toggle(s != "search"); $results.toggle(s == "search");
  }

  function activate($fun) {
    $results.find(".active").not($fun).removeClass("active");
    $fun.toggleClass("active");
  }

  function search(query, o) {
    var options = $.extend({page: 1, callback: function() {}, append: false}, o);
    if (!options.append) $(".status").addClass("loading");
    toggle("search");
    xhr = $.ajax({
      url: $form.attr("data-url"),
        data: { q: query, callback: "scalex_jc", page: options.page },
        dataType: "jsonp", jsonp: false, jsonpCallback: "scalex_jc",
        cache: true,
        success: function(data) {
          if (data.error) var html = "
"+nl2br(data.error)+"
";
          else {
            var html = renderResults(data.results);
            if (options.page == 1) html = '
' + data.nbResults + ' functions found
' + html;
          }
    if (options.append) $results.append(html);
    else $results.html(html);
    toggle("search");
    options.callback();
    if (options.page < data.nbPages) {
      var end = $results.find(".result:last").offset().top - $(window).height() - 300;
      $(window).smartscroll(function() {
        if ($(window).scrollTop() > end) {
          search(query, { page: options.page + 1, append: true });
        }
      });
    }
        }
    });
  }

  function changeUrlPage(page) {
    var url = location.href;
    if (url.indexOf(/page=/) != -1) return url.replace(/page=\d+/, "page=" + page);
    else return url + "&page=" + page;
  }

  function nl2br(str) {
    return str.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2');
  }

  function renderResults(results) {
    var html = "", i;
    for (i in results) html += renderResult(results[i]);
    return html;
  }

  function renderResult(e) {
    var r = $resultTpl.clone()
      .find(".parent-class").text(e.parent.name).end()
      .find(".parent-params").text(e.parent.typeParams).end()
      .find(".name").text(e.name).end()
      .find(".type-params").text(e.typeParams).end()
      .find(".return").text(e.resultType).end()
      .find(".package").text(e.package).end()
      .find(".qualified-name").text(e.parent.qualifiedName).end();
    if (e.package == "scala") {
      r.find(".scaladoc-link").text("View " + e.parent.qualifiedName + " on scala-lang API").attr("href", scaladocUrl(e)).show();
    }
    if (e.valueParams) r.find(".params").text(e.valueParams);
    else r.find(".params-sep").remove();
    if (c = e.comment) {
      if (c.short) r.find(".comment-short").html(c.short.html);
      if (c.body) r.find(".comment-body").html(c.body.html);
      if (c.typeParams) r.find(".comment-dl").append(dl(c.typeParams)).show();
      if (c.valueParams) r.find(".comment-dl").append(dl(c.valueParams)).show();
      if (c.result) r.find(".comment-dl").append("
result

" + c.result.html + "
").show();
      if (c.throws) r.find(".comment-throws").html(dl(c.throws));
    }
    if (d = e.deprecation) r.find(".deprecation").html(d.html);
    else r.find(".deprecated, .deprecation").remove();
    var a = anchor(e);
    r.find(".signature").attr("href", "#" + a);
    return '
'+r.html()+'
';
  }

  function anchor(fun) {
    var parts = [fun.parent.qualifiedName, fun.parent.typeParams, fun.name, fun.typeParams, fun.valueParams, fun.resultType]
      return $.trim(parts.join()).replace(/\W/g, "");
  }

  function dl(obj) {
    var html = "", k;
    for (k in obj) html += "
" + k + "
" + "
" + obj[k].html + "
";
    return html;
  }

  function scaladocUrl(fun) {
    return "http://www.scala-lang.org/api/current/"
      + fun.parent.qualifiedName.replace(/\./g, "/")
      + ".html"
  }

  function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(window.location.href);
    if(results == null) return "";
    else return decodeURIComponent(results[1].replace(/\+/g, " "));
  }

  /*
   * smartscroll: debounced scroll event for jQuery *
   * https://github.com/lukeshumard/smartscroll
   * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
   * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
   */

  var event = $.event,
      scrollTimeout;

  event.special.smartscroll = {
    setup: function () {
      $(this).bind("scroll", event.special.smartscroll.handler);
    },
    teardown: function () {
      $(this).unbind("scroll", event.special.smartscroll.handler);
    },
    handler: function (event, execAsap) {
      // Save the context
      var context = this,
      args = arguments;

      // set correct event type
      event.type = "smartscroll";

      if (scrollTimeout) { clearTimeout(scrollTimeout); }
      scrollTimeout = setTimeout(function () {
        jQuery.event.handle.apply(context, args);
      }, execAsap === "execAsap" ? 0 : 100);
    }
  };

  $.fn.smartscroll = function (fn) {
    return fn ? this.bind("smartscroll", fn) : this.trigger("smartscroll", ["execAsap"]);
  };
});

//analytics
if (/scalex\.org/.test(document.domain)) {
  var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-7935029-5']); _gaq.push(['_trackPageview']);
  (function() {
    var ga = document.createElement('script');
    ga.type = 'text/javascript'; ga.async = true; ga.src = 'http://www.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
}
else {
  $form.attr("data-url", "http://scalex:8080/");
}
<commit_msg>Fix localhost detection<commit_after>var scalexProd = /scalex\.org/.test(document.domain);

$(function() {

  var $form = $("form.search-form");
  var $input = $form.find("input");
  var $results = $(".results");
  var $resultTpl = $("#result-template");
  var $greetings = $(".greetings");
  var xhr;

  if (!scalexProd) $form.attr("data-url", "http://scalex:8080/");

  // put request query in the search input
  if (query = getParameterByName("q")) $input.val(query);

  // instant search
  $input.bind("keyup", function() {
    if (xhr) xhr.abort();
    if (query = $input.val()) search(query); else toggle("greetings");
  });

  // first search: jump to url hash if possible
  if (query = $input.val()) {
    search(query, {
      callback: function() {
        if (window.location.hash && ($fun = $(window.location.hash)).length) {
          activate($fun);
          $('html,body').animate({"scrollTop": $fun.offset().top}, 300);
        }
      }
    });
  } else toggle("greetings");

  // expand search results
  $results.delegate(".signature", "click", function() { activate($(this).closest(".result")); });

  // transform code examples to search links
  $greetings.find('code').each(function() { $(this).wrap(''); });

  // toggle between greetings and search results
  function toggle(s) {
    $(window).unbind("smartscroll");
    $greetings.toggle(s != "search"); $results.toggle(s == "search");
  }

  function activate($fun) {
    $results.find(".active").not($fun).removeClass("active");
    $fun.toggleClass("active");
  }

  function search(query, o) {
    var options = $.extend({page: 1, callback: function() {}, append: false}, o);
    if (!options.append) $(".status").addClass("loading");
    toggle("search");
    xhr = $.ajax({
      url: $form.attr("data-url"),
        data: { q: query, callback: "scalex_jc", page: options.page },
        dataType: "jsonp", jsonp: false, jsonpCallback: "scalex_jc",
        cache: true,
        success: function(data) {
          if (data.error) var html = "
"+nl2br(data.error)+"
";
          else {
            var html = renderResults(data.results);
            if (options.page == 1) html = '
' + data.nbResults + ' functions found
' + html;
          }
    if (options.append) $results.append(html);
    else $results.html(html);
    toggle("search");
    options.callback();
    if (options.page < data.nbPages) {
      var end = $results.find(".result:last").offset().top - $(window).height() - 300;
      $(window).smartscroll(function() {
        if ($(window).scrollTop() > end) {
          search(query, { page: options.page + 1, append: true });
        }
      });
    }
        }
    });
  }

  function changeUrlPage(page) {
    var url = location.href;
    if (url.indexOf(/page=/) != -1) return url.replace(/page=\d+/, "page=" + page);
    else return url + "&page=" + page;
  }

  function nl2br(str) {
    return str.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2');
  }

  function renderResults(results) {
    var html = "", i;
    for (i in results) html += renderResult(results[i]);
    return html;
  }

  function renderResult(e) {
    var r = $resultTpl.clone()
      .find(".parent-class").text(e.parent.name).end()
      .find(".parent-params").text(e.parent.typeParams).end()
      .find(".name").text(e.name).end()
      .find(".type-params").text(e.typeParams).end()
      .find(".return").text(e.resultType).end()
      .find(".package").text(e.package).end()
      .find(".qualified-name").text(e.parent.qualifiedName).end();
    if (e.package == "scala") {
      r.find(".scaladoc-link").text("View " + e.parent.qualifiedName + " on scala-lang API").attr("href", scaladocUrl(e)).show();
    }
    if (e.valueParams) r.find(".params").text(e.valueParams);
    else r.find(".params-sep").remove();
    if (c = e.comment) {
      if (c.short) r.find(".comment-short").html(c.short.html);
      if (c.body) r.find(".comment-body").html(c.body.html);
      if (c.typeParams) r.find(".comment-dl").append(dl(c.typeParams)).show();
      if (c.valueParams) r.find(".comment-dl").append(dl(c.valueParams)).show();
      if (c.result) r.find(".comment-dl").append("
result

" + c.result.html + "
").show();
      if (c.throws) r.find(".comment-throws").html(dl(c.throws));
    }
    if (d = e.deprecation) r.find(".deprecation").html(d.html);
    else r.find(".deprecated, .deprecation").remove();
    var a = anchor(e);
    r.find(".signature").attr("href", "#" + a);
    return '
'+r.html()+'
';
  }

  function anchor(fun) {
    var parts = [fun.parent.qualifiedName, fun.parent.typeParams, fun.name, fun.typeParams, fun.valueParams, fun.resultType]
      return $.trim(parts.join()).replace(/\W/g, "");
  }

  function dl(obj) {
    var html = "", k;
    for (k in obj) html += "
" + k + "
" + "
" + obj[k].html + "
";
    return html;
  }

  function scaladocUrl(fun) {
    return "http://www.scala-lang.org/api/current/"
      + fun.parent.qualifiedName.replace(/\./g, "/")
      + ".html"
  }

  function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(window.location.href);
    if(results == null) return "";
    else return decodeURIComponent(results[1].replace(/\+/g, " "));
  }

  /*
   * smartscroll: debounced scroll event for jQuery *
   * https://github.com/lukeshumard/smartscroll
   * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
   * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
   */

  var event = $.event,
      scrollTimeout;

  event.special.smartscroll = {
    setup: function () {
      $(this).bind("scroll", event.special.smartscroll.handler);
    },
    teardown: function () {
      $(this).unbind("scroll", event.special.smartscroll.handler);
    },
    handler: function (event, execAsap) {
      // Save the context
      var context = this,
      args = arguments;

      // set correct event type
      event.type = "smartscroll";

      if (scrollTimeout) { clearTimeout(scrollTimeout); }
      scrollTimeout = setTimeout(function () {
        jQuery.event.handle.apply(context, args);
      }, execAsap === "execAsap" ? 0 : 100);
    }
  };

  $.fn.smartscroll = function (fn) {
    return fn ? this.bind("smartscroll", fn) : this.trigger("smartscroll", ["execAsap"]);
  };
});

//analytics
if (scalexProd) {
  var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-7935029-5']); _gaq.push(['_trackPageview']);
  (function() {
    var ga = document.createElement('script');
    ga.type = 'text/javascript'; ga.async = true; ga.src = 'http://www.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
}
<|endoftext|>