<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import { themeGet } from 'styled-system'
import { withTheme } from 'styled-components'
import { tint } from 'polished'

const Segment = ({ color, amount = 0, rotate, ...rest }) => {
  const radius = 17.5
  const circumference = 2 * Math.PI * radius
  return (
    <circle
      className="donut-segment"
      cx="20"
      cy="20"
      fill="transparent"
      r={radius}
      stroke={color}
      strokeDasharray={circumference}
      strokeDashoffset={circumference * (1 - amount)}
      strokeWidth="1"
      transform={`rotate(-${rotate} 20 20)`}
      {...rest}
    />
  )
}

Segment.propTypes = {
  amount: PropTypes.number.isRequired,
  color: PropTypes.string.isRequired,
  rotate: PropTypes.number.isRequired,
}

const Donut = withTheme(({ data, text, ...rest }) => {
  const initialRotation = 90
  let cumRotation = initialRotation

  // Add an additioanl segment for the base layer
  const allData = [{ key: '__base__', amount: 1, color: 'tertiaryColor' }, ...data]

  // Set rotation for each segment.
  const segments = allData.map(item => {
    const segment = { ...item, rotate: cumRotation }
    const offset = 360 * (1 - item.amount)
    cumRotation += offset
    return segment
  })

  return (
    <svg height="100%" viewBox="0 0 40 40" width="100%" {...rest}>
      {segments.map(segment => {
        const color = themeGet(`colors.${segment.color}`)(rest)
        return (
          <React.Fragment key={segment.key}>
            <defs>
              <linearGradient id={`gradient-${segment.key}`} x1="0%" x2="100%" y1="0%" y2="0%">
                <stop offset="0%" stopColor={tint(0.2, color)} />
                <stop offset="100%" stopColor={color} />
              </linearGradient>

              <filter height="150%" id={`glow-${segment.key}`} width="150%">
                {/* Thicken out the original shape  */}
                <feMorphology in="SourceAlpha" operator="dilate" radius="0.3" result="thicken" />

                {/* Use a gaussian blur to create the soft blurriness of the glow */}
                <feGaussianBlur in="thicken" result="blurred" stdDeviation="1" />

                {/* Change the colour */}
                <feFlood floodColor={color} result="glowColor" />

                {/* Color in the glows */}
                <feComposite in="glowColor" in2="blurred" operator="in" result="softGlow_colored" />

                {/* Layer the effects together */}
                <feMerge>
                  <feMergeNode in="softGlow_colored" />
                  <feMergeNode in="SourceGraphic" />
                </feMerge>
              </filter>
            </defs>

            <Segment
              amount={segment.amount}
              color={
                segment.withTint
                  ? `url(#gradient-${segment.key})`
                  : themeGet(`colors.${segment.color}`)(rest)
              }
              filter={segment.withGlow ? `url(#glow-${segment.key})` : null}
              rotate={segment.rotate}
            />
          </React.Fragment>
        )
      })}

      <text fill={themeGet('colors.primaryText')(rest)} transform="translate(0, 5)" y="50%">
        <tspan textAnchor="middle" x="50%">
          {text}
        </tspan>
      </text>
    </svg>
  )
})

Donut.propTypes = {
  data: PropTypes.arrayOf(
    PropTypes.shape({
      amount: PropTypes.number.isRequired,
      color: PropTypes.string,
      key: PropTypes.string.isRequired,
      withGlow: PropTypes.bool,
      withTint: PropTypes.bool,
    })
  ),
  height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  text: PropTypes.node,
  width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
}

Donut.defaultProps = {
  data: [],
}

Donut.displayName = 'Donut'

export default Donut
<commit_msg>refactor: support Donut strokeWidth customization<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import { themeGet } from 'styled-system'
import { withTheme } from 'styled-components'
import { tint } from 'polished'

const Segment = ({ color, strokeWidth, amount = 0, rotate, ...rest }) => {
  const radius = 17.5
  const circumference = 2 * Math.PI * radius
  return (
    <circle
      className="donut-segment"
      cx="20"
      cy="20"
      fill="transparent"
      r={radius}
      stroke={color}
      strokeDasharray={circumference}
      strokeDashoffset={circumference * (1 - amount)}
      strokeWidth={strokeWidth}
      transform={`rotate(-${rotate} 20 20)`}
      {...rest}
    />
  )
}

Segment.propTypes = {
  amount: PropTypes.number.isRequired,
  color: PropTypes.string.isRequired,
  rotate: PropTypes.number.isRequired,
  strokeWidth: PropTypes.number.isRequired,
}

const Donut = withTheme(({ data, text, strokeWidth, ...rest }) => {
  const initialRotation = 90
  let cumRotation = initialRotation

  // Add an additioanl segment for the base layer
  const allData = [{ key: '__base__', amount: 1, color: 'tertiaryColor' }, ...data]

  // Set rotation for each segment.
  const segments = allData.map(item => {
    const segment = { ...item, rotate: cumRotation }
    const offset = 360 * (1 - item.amount)
    cumRotation += offset
    return segment
  })

  return (
    <svg height="100%" viewBox="0 0 40 40" width="100%" {...rest}>
      {segments.map(segment => {
        const color = themeGet(`colors.${segment.color}`)(rest)
        return (
          <React.Fragment key={segment.key}>
            <defs>
              <linearGradient id={`gradient-${segment.key}`} x1="0%" x2="100%" y1="0%" y2="0%">
                <stop offset="0%" stopColor={tint(0.2, color)} />
                <stop offset="100%" stopColor={color} />
              </linearGradient>

              <filter height="150%" id={`glow-${segment.key}`} width="150%">
                {/* Thicken out the original shape  */}
                <feMorphology in="SourceAlpha" operator="dilate" radius="0.3" result="thicken" />

                {/* Use a gaussian blur to create the soft blurriness of the glow */}
                <feGaussianBlur in="thicken" result="blurred" stdDeviation="1" />

                {/* Change the colour */}
                <feFlood floodColor={color} result="glowColor" />

                {/* Color in the glows */}
                <feComposite in="glowColor" in2="blurred" operator="in" result="softGlow_colored" />

                {/* Layer the effects together */}
                <feMerge>
                  <feMergeNode in="softGlow_colored" />
                  <feMergeNode in="SourceGraphic" />
                </feMerge>
              </filter>
            </defs>

            <Segment
              amount={segment.amount}
              color={
                segment.withTint
                  ? `url(#gradient-${segment.key})`
                  : themeGet(`colors.${segment.color}`)(rest)
              }
              filter={segment.withGlow ? `url(#glow-${segment.key})` : null}
              rotate={segment.rotate}
              strokeWidth={strokeWidth}
            />
          </React.Fragment>
        )
      })}

      <text fill={themeGet('colors.primaryText')(rest)} transform="translate(0, 5)" y="50%">
        <tspan textAnchor="middle" x="50%">
          {text}
        </tspan>
      </text>
    </svg>
  )
})

Donut.propTypes = {
  data: PropTypes.arrayOf(
    PropTypes.shape({
      amount: PropTypes.number.isRequired,
      color: PropTypes.string,
      key: PropTypes.string.isRequired,
      withGlow: PropTypes.bool,
      withTint: PropTypes.bool,
    })
  ),
  height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  strokeWidth: PropTypes.number,
  text: PropTypes.node,
  width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
}

Donut.defaultProps = {
  data: [],
  strokeWidth: 1,
}

Donut.displayName = 'Donut'

export default Donut
<|endoftext|>


<commit_before>/*
 * file:	SR-EELS_ImportCal.js
 * author:	Michael Entrup b. Epping (michael.entrup@wwu.de)
 * version:	20150407
 * info:	This script is used to import calibration images into my "database".
 * 			The "databse" is a folder structure that contains all my calibration images.
 * 			This script trises to gues the acquisition data and all parameters by processing the file path.
 *
 * 			This script is part of the Fiji plugin EFTEMj (https://github.com/EFTEMj/EFTEMj).
 */

importClass(Packages.ij.IJ);
importClass(Packages.ij.Prefs);
importClass(Packages.java.io.File);
importClass(Packages.ij.io.DirectoryChooser);
importClass(Packages.ij.gui.GenericDialog);

var databaseKey = "EFTEMj.SR-EELS.database.path";
var databasePath;

main();

function main() {
	/*
	 * The path to the databasePath folder is stored in IJ_Prefs.txt.
	 * If the value is not yet defined, the user is asked to set a directory.
	 */
	if ((databasePath = Prefs.get(databaseKey, "")) == "") {
		if ((databasePath = getDirectory("Path to your SR-EELS database...")) != null) Prefs.set(databaseKey, databasePath);
		else return;
	}
	var path;
	/*
	 * Select the files to import.
	 */
	if ((path = getDirectory("Calibration files...")) == null) return;
	var files;
	if ((files = selectFiles(path)) == null) return;
	var parameters;
	if ((parameters = getParameters(path)) == null) return;
	if (parameters.date != null & parameters.SM != null & parameters.QSinK7 != null) {
		saveFiles(path, files, parameters);
	}
}

function getDirectory(title) {
	var dc = new DirectoryChooser(title);
	return dc.getDirectory();
}

function selectFiles(path) {
	var folder = new File(path);
	var list = folder.list();
	var gd = GenericDialog("Select files");
	for (var i = 0; i < list.length; i++) {
		if (new File(path + list[i]).isFile() & list[i].search("Cal") >= 0) {
			gd.addCheckbox(list[i], true);
		} else {
			gd.addCheckbox(list[i], false);
		}
	}
	gd.showDialog();
	if (gd.wasCanceled()) {
		return null;
	}
	var files = new Array();
	for (var i = 0; i < list.length; i++) {
		if (gd.getNextBoolean()) {
			files.push(list[i]);
		}
	}
	return files;
}

function getParameters(path) {
	var patternDate = /(\d{8})/ig;
	var patternSM = /(?:SM|SpecMag)(\d{2,3})/ig;
	var patternQSinK7 = /(QSinK7[\s|=])(-?\+?\d{1,3})%?/ig;
	var parameters = new Parameters();
	var dateArray;
	while ((dateArray = patternDate.exec(path)) !== null) {
		parameters.date = dateArray[1];
	}
	var smArray;
	while ((smArray = patternSM.exec(path)) !== null) {
		parameters.SM = smArray[1];
	}
	var qsinArray;
	while ((qsinArray = patternQSinK7.exec(path)) !== null) {
		parameters.QSinK7 = qsinArray[2];
	}
	var gd = GenericDialog("Set parameters");
	gd.addStringField("date:", parameters.date);
	gd.addStringField("SpecMag:", parameters.SM);
	gd.addStringField("QSinK7:", parameters.QSinK7);
	gd.addStringField("comment:", parameters.comment);
	gd.showDialog();
	if (gd.wasCanceled()) {
		return null;
	} else {
		parameters.date = gd.getNextString();
		parameters.SM = gd.getNextString();
		parameters.QSinK7 = gd.getNextString();
		parameters.comment = gd.getNextString();
	}
	return parameters;
}

function Parameters() {
	this.date = null;
	this.SM = null;
	this.QSinK7 = null;
	this.comment = null;
}

function saveFiles(path, files, parameters) {
	output = databasePath + parameters.date + " SM" + parameters.SM + " " + parameters.QSinK7 + "%";
	if (parameters.comment != "") {
		output += " " + parameters.comment;
	}
	output += "/";
	folder = new File(output);
	folder.mkdir();
	for (index in files) {
		imp = IJ.openImage(path + files[index]);
		IJ.run(imp, "Rotate 90 Degrees Left", "");
		IJ.save(imp, output + "Cal_" + pad(++index, 2) + ".tif");
		imp.close();
	}
}

function pad(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
}<commit_msg>Updated SR-EELS_ImportCal.js to ignore files:<commit_after>/*
 * file:	SR-EELS_ImportCal.js
 * author:	Michael Entrup b. Epping (michael.entrup@wwu.de)
 * version:	20150804
 * info:	This script is used to import calibration images into my "database".
 * 			The "databse" is a folder structure that contains all my calibration images.
 * 			This script trises to gues the acquisition data and all parameters by processing the file path.
 *
 * 			This script is part of the Fiji plugin EFTEMj (https://github.com/EFTEMj/EFTEMj).
 */

importClass(Packages.ij.IJ);
importClass(Packages.ij.Prefs);
importClass(Packages.java.io.File);
importClass(Packages.ij.io.DirectoryChooser);
importClass(Packages.ij.gui.GenericDialog);

var databaseKey = "EFTEMj.SR-EELS.database.path";
var databasePath;

main();

function main() {
	/*
	 * The path to the databasePath folder is stored in IJ_Prefs.txt.
	 * If the value is not yet defined, the user is asked to set a directory.
	 */
	if ((databasePath = Prefs.get(databaseKey, "")) == "") {
		if ((databasePath = getDirectory("Path to your SR-EELS database...")) != null) Prefs.set(databaseKey, databasePath);
		else return;
	}
	var path;
	/*
	 * Select the files to import.
	 */
	if ((path = getDirectory("Calibration files...")) == null) return;
	var files;
	if ((files = selectFiles(path)) == null) return;
	var parameters;
	if ((parameters = getParameters(path)) == null) return;
	if (parameters.date != null & parameters.SM != null & parameters.QSinK7 != null) {
		saveFiles(path, files, parameters);
	}
}

function getDirectory(title) {
	var dc = new DirectoryChooser(title);
	return dc.getDirectory();
}

function selectFiles(path) {
	var folder = new File(path);
	var list = folder.list();
	var gd = GenericDialog("Select files");
	for (var i = 0; i < list.length; i++) {
		if (new File(path + list[i]).isFile() & list[i].search("Cal") >= 0 & list[i].search("-exclude") < 0) {
			gd.addCheckbox(list[i], true);
		} else {
			gd.addCheckbox(list[i], false);
		}
	}
	gd.showDialog();
	if (gd.wasCanceled()) {
		return null;
	}
	var files = new Array();
	for (var i = 0; i < list.length; i++) {
		if (gd.getNextBoolean()) {
			files.push(list[i]);
		}
	}
	return files;
}

function getParameters(path) {
	var patternDate = /(\d{8})/ig;
	var patternSM = /(?:SM|SpecMag)(\d{2,3})/ig;
	var patternQSinK7 = /(QSinK7[\s|=])(-?\+?\d{1,3})%?/ig;
	var parameters = new Parameters();
	var dateArray;
	while ((dateArray = patternDate.exec(path)) !== null) {
		parameters.date = dateArray[1];
	}
	var smArray;
	while ((smArray = patternSM.exec(path)) !== null) {
		parameters.SM = smArray[1];
	}
	var qsinArray;
	while ((qsinArray = patternQSinK7.exec(path)) !== null) {
		parameters.QSinK7 = qsinArray[2];
	}
	var gd = GenericDialog("Set parameters");
	gd.addStringField("date:", parameters.date);
	gd.addStringField("SpecMag:", parameters.SM);
	gd.addStringField("QSinK7:", parameters.QSinK7);
	gd.addStringField("comment:", parameters.comment);
	gd.showDialog();
	if (gd.wasCanceled()) {
		return null;
	} else {
		parameters.date = gd.getNextString();
		parameters.SM = gd.getNextString();
		parameters.QSinK7 = gd.getNextString();
		parameters.comment = gd.getNextString();
	}
	return parameters;
}

function Parameters() {
	this.date = null;
	this.SM = null;
	this.QSinK7 = null;
	this.comment = null;
}

function saveFiles(path, files, parameters) {
	output = databasePath + parameters.date + " SM" + parameters.SM + " " + parameters.QSinK7 + "%";
	if (parameters.comment != "") {
		output += " " + parameters.comment;
	}
	output += "/";
	folder = new File(output);
	folder.mkdir();
	for (index in files) {
		imp = IJ.openImage(path + files[index]);
		IJ.run(imp, "Rotate 90 Degrees Left", "");
		IJ.save(imp, output + "Cal_" + pad(++index, 2) + ".tif");
		imp.close();
	}
}

function pad(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
}<|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;
				}
			} else {
				clear.call(this.valueDOM);
				if (this._required) this.castControlAttribute('required', true);
			}
		} 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 listener attachment<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
  , 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;
				}
			} else {
				clear.call(this.valueDOM);
				if (this._required) this.castControlAttribute('required', true);
			}
		} 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;
<|endoftext|>


<commit_before>'use strict';

const DataStore = require('./DataStore');
const fs = require('fs');
const MASK = '0777';
const IGNORED_MKDIR_ERROR = 'EEXIST';

/**
 * @fileOverview
 * Store using local filesystem.
 *
 * @author Ben Stahl <bhstahl@gmail.com>
 */

class FileStore extends DataStore {
    constructor(options) {
        super(options);

        this.directory = options.directory || options.path.replace(/^\//, '');

        this.extensions = ['creation', 'expiration'];
        this._checkOrCreateDirectory();
    }

    /**
     *  Ensure the directory exists.
     */
    _checkOrCreateDirectory() {
        fs.mkdir(this.directory, MASK, (error) => {
            if (error && error.code !== IGNORED_MKDIR_ERROR) {
                throw error;
            }
        });
    }

    /**
     * Create an empty file.
     *
     * @param  {File} file
     * @return {Promise}
     */
    create(file) {
        super.create(file);
        return new Promise((resolve, reject) => {
            fs.open(`${this.directory}/${file.id}`, 'w', (err, fd) => {
                if (err) {
                    console.log(err);
                    return reject(err);
                }

                return fs.close(fd, (exception) => {
                    if (exception) {
                        return reject(exception);
                    }

                    return resolve();
                });
            });
        });
    }

    write(req, file_name, offset) {
        return new Promise((resolve, reject) => {
            const path = `${this.directory}/${file_name}`;
            const options = {
                flags: 'r+',
                start: offset,
            };

            const stream = fs.createWriteStream(path, options);

            if (!stream) {
                return reject('unable to create write stream');
            }

            let new_offset = 0;
            req.on('data', (buffer) => {
                new_offset += buffer.length;
            });

            req.on('end', () => {
                console.log(`${new_offset} bytes written to ${path}`);
                resolve(new_offset);
            });

            stream.on('error', (e) => {
                console.log(e);
                reject(e);
            });

            return req.pipe(stream);
        });
    }

    /**
     * Return file stats, if they exits
     *
     * @param  {string} file_name name of the file
     * @return {object}           fs stats
     */
    getOffset(file_name) {
        return new Promise((resolve, reject) => {
            fs.stat(`${this.directory}/${file_name}`, (error, stats) => {
                if (error) {
                    console.log(error);
                    reject(error);
                }

                resolve(stats);
            });
        });
    }
}

module.exports = FileStore;
<commit_msg>Return the total bytes in the Upload-Length header<commit_after>'use strict';

const DataStore = require('./DataStore');
const fs = require('fs');
const MASK = '0777';
const IGNORED_MKDIR_ERROR = 'EEXIST';

/**
 * @fileOverview
 * Store using local filesystem.
 *
 * @author Ben Stahl <bhstahl@gmail.com>
 */

class FileStore extends DataStore {
    constructor(options) {
        super(options);

        this.directory = options.directory || options.path.replace(/^\//, '');

        this.extensions = ['creation', 'expiration'];
        this._checkOrCreateDirectory();
    }

    /**
     *  Ensure the directory exists.
     */
    _checkOrCreateDirectory() {
        fs.mkdir(this.directory, MASK, (error) => {
            if (error && error.code !== IGNORED_MKDIR_ERROR) {
                throw error;
            }
        });
    }

    /**
     * Create an empty file.
     *
     * @param  {File} file
     * @return {Promise}
     */
    create(file) {
        super.create(file);
        return new Promise((resolve, reject) => {
            fs.open(`${this.directory}/${file.id}`, 'w', (err, fd) => {
                if (err) {
                    console.log(err);
                    return reject(err);
                }

                return fs.close(fd, (exception) => {
                    if (exception) {
                        return reject(exception);
                    }

                    return resolve();
                });
            });
        });
    }

    write(req, file_name, offset) {
        return new Promise((resolve, reject) => {
            const path = `${this.directory}/${file_name}`;
            const options = {
                flags: 'r+',
                start: offset,
            };

            const stream = fs.createWriteStream(path, options);

            if (!stream) {
                return reject('unable to create write stream');
            }

            let new_offset = 0;
            req.on('data', (buffer) => {
                new_offset += buffer.length;
            });

            req.on('end', () => {
                console.log(`${new_offset} bytes written to ${path}`);
                offset += new_offset;
                console.log(`File is now ${offset} bytes`);
                resolve(offset);
            });

            stream.on('error', (e) => {
                console.log(e);
                reject(e);
            });

            return req.pipe(stream);
        });
    }

    /**
     * Return file stats, if they exits
     *
     * @param  {string} file_name name of the file
     * @return {object}           fs stats
     */
    getOffset(file_name) {
        return new Promise((resolve, reject) => {
            fs.stat(`${this.directory}/${file_name}`, (error, stats) => {
                if (error) {
                    console.log(error);
                    reject(error);
                }

                resolve(stats);
            });
        });
    }
}

module.exports = FileStore;
<|endoftext|>


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

// Db connection. singleton
var rdb = null;

var connectDb = function (dbConf) {
    var dbHost = dbConf.host || "localhost";
    var dbPort = dbConf.port || 28015;
    var dbName = dbConf.dbName;
    var authKey = dbConf.authKey || '';
    var dbOpts = {
        host: dbHost,
        port: dbPort,
        db: dbName,
        authKey: authKey,
        buffer: 10,
        max: 50,
        timeout: 10,
        timeoutError: 2 * 1000,
        timeoutGb: 10 * 60 * 1000,
        silent: false,
        cursor: false,
        pool: true
    }; // See https://github.com/neumino/rethinkdbdash

    return require('rethinkdbdash')(dbOpts);
};

/**
 * Select data in DB. Returns promise
 * @param name - sensor name
 * @param limit - limit
 * @param rdb - db connection instance
 * @param dbName
 * @param tableName
 * @param logger
 * @returns {*}
 */
var selectInDb = function (name, limit, rdb, dbName, tableName, logger) {
    logger.debug('loading ', name, limit);
    var deferred = Q.defer();
    rdb.db(dbName).table(tableName).orderBy({index: r.desc('timestamp')})
        .filter(r.row('name').eq(name))
        .limit(limit)
        .pluck('timestamp', 'value')
        .then(function (res) {
            logger.debug('results ', res.length);
            deferred.resolve(res);
        }).error(function (err) {
            logger.error(util.inspect(err));
            deferred.reject(new Error('Could not load sensor data. Err:' + util.inspect(err)));
        });
    return deferred.promise;
};

var sensorDataFactory = function (appConf, log4js) {
    var logger = log4js.getLogger('sensorData');
    var selectFunction = null;

    // Setup db
    if (!rdb && appConf.app.storageStrategy === 'dbStore') {
        logger.info('Using DB Store. Connecting to db at ' + (appConf.app.dbStore.host || "127.0.0.1"));
        rdb = connectDb(appConf.app.dbStore);
        selectFunction = function (name, limit) {
            return selectInDb(name, limit, rdb, appConf.app.dbStore.dbName, appConf.app.dbStore.sensorTableName, logger);
        };
    } else
        throw new Error('no dbStore configured in appConfig.json!');

    return function sensorData(name, limit) {
        return selectFunction(name, limit);
    };
};

exports = module.exports = sensorDataFactory;
<commit_msg>serving sensordata<commit_after>var util = require('util');
var Q = require('q');

// Db connection. singleton
var rdb = null;

var connectDb = function (dbConf) {
    var dbHost = dbConf.host || "localhost";
    var dbPort = dbConf.port || 28015;
    var dbName = dbConf.dbName;
    var authKey = dbConf.authKey || '';
    var dbOpts = {
        host: dbHost,
        port: dbPort,
        db: dbName,
        authKey: authKey,
        buffer: 10,
        max: 50,
        timeout: 10,
        timeoutError: 2 * 1000,
        timeoutGb: 10 * 60 * 1000,
        silent: false,
        cursor: false,
        pool: true
    }; // See https://github.com/neumino/rethinkdbdash

    return require('rethinkdbdash')(dbOpts);
};

/**
 * Select data in DB. Returns promise
 * @param name - sensor name
 * @param limit - limit
 * @param rdb - db connection instance
 * @param dbName
 * @param tableName
 * @param logger
 * @returns {*}
 */
var selectInDb = function (name, limit, rdb, dbName, tableName, logger) {
    logger.debug('loading ', name, limit);
    var deferred = Q.defer();
    rdb.db(dbName).table(tableName).orderBy({index: rdb.desc('timestamp')})
        .filter(rdb.row('name').eq(name))
        .limit(limit)
        .pluck('timestamp', 'value')
        .then(function (res) {
            logger.debug('results ', res.length);
            deferred.resolve(res);
        }).error(function (err) {
            logger.error(util.inspect(err));
            deferred.reject(new Error('Could not load sensor data. Err:' + util.inspect(err)));
        });
    return deferred.promise;
};

var sensorDataFactory = function (appConf, log4js) {
    var logger = log4js.getLogger('sensorData');
    var selectFunction = null;

    // Setup db
    if (!rdb && appConf.app.storageStrategy === 'dbStore') {
        logger.info('Using DB Store. Connecting to db at ' + (appConf.app.dbStore.host || "127.0.0.1"));
        rdb = connectDb(appConf.app.dbStore);
        selectFunction = function (name, limit) {
            return selectInDb(name, limit, rdb, appConf.app.dbStore.dbName, appConf.app.dbStore.sensorTableName, logger);
        };
    } else
        throw new Error('no dbStore configured in appConfig.json!');

    return function sensorData(name, limit) {
        return selectFunction(name, limit);
    };
};

exports = module.exports = sensorDataFactory;
<|endoftext|>


<commit_before>/*
 * stylie.slideshows
 * http://github.com/typesettin
 *
 * Copyright (c) 2013 Amex Pub. All rights reserved.
 */

'use strict';

var classie = require('classie'),
	extend = require('util-extend'),
	events = require('events'),
	Pushie = require('pushie'),
	util = require('util'),
	slideshowPushie,
	Hammer,
	detectCSS = require('detectcss');

var getEventTarget = function (e) {
	e = e || window.event;
	return e.target || e.srcElement;
};

/**
 * A module that represents a full with slideshow componenet object, a stylie.slideshows is a slideshow.
 * @{@link https://github.com/typesettin/stylie.slideshows}
 * @author Yaw Joseph Etse
 * @copyright Copyright (c) 2014 Typesettin. All rights reserved.
 * @license MIT
 * @constructor StylieSlideshow
 * @requires module:util-extent
 * @requires module:util
 * @requires module:events
 * @requires module:hammerjs
 * @requires module:detectcss
 * @param {object} config {el -  element of tab container}
 * @param {object} options configuration options
 */
var StylieSlideshow = function (config) {
	// console.log(config);
	this.$el = config.element;
	this.jump = this._jump;
	this.slide = this._slide;
	this.navigate = this._navigate;
	this._init(config.options);
};

util.inherits(StylieSlideshow, events.EventEmitter);

/** module default configuration */
StylieSlideshow.prototype._init = function (options) {
	var defaults = {
		speed: 500, // default transition speed (ms)
		touchsupport: true,
		usepushstate: false,
		navarrows: true,
		navarrows_next_html: '>',
		navarrows_next_class: 'ts-ss-slidenext',
		navarrows_prev_html: '<',
		navarrows_prev_class: 'ts-ss-slideprev',
		navdots: true,
		navdots_class: 'ts-ss-dots',
		navdots_current_class: 'ts-ss-currentdot',
		easing: 'ease' // default transition easing
	};
	options = options || {};
	this.options = extend(defaults, options);
	this._config();
	this._initEvents(); // initialize/bind the events
};

/**
 * initializes slideshow and shows current slide.
 * @emits slidesInitialized
 */
StylieSlideshow.prototype._config = function () {

	// the list of items
	this.$list = this.$el.querySelector('ul');
	this.$items = this.$list.querySelectorAll('li');
	// total number of items
	this.itemsCount = this.$items.length;
	// support for CSS Transitions & transforms

	this.support = detectCSS.prefixed('transition') && detectCSS.feature('transform');
	this.support3d = detectCSS.prefixed('perspective');

	// transition end event name and transform name
	// transition end event name
	var transEndEventNames = {
			'WebkitTransition': 'webkitTransitionEnd',
			'MozTransition': 'transitionend',
			'OTransition': 'oTransitionEnd',
			'msTransition': 'MSTransitionEnd',
			'transition': 'transitionend'
		},
		transformNames = {
			'WebkitTransform': '-webkit-transform',
			'MozTransform': '-moz-transform',
			'OTransform': '-o-transform',
			'msTransform': '-ms-transform',
			'transform': 'transform'
		};

	if (this.support) {
		this.transEndEventName = transEndEventNames[detectCSS.prefixed('transition')] + '.p_c_fws';
		this.transformName = transformNames[detectCSS.prefixed('transform')];
	}
	// current and old item´s index
	this.current = 0;
	this.old = 0;
	// check if the list is currently moving
	this.isAnimating = false;
	// the list (ul) will have a width of 100% x itemsCount
	this.$list.style.width = 100 * this.itemsCount + '%';
	// apply the transition
	if (this.support) {
		this.$list.style.transition = this.transformName + ' ' + this.options.speed + 'ms ' + this.options.easing;
	}
	// each item will have a width of 100 / itemsCount

	for (var x in this.$items) {
		if (this.$items[x].style) {
			this.$items[x].style.width = 100 / this.itemsCount + '%';
		}
	}
	if (this.itemsCount > 1) { // add navigation arrows and the navigation dots if there is more than 1 item
		if (this.options.navarrows) { // add navigation arrows (the previous arrow is not shown initially):
			var nav = document.createElement('nav');
			nav.innerHTML = '' + this.options.navarrows_prev_html + '' + this.options.navarrows_next_html + '';
			this.$el.appendChild(nav);
			this.$navPrev = this.$el.querySelector('.' + this.options.navarrows_prev_class);
			this.$navNext = this.$el.querySelector('.' + this.options.navarrows_next_class);
		}
		if (this.options.navdots) {
			var dots = '';
			for (var i = 0; i < this.itemsCount; ++i) { // current dot will have the class p_c_fws-cuurentdot
				var dot = i === this.current ? '' : '';
				dots += dot;
			}
			var navDots = document.createElement('div');
			navDots.setAttribute('class', this.options.navdots_class);
			// console.log("navDots",navDots);
			navDots.innerHTML = dots;
			this.$el.appendChild(navDots);
			this.$navDots = navDots.querySelectorAll('span');
		}
	}
	if (this.options.usepushstate) {
		var initSlideIndex,
			jumpToSlide = function (data) {
				// console.log('popcallback');
				this.jump(data.currentSlide);
			}.bind(this),
			jumpToFirstInitialSlide = function () {
				var winhref, winhash;
				for (var q = 0; q < this.itemsCount; q++) {
					winhref = window.location.href;
					winhref = (winhref.search(window.location.origin) >= 0) ? winhref.replace(window.location.origin, '') : winhref;
					winhash = window.location.hash.substr(1, window.location.hash.length);
					winhash = (winhash.search(window.location.origin) >= 0) ? winhash.replace(window.location.origin, '') : winhash;
					if (this.$items[q].getAttribute('data-ts-ss-href') === winhref || this.$items[q].getAttribute('data-ts-ss-href') === winhash) {
						initSlideIndex = q;
					}
					if (initSlideIndex) {
						this.jump(initSlideIndex);
					}
				}
			}.bind(this); //,
		// initialSlideIndex=0;
		slideshowPushie = new Pushie({
			popcallback: jumpToSlide,
			pushcallback: function ( /*data*/ ) {
				// console.log('pushcallback');
			},
			replacecallback: function ( /*data*/ ) {
				// console.log('replacecallback');
			},
		});
		jumpToFirstInitialSlide();
	}
	this.emit('slidesInitialized');
};

/**
 * handle slideshow click events.
 */
StylieSlideshow.prototype._initEvents = function () {
	if (this.options.touchsupport) {
		Hammer = require('hammerjs');
		var hammertime = new Hammer(this.$el, {
			drag_block_horizontal: true
		});

		hammertime.on('swiperight', function (ev) {
			this.emit('swipedright', ev);
			this._navigate('previous');
		}.bind(this));

		hammertime.on('swipeleft', function (ev) {
			this.emit('swipeleft', ev);
			this._navigate('next');
		}.bind(this));
	}
	if (this.itemsCount > 1) {
		if (this.options.navarrows) {
			this.$navPrev.addEventListener('click', function () {
				this._navigate('previous');
			}.bind(this));

			this.$navNext.addEventListener('click', function () {
				this._navigate('next');
			}.bind(this));
		}
		if (this.options.navdots) {
			this.$navDotDom = this.$el.querySelector('.' + this.options.navdots_class);

			this.$navDotDom.addEventListener('click', function (event) {
				var target = getEventTarget(event);
				if (target.tagName === 'SPAN') {
					this._jump(target.getAttribute('data-itr'));
				}
			}.bind(this));
		}
	}
};

/**
 * move slideshow to slide based on the direction.
 * @param {string} direction (previous|next) slide
 * @emits slided
 */
StylieSlideshow.prototype._navigate = function (direction) {
	// do nothing if the list is currently moving
	if (this.isAnimating) {
		return false;
	}

	this.isAnimating = true;
	// update old and current values
	this.old = this.current;
	if (direction === 'next' && this.current < this.itemsCount - 1) {
		++this.current;
	}
	else if (direction === 'previous' && this.current > 0) {
		--this.current;
	}
	this.emit('navigatedComponent', this.current);

	// slide
	this._slide();
	// console.log('this._slide()',this._slide());
};

/**
 * slide to show this.current(index) slide.
 * @emits slided
 */
StylieSlideshow.prototype._slide = function () {
	// check which navigation arrows should be shown
	this._toggleNavControls();
	if (this.options.usepushstate) {
		// console.log('this.current', this.current);
		// console.log('this.$items[this.current]', this.$items[this.current]);
		var currentSlideEl = this.$items[this.current],
			currentSlideElTitle = currentSlideEl.getAttribute('data-ts-ss-href');
		slideshowPushie.pushHistory({
			data: {
				currentSlide: this.current
			},
			title: currentSlideElTitle,
			href: currentSlideElTitle
		});
	}
	// translate value
	var translateVal = -1 * this.current * 100 / this.itemsCount;

	if (this.support) {
		this.$list.style[this.transformName] = this.support3d ? 'translate3d(' + translateVal + '%,0,0)' : 'translate(' + translateVal + '%)';
	}
	else {
		this.$list.style['margin-left'] = -1 * this.current * 100 + '%';
	}

	var transitionendfn = function () {
		this.isAnimating = false;
	}.bind(this);

	if (this.support) {
		this.$list.addEventListener(this.transEndEventName, transitionendfn());
	}
	else {
		transitionendfn.call();
	}
	this.emit('slided', this.current);
};

/**
 * update slideshow ui.
 */
StylieSlideshow.prototype._toggleNavControls = function () {
	if (this.options.navarrows) {
		// if the current item is the first one in the list, the left arrow is not shown
		// if the current item is the last one in the list, the right arrow is not shown
		switch (this.current) {
		case 0:
			this.$navNext.style.display = 'block';
			this.$navPrev.style.display = 'none';
			break;
		case this.itemsCount - 1:
			this.$navNext.style.display = 'none';
			this.$navPrev.style.display = 'block';
			break;
		default:
			this.$navNext.style.display = 'block';
			this.$navPrev.style.display = 'block';
			break;
		}
	}
	if (this.options.navdots) { // highlight navigation dot
		classie.remove(this.$navDots[this.old], this.options.navdots_current_class);
		classie.add(this.$navDots[this.current], this.options.navdots_current_class);
	}
};
/**
 * jump to specific slide.
 * @param {number} position slide to show
 */
StylieSlideshow.prototype._jump = function (position) {
	// do nothing if clicking on the current dot, or if the list is currently moving
	if (position === this.current || this.isAnimating) {
		return false;
	}
	this.isAnimating = true;
	// update old and current values
	this.old = this.current;
	this.current = position;
	// slide
	this._slide();
};
/**
 * delete/remove slideshow elements
 */
StylieSlideshow.prototype.destroy = function () {
	if (this.itemsCount > 1) {
		if (this.options.navarrows) {
			this.$navPrev.parent().remove();
		}
		if (this.options.navdots) {
			this.$navDots.parent().remove();
		}
	}
	this.$list.css('width', 'auto');
	if (this.support) {
		this.$list.css('transition', 'none');
	}
	this.$items.css('width', 'auto');
};

if (typeof window === 'object') {
	window.StylieSlideshow = StylieSlideshow;
}
if (typeof module === 'object') {
	module.exports = StylieSlideshow;
}
<commit_msg>Fix for dot navigation not updating arrows<commit_after>/*
 * stylie.slideshows
 * http://github.com/typesettin
 *
 * Copyright (c) 2013 Amex Pub. All rights reserved.
 */

'use strict';

var classie = require('classie'),
	extend = require('util-extend'),
	events = require('events'),
	Pushie = require('pushie'),
	util = require('util'),
	slideshowPushie,
	Hammer,
	detectCSS = require('detectcss');

var getEventTarget = function (e) {
	e = e || window.event;
	return e.target || e.srcElement;
};

/**
 * A module that represents a full with slideshow componenet object, a stylie.slideshows is a slideshow.
 * @{@link https://github.com/typesettin/stylie.slideshows}
 * @author Yaw Joseph Etse
 * @copyright Copyright (c) 2014 Typesettin. All rights reserved.
 * @license MIT
 * @constructor StylieSlideshow
 * @requires module:util-extent
 * @requires module:util
 * @requires module:events
 * @requires module:hammerjs
 * @requires module:detectcss
 * @param {object} config {el -  element of tab container}
 * @param {object} options configuration options
 */
var StylieSlideshow = function (config) {
	// console.log(config);
	this.$el = config.element;
	this.jump = this._jump;
	this.slide = this._slide;
	this.navigate = this._navigate;
	this._init(config.options);
};

util.inherits(StylieSlideshow, events.EventEmitter);

/** module default configuration */
StylieSlideshow.prototype._init = function (options) {
	var defaults = {
		speed: 500, // default transition speed (ms)
		touchsupport: true,
		usepushstate: false,
		navarrows: true,
		navarrows_next_html: '>',
		navarrows_next_class: 'ts-ss-slidenext',
		navarrows_prev_html: '<',
		navarrows_prev_class: 'ts-ss-slideprev',
		navdots: true,
		navdots_class: 'ts-ss-dots',
		navdots_current_class: 'ts-ss-currentdot',
		easing: 'ease' // default transition easing
	};
	options = options || {};
	this.options = extend(defaults, options);
	this._config();
	this._initEvents(); // initialize/bind the events
};

/**
 * initializes slideshow and shows current slide.
 * @emits slidesInitialized
 */
StylieSlideshow.prototype._config = function () {

	// the list of items
	this.$list = this.$el.querySelector('ul');
	this.$items = this.$list.querySelectorAll('li');
	// total number of items
	this.itemsCount = this.$items.length;
	// support for CSS Transitions & transforms

	this.support = detectCSS.prefixed('transition') && detectCSS.feature('transform');
	this.support3d = detectCSS.prefixed('perspective');

	// transition end event name and transform name
	// transition end event name
	var transEndEventNames = {
			'WebkitTransition': 'webkitTransitionEnd',
			'MozTransition': 'transitionend',
			'OTransition': 'oTransitionEnd',
			'msTransition': 'MSTransitionEnd',
			'transition': 'transitionend'
		},
		transformNames = {
			'WebkitTransform': '-webkit-transform',
			'MozTransform': '-moz-transform',
			'OTransform': '-o-transform',
			'msTransform': '-ms-transform',
			'transform': 'transform'
		};

	if (this.support) {
		this.transEndEventName = transEndEventNames[detectCSS.prefixed('transition')] + '.p_c_fws';
		this.transformName = transformNames[detectCSS.prefixed('transform')];
	}
	// current and old item´s index
	this.current = 0;
	this.old = 0;
	// check if the list is currently moving
	this.isAnimating = false;
	// the list (ul) will have a width of 100% x itemsCount
	this.$list.style.width = 100 * this.itemsCount + '%';
	// apply the transition
	if (this.support) {
		this.$list.style.transition = this.transformName + ' ' + this.options.speed + 'ms ' + this.options.easing;
	}
	// each item will have a width of 100 / itemsCount

	for (var x in this.$items) {
		if (this.$items[x].style) {
			this.$items[x].style.width = 100 / this.itemsCount + '%';
		}
	}
	if (this.itemsCount > 1) { // add navigation arrows and the navigation dots if there is more than 1 item
		if (this.options.navarrows) { // add navigation arrows (the previous arrow is not shown initially):
			var nav = document.createElement('nav');
			nav.innerHTML = '' + this.options.navarrows_prev_html + '' + this.options.navarrows_next_html + '';
			this.$el.appendChild(nav);
			this.$navPrev = this.$el.querySelector('.' + this.options.navarrows_prev_class);
			this.$navNext = this.$el.querySelector('.' + this.options.navarrows_next_class);
		}
		if (this.options.navdots) {
			var dots = '';
			for (var i = 0; i < this.itemsCount; ++i) { // current dot will have the class p_c_fws-cuurentdot
				var dot = i === this.current ? '' : '';
				dots += dot;
			}
			var navDots = document.createElement('div');
			navDots.setAttribute('class', this.options.navdots_class);
			// console.log("navDots",navDots);
			navDots.innerHTML = dots;
			this.$el.appendChild(navDots);
			this.$navDots = navDots.querySelectorAll('span');
		}
	}
	if (this.options.usepushstate) {
		var initSlideIndex,
			jumpToSlide = function (data) {
				// console.log('popcallback');
				this.jump(data.currentSlide);
			}.bind(this),
			jumpToFirstInitialSlide = function () {
				var winhref, winhash;
				for (var q = 0; q < this.itemsCount; q++) {
					winhref = window.location.href;
					winhref = (winhref.search(window.location.origin) >= 0) ? winhref.replace(window.location.origin, '') : winhref;
					winhash = window.location.hash.substr(1, window.location.hash.length);
					winhash = (winhash.search(window.location.origin) >= 0) ? winhash.replace(window.location.origin, '') : winhash;
					if (this.$items[q].getAttribute('data-ts-ss-href') === winhref || this.$items[q].getAttribute('data-ts-ss-href') === winhash) {
						initSlideIndex = q;
					}
					if (initSlideIndex) {
						this.jump(initSlideIndex);
					}
				}
			}.bind(this); //,
		// initialSlideIndex=0;
		slideshowPushie = new Pushie({
			popcallback: jumpToSlide,
			pushcallback: function ( /*data*/ ) {
				// console.log('pushcallback');
			},
			replacecallback: function ( /*data*/ ) {
				// console.log('replacecallback');
			},
		});
		jumpToFirstInitialSlide();
	}
	this.emit('slidesInitialized');
};

/**
 * handle slideshow click events.
 */
StylieSlideshow.prototype._initEvents = function () {
	if (this.options.touchsupport) {
		Hammer = require('hammerjs');
		var hammertime = new Hammer(this.$el, {
			drag_block_horizontal: true
		});

		hammertime.on('swiperight', function (ev) {
			this.emit('swipedright', ev);
			this._navigate('previous');
		}.bind(this));

		hammertime.on('swipeleft', function (ev) {
			this.emit('swipeleft', ev);
			this._navigate('next');
		}.bind(this));
	}
	if (this.itemsCount > 1) {
		if (this.options.navarrows) {
			this.$navPrev.addEventListener('click', function () {
				this._navigate('previous');
			}.bind(this));

			this.$navNext.addEventListener('click', function () {
				this._navigate('next');
			}.bind(this));
		}
		if (this.options.navdots) {
			this.$navDotDom = this.$el.querySelector('.' + this.options.navdots_class);

			this.$navDotDom.addEventListener('click', function (event) {
				var target = getEventTarget(event);
				if (target.tagName === 'SPAN') {
					this._jump(target.getAttribute('data-itr'));
				}
			}.bind(this));
		}
	}
};

/**
 * move slideshow to slide based on the direction.
 * @param {string} direction (previous|next) slide
 * @emits slided
 */
StylieSlideshow.prototype._navigate = function (direction) {
	// do nothing if the list is currently moving
	if (this.isAnimating) {
		return false;
	}

	this.isAnimating = true;
	// update old and current values
	this.old = this.current;
	if (direction === 'next' && this.current < this.itemsCount - 1) {
		++this.current;
	}
	else if (direction === 'previous' && this.current > 0) {
		--this.current;
	}
	this.emit('navigatedComponent', this.current);

	// slide
	this._slide();
	// console.log('this._slide()',this._slide());
};

/**
 * slide to show this.current(index) slide.
 * @emits slided
 */
StylieSlideshow.prototype._slide = function () {
	// check which navigation arrows should be shown
	this._toggleNavControls();
	if (this.options.usepushstate) {
		// console.log('this.current', this.current);
		// console.log('this.$items[this.current]', this.$items[this.current]);
		var currentSlideEl = this.$items[this.current],
			currentSlideElTitle = currentSlideEl.getAttribute('data-ts-ss-href');
		slideshowPushie.pushHistory({
			data: {
				currentSlide: this.current
			},
			title: currentSlideElTitle,
			href: currentSlideElTitle
		});
	}
	// translate value
	var translateVal = -1 * this.current * 100 / this.itemsCount;

	if (this.support) {
		this.$list.style[this.transformName] = this.support3d ? 'translate3d(' + translateVal + '%,0,0)' : 'translate(' + translateVal + '%)';
	}
	else {
		this.$list.style['margin-left'] = -1 * this.current * 100 + '%';
	}

	var transitionendfn = function () {
		this.isAnimating = false;
	}.bind(this);

	if (this.support) {
		this.$list.addEventListener(this.transEndEventName, transitionendfn());
	}
	else {
		transitionendfn.call();
	}
	this.emit('slided', this.current);
};

/**
 * update slideshow ui.
 */
StylieSlideshow.prototype._toggleNavControls = function () {
	if (this.options.navarrows) {
		// if the current item is the first one in the list, the left arrow is not shown
		// if the current item is the last one in the list, the right arrow is not shown
		switch (this.current) {
		case 0:
			this.$navNext.style.display = 'block';
			this.$navPrev.style.display = 'none';
			break;
		case this.itemsCount - 1:
			this.$navNext.style.display = 'none';
			this.$navPrev.style.display = 'block';
			break;
		default:
			this.$navNext.style.display = 'block';
			this.$navPrev.style.display = 'block';
			break;
		}
	}
	if (this.options.navdots) { // highlight navigation dot
		classie.remove(this.$navDots[this.old], this.options.navdots_current_class);
		classie.add(this.$navDots[this.current], this.options.navdots_current_class);
	}
};
/**
 * jump to specific slide.
 * @param {number} position slide to show
 */
StylieSlideshow.prototype._jump = function (position) {
	// do nothing if clicking on the current dot, or if the list is currently moving
	if (position === this.current || this.isAnimating) {
		return false;
	}
	this.isAnimating = true;
	// update old and current values
	this.old = this.current;
	this.current = parseInt(position, 10);
	// slide
	this._slide();
};
/**
 * delete/remove slideshow elements
 */
StylieSlideshow.prototype.destroy = function () {
	if (this.itemsCount > 1) {
		if (this.options.navarrows) {
			this.$navPrev.parent().remove();
		}
		if (this.options.navdots) {
			this.$navDots.parent().remove();
		}
	}
	this.$list.css('width', 'auto');
	if (this.support) {
		this.$list.css('transition', 'none');
	}
	this.$items.css('width', 'auto');
};

if (typeof window === 'object') {
	window.StylieSlideshow = StylieSlideshow;
}
if (typeof module === 'object') {
	module.exports = StylieSlideshow;
}
<|endoftext|>


<commit_before>"use strict";

var currentViewer;
var viewerElement;
var currentScene;
var config;
var justOnce;

var threshold = 25;
var errorRatio = 1.5;

// Overload the random to make it deterministic
var seed = 100000,
    constant = Math.pow(2, 13) + 1,
    prime = 37,
    maximum = Math.pow(2, 50);

Math.random = function () {
    seed *= constant;
    seed += prime;
    seed %= maximum;

    return seed / maximum;
}

function compare(renderData, referenceCanvas) {
    var width = referenceCanvas.width;
    var height = referenceCanvas.height;
    var size = width * height * 4;

    var referenceContext = referenceCanvas.getContext("2d");

    var referenceData = referenceContext.getImageData(0, 0, width, height);

    var differencesCount = 0;
    for (var index = 0; index < size; index += 4) {
        if (Math.abs(renderData[index] - referenceData.data[index]) < threshold &&
            Math.abs(renderData[index + 1] - referenceData.data[index + 1]) < threshold &&
            Math.abs(renderData[index + 2] - referenceData.data[index + 2]) < threshold) {
            continue;
        }

        referenceData.data[index] = 255;
        referenceData.data[index + 1] *= 0.5;
        referenceData.data[index + 2] *= 0.5;
        differencesCount++;
    }

    referenceContext.putImageData(referenceData, 0, 0);

    return (differencesCount * 100) / (width * height) > errorRatio;
}

function getRenderData(canvas, engine) {
    var width = canvas.width;
    var height = canvas.height;

    var renderData = engine.readPixels(0, 0, width, height);
    var numberOfChannelsByLine = width * 4;
    var halfHeight = height / 2;

    for (var i = 0; i < halfHeight; i++) {
        for (var j = 0; j < numberOfChannelsByLine; j++) {
            var currentCell = j + i * numberOfChannelsByLine;
            var targetLine = height - i - 1;
            var targetCell = j + targetLine * numberOfChannelsByLine;

            var temp = renderData[currentCell];
            renderData[currentCell] = renderData[targetCell];
            renderData[targetCell] = temp;
        }
    }

    return renderData;
}

function saveRenderImage(data, canvas) {
    var width = canvas.width;
    var height = canvas.height;
    var screenshotCanvas = document.createElement('canvas');
    screenshotCanvas.width = width;
    screenshotCanvas.height = height;
    var context = screenshotCanvas.getContext('2d');

    var imageData = context.createImageData(width, height);
    var castData = imageData.data;
    castData.set(data);
    context.putImageData(imageData, 0, 0);

    return screenshotCanvas.toDataURL();
}

function downloadDataUrlFromJavascript(filename, dataUrl) {

    // Construct the 'a' element
    var link = document.createElement("a");
    link.download = filename;
    link.target = "_blank";

    // Construct the URI
    link.href = dataUrl;
    document.body.appendChild(link);
    link.click();

    // Cleanup the DOM
    document.body.removeChild(link);
}

function evaluate(test, resultCanvas, result, renderImage, index, waitRing, done) {
    seed = 100000;
    var renderData = getRenderData(currentViewer.canvas, currentViewer.engine);
    var testRes = true;

    // gl check
    var gl = currentViewer.engine._gl;
    if (gl.getError() !== 0) {
        result.classList.add("failed");
        result.innerHTML = "×";
        testRes = false;
        console.log('%c failed (gl error)', 'color: red');
    } else {

        // Visual check
        if (!test.onlyVisual) {
            if (compare(renderData, resultCanvas)) {
                result.classList.add("failed");
                result.innerHTML = "×";
                testRes = false;
                console.log('%c failed', 'color: red');
            } else {
                result.innerHTML = "✔";
                testRes = true;
                console.log('%c validated', 'color: green');
            }
        }
    }
    waitRing.classList.add("hidden");

    var renderB64 = saveRenderImage(renderData, currentViewer.canvas);
    renderImage.src = renderB64;

    // save all reference images
    // downloadDataUrlFromJavascript(test.referenceImage, renderB64)

    done(testRes, renderB64);
}

function runTest(index, done) {
    if (index >= config.tests.length) {
        done(false);
    }

    var test = Object.assign({}, config.tests[index]);

    var container = document.createElement("div");
    container.id = "container#" + index;
    container.className = "container";
    document.body.appendChild(container);

    var titleContainer = document.createElement("div");
    titleContainer.className = "containerTitle";
    container.appendChild(titleContainer);

    var title = document.createElement("div");
    title.className = "title";
    titleContainer.appendChild(title);

    var result = document.createElement("div");
    result.className = "result";
    titleContainer.appendChild(result);

    var waitRing = document.createElement("img");
    waitRing.className = "waitRing";
    titleContainer.appendChild(waitRing);
    waitRing.src = "/tests/validation/loading.gif";

    var resultCanvas = document.createElement("canvas");
    resultCanvas.className = "resultImage";
    container.appendChild(resultCanvas);

    title.innerHTML = test.title;

    console.log("Running " + test.title);

    var resultContext = resultCanvas.getContext("2d");
    var img = new Image();
    img.onload = function () {
        resultCanvas.width = img.width;
        resultCanvas.height = img.height;
        resultContext.drawImage(img, 0, 0);
    }

    img.src = "/tests/validation/ReferenceImages/" + test.referenceImage;

    var renderImage = new Image();
    renderImage.className = "renderImage";
    container.appendChild(renderImage);

    location.href = "#" + container.id;

    //run a single test
    var configuration = test.configuration || {};

    configuration.engine = configuration.engine || {};
    configuration.engine.engineOptions = configuration.engine.engineOptions || {};
    configuration.engine.engineOptions.preserveDrawingBuffer = true;

    //cancel camera behvaviors for the tests
    configuration.camera = configuration.camera || {};
    configuration.camera.behaviors = null;

    // make sure we use only local assets
    /*configuration.skybox = {
        cubeTexture: {
            url: "DefaultSkybox_cube_radiance_256.dds"
        }
    }*/

    //envirnonment directory
    configuration.lab = configuration.lab || {};
    configuration.lab.assetsRootURL = "/dist/assets/environment/";
    if (!test.enableEnvironment) {
        configuration.lab.environmentMap = false;
    } else {
        console.log(configuration.lab.environmentMap)
    }

    //model config
    configuration.model = configuration.model || {};
    //configuration.model.castShadow = !test.createMesh
    configuration.model.entryAnimation = false;

    // create a new viewer
    currentViewer && currentViewer.dispose();
    currentViewer && currentViewer.engine.dispose();

    setTimeout(() => {
        currentViewer = null;
        currentScene = null;
        viewerElement.innerHTML = '';
        currentViewer = new BabylonViewer.DefaultViewer(viewerElement, configuration);

        currentViewer.onInitDoneObservable.add(() => {

            var currentFrame = 0;
            var waitForFrame = test.waitForFrame || 0;

            currentViewer.onModelLoadedObservable.add((model) => {
                console.log("model loaded");
                currentViewer.onFrameRenderedObservable.add(() => {
                    console.log("frame rendered", currentFrame, model.meshes.every(m => m.isReady()));
                    if (test.animationTest && !currentFrame) {
                        model.playAnimation(model.getAnimationNames()[0]);
                    }
                    if (currentFrame === waitForFrame) {
                        currentViewer.onFrameRenderedObservable.clear();
                        currentViewer.sceneManager.scene.executeWhenReady(() => {
                            evaluate(test, resultCanvas, result, renderImage, index, waitRing, done);
                        });
                    }
                    currentFrame++;
                });
            });

            if (test.model) {
                currentViewer.initModel(test.model);
            } else if (test.createMesh) {
                prepareMeshForViewer(currentViewer, configuration, test);
            }
        });
    });
}

function prepareMeshForViewer(viewer, configuration, test) {
    let meshModel = new BabylonViewer.ViewerModel(viewer, configuration.model || {});

    let sphereMesh = BABYLON.Mesh.CreateSphere('sphere-' + test.title, 20, 1.0, viewer.sceneManager.scene);
    if (test.createMaterial) {
        let material = new BABYLON.PBRMaterial("sphereMat", viewer.sceneManager.scene);
        sphereMesh.material = material;
    }
    meshModel.addMesh(sphereMesh, true);
    meshModel.rootMesh.position.y = 0.5;
    console.log("sphere created");
}

function init() {
    BABYLON.SceneLoader.ShowLoadingScreen = false;
    BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental = true;

    // Draco configuration
    BABYLON.DracoCompression.Configuration.decoder = {
        wasmUrl: "../../dist/preview%20release/draco_wasm_wrapper_gltf.js",
        wasmBinaryUrl: "../../dist/preview%20release/draco_decoder_gltf.wasm",
        fallbackUrl: "../../dist/preview%20release/draco_decoder_gltf.js"
    };

    viewerElement = document.createElement("babylon");
    document.body.appendChild(viewerElement);

    // disable init
    BabylonViewer.viewerGlobals.disableInit = true;
}

init();

<commit_msg>deprecated lab feature<commit_after>"use strict";

var currentViewer;
var viewerElement;
var currentScene;
var config;
var justOnce;

var threshold = 25;
var errorRatio = 1.5;

// Overload the random to make it deterministic
var seed = 100000,
    constant = Math.pow(2, 13) + 1,
    prime = 37,
    maximum = Math.pow(2, 50);

Math.random = function () {
    seed *= constant;
    seed += prime;
    seed %= maximum;

    return seed / maximum;
}

function compare(renderData, referenceCanvas) {
    var width = referenceCanvas.width;
    var height = referenceCanvas.height;
    var size = width * height * 4;

    var referenceContext = referenceCanvas.getContext("2d");

    var referenceData = referenceContext.getImageData(0, 0, width, height);

    var differencesCount = 0;
    for (var index = 0; index < size; index += 4) {
        if (Math.abs(renderData[index] - referenceData.data[index]) < threshold &&
            Math.abs(renderData[index + 1] - referenceData.data[index + 1]) < threshold &&
            Math.abs(renderData[index + 2] - referenceData.data[index + 2]) < threshold) {
            continue;
        }

        referenceData.data[index] = 255;
        referenceData.data[index + 1] *= 0.5;
        referenceData.data[index + 2] *= 0.5;
        differencesCount++;
    }

    referenceContext.putImageData(referenceData, 0, 0);

    return (differencesCount * 100) / (width * height) > errorRatio;
}

function getRenderData(canvas, engine) {
    var width = canvas.width;
    var height = canvas.height;

    var renderData = engine.readPixels(0, 0, width, height);
    var numberOfChannelsByLine = width * 4;
    var halfHeight = height / 2;

    for (var i = 0; i < halfHeight; i++) {
        for (var j = 0; j < numberOfChannelsByLine; j++) {
            var currentCell = j + i * numberOfChannelsByLine;
            var targetLine = height - i - 1;
            var targetCell = j + targetLine * numberOfChannelsByLine;

            var temp = renderData[currentCell];
            renderData[currentCell] = renderData[targetCell];
            renderData[targetCell] = temp;
        }
    }

    return renderData;
}

function saveRenderImage(data, canvas) {
    var width = canvas.width;
    var height = canvas.height;
    var screenshotCanvas = document.createElement('canvas');
    screenshotCanvas.width = width;
    screenshotCanvas.height = height;
    var context = screenshotCanvas.getContext('2d');

    var imageData = context.createImageData(width, height);
    var castData = imageData.data;
    castData.set(data);
    context.putImageData(imageData, 0, 0);

    return screenshotCanvas.toDataURL();
}

function downloadDataUrlFromJavascript(filename, dataUrl) {

    // Construct the 'a' element
    var link = document.createElement("a");
    link.download = filename;
    link.target = "_blank";

    // Construct the URI
    link.href = dataUrl;
    document.body.appendChild(link);
    link.click();

    // Cleanup the DOM
    document.body.removeChild(link);
}

function evaluate(test, resultCanvas, result, renderImage, index, waitRing, done) {
    seed = 100000;
    var renderData = getRenderData(currentViewer.canvas, currentViewer.engine);
    var testRes = true;

    // gl check
    var gl = currentViewer.engine._gl;
    if (gl.getError() !== 0) {
        result.classList.add("failed");
        result.innerHTML = "×";
        testRes = false;
        console.log('%c failed (gl error)', 'color: red');
    } else {

        // Visual check
        if (!test.onlyVisual) {
            if (compare(renderData, resultCanvas)) {
                result.classList.add("failed");
                result.innerHTML = "×";
                testRes = false;
                console.log('%c failed', 'color: red');
            } else {
                result.innerHTML = "✔";
                testRes = true;
                console.log('%c validated', 'color: green');
            }
        }
    }
    waitRing.classList.add("hidden");

    var renderB64 = saveRenderImage(renderData, currentViewer.canvas);
    renderImage.src = renderB64;

    // save all reference images
    // downloadDataUrlFromJavascript(test.referenceImage, renderB64)

    done(testRes, renderB64);
}

function runTest(index, done) {
    if (index >= config.tests.length) {
        done(false);
    }

    var test = Object.assign({}, config.tests[index]);

    var container = document.createElement("div");
    container.id = "container#" + index;
    container.className = "container";
    document.body.appendChild(container);

    var titleContainer = document.createElement("div");
    titleContainer.className = "containerTitle";
    container.appendChild(titleContainer);

    var title = document.createElement("div");
    title.className = "title";
    titleContainer.appendChild(title);

    var result = document.createElement("div");
    result.className = "result";
    titleContainer.appendChild(result);

    var waitRing = document.createElement("img");
    waitRing.className = "waitRing";
    titleContainer.appendChild(waitRing);
    waitRing.src = "/tests/validation/loading.gif";

    var resultCanvas = document.createElement("canvas");
    resultCanvas.className = "resultImage";
    container.appendChild(resultCanvas);

    title.innerHTML = test.title;

    console.log("Running " + test.title);

    var resultContext = resultCanvas.getContext("2d");
    var img = new Image();
    img.onload = function () {
        resultCanvas.width = img.width;
        resultCanvas.height = img.height;
        resultContext.drawImage(img, 0, 0);
    }

    img.src = "/tests/validation/ReferenceImages/" + test.referenceImage;

    var renderImage = new Image();
    renderImage.className = "renderImage";
    container.appendChild(renderImage);

    location.href = "#" + container.id;

    //run a single test
    var configuration = test.configuration || {};

    configuration.engine = configuration.engine || {};
    configuration.engine.engineOptions = configuration.engine.engineOptions || {};
    configuration.engine.engineOptions.preserveDrawingBuffer = true;

    //cancel camera behvaviors for the tests
    configuration.camera = configuration.camera || {};
    configuration.camera.behaviors = null;

    // make sure we use only local assets

    //envirnonment directory
    configuration.scene = configuration.scene || {};
    configuration.scene.assetsRootURL = "http://localhost:3000/dist/assets/environment/";
    if (!test.enableEnvironment) {
        configuration.environmentMap = false;
    } else {
        console.log(configuration.environmentMap)
    }

    //model config
    configuration.model = configuration.model || {};
    //configuration.model.castShadow = !test.createMesh
    configuration.model.entryAnimation = false;

    // create a new viewer
    currentViewer && currentViewer.dispose();
    currentViewer && currentViewer.engine.dispose();

    setTimeout(() => {
        currentViewer = null;
        currentScene = null;
        viewerElement.innerHTML = '';
        currentViewer = new BabylonViewer.DefaultViewer(viewerElement, configuration);

        currentViewer.onInitDoneObservable.add(() => {

            var currentFrame = 0;
            var waitForFrame = test.waitForFrame || 0;

            currentViewer.onModelLoadedObservable.add((model) => {
                console.log("model loaded");
                currentViewer.onFrameRenderedObservable.add(() => {
                    console.log("frame rendered", currentFrame, model.meshes.every(m => m.isReady()));
                    if (test.animationTest && !currentFrame) {
                        model.playAnimation(model.getAnimationNames()[0]);
                    }
                    if (currentFrame === waitForFrame) {
                        currentViewer.onFrameRenderedObservable.clear();
                        currentViewer.sceneManager.scene.executeWhenReady(() => {
                            evaluate(test, resultCanvas, result, renderImage, index, waitRing, done);
                        });
                    }
                    currentFrame++;
                });
            });

            if (test.model) {
                currentViewer.initModel(test.model);
            } else if (test.createMesh) {
                prepareMeshForViewer(currentViewer, configuration, test);
            }
        });
    });
}

function prepareMeshForViewer(viewer, configuration, test) {
    let meshModel = new BabylonViewer.ViewerModel(viewer, configuration.model || {});

    let sphereMesh = BABYLON.Mesh.CreateSphere('sphere-' + test.title, 20, 1.0, viewer.sceneManager.scene);
    if (test.createMaterial) {
        let material = new BABYLON.PBRMaterial("sphereMat", viewer.sceneManager.scene);
        sphereMesh.material = material;
    }
    meshModel.addMesh(sphereMesh, true);
    meshModel.rootMesh.position.y = 0.5;
    console.log("sphere created");
}

function init() {
    BABYLON.SceneLoader.ShowLoadingScreen = false;
    BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental = true;

    // Draco configuration
    BABYLON.DracoCompression.Configuration.decoder = {
        wasmUrl: "../../dist/preview%20release/draco_wasm_wrapper_gltf.js",
        wasmBinaryUrl: "../../dist/preview%20release/draco_decoder_gltf.wasm",
        fallbackUrl: "../../dist/preview%20release/draco_decoder_gltf.js"
    };

    viewerElement = document.createElement("babylon");
    document.body.appendChild(viewerElement);

    // disable init
    BabylonViewer.viewerGlobals.disableInit = true;
}

init();

<|endoftext|>


<commit_before>var MTConnect = function(options){
	this.options = $.extend({
		agent: 'http://agent.mtconnect.org',
		proxy: null
	}, options);

	// Private functionality
	var createUrl = function(options, resource, params){
		var url = '';

		// Create url, with proxy if provided
		if(options.proxy) url += options.proxy;
		url += options.agent;

		// Append resource name
		if(resource) url += '/' + resource;

		// If we have any parameters, add those to the querystring
		if(params){
			url += '?'
			for(var i in params){
				url += i + '=' + params[i];
			}
		}

		return url;
	};

	var fetchXmlDocumentFromUrl = function(url){
		return $.ajax({
			type: 'GET',
			url: url,
			async: false,
			cache: false,
			dataType: 'xml'
		}).responseText;
	};

	// Public interface
	this.probe = function(){
		var url = createUrl(this.options);
		return fetchXmlDocumentFromUrl(url);
	};

	this.current = function(){
		var params = {};
		if(this.options.at) params.at = this.options.at;
		if(this.options.path) params.path = this.options.path;

		var url = createUrl(this.options, 'current', params);

		return fetchXmlDocumentFromUrl(url);
	};

	this.sample = function(){
		var params = {};
		if(this.options.from) params.from = this.options.from;
		if(this.options.path) params.path = this.options.path;
		if(this.options.count) params.count = this.options.count;

		var url = createUrl(this.options, 'sample', params);

		return fetchXmlDocumentFromUrl(url);
	};

};

MTConnect.devices = function(doc){
	return $(doc).find('Device');
};

MTConnect.header = function(doc){
	return $(doc).find('Header');
};

MTConnect.dataItems = function(doc){
	var $doc = $(doc);
	if($doc.filter('MTConnectDevices').length>0){
		return $doc.find('DataItem');
	}
	else{
		return $doc.find('Samples,Events,Condition').children();
	}
};<commit_msg>Minor corrections to MTConnect class.<commit_after>var MTConnect = function(options){
	this.options = $.extend({
		agent: 'http://agent.mtconnect.org',
		proxy: null
	}, options);

	// Private functionality
	var createUrl = function(options, resource, params){
		var url = '';

		// Create url, with proxy if provided
		if(options.proxy) url += options.proxy;
		url += options.agent;

		// Append resource name
		if(resource) url += '/' + resource;

		// If we have any parameters, add those to the querystring
		var qs = []
		if(params){
			url += '?'
			for(var i in params){
				qs.push(i + '=' + params[i]);
			}
			url += qs.join('&');
		}

		return url;
	};

	var fetchXmlDocumentFromUrl = function(url){
		return $.ajax({
			type: 'GET',
			url: url,
			async: false,
			cache: false,
			dataType: 'xml'
		}).responseText;
	};

	// Public interface
	this.probe = function(){
		var url = createUrl(this.options);
		return fetchXmlDocumentFromUrl(url);
	};

	this.current = function(options){
		var params = {};
		options = $.extend({}, this.options, options);
		if(options.at) params.at = options.at;
		if(options.path) params.path = options.path;

		var url = createUrl(options, 'current', params);

		return fetchXmlDocumentFromUrl(url);
	};

	this.sample = function(options){
		var params = {};
		options = $.extend({}, this.options, options);
		if(options.from) params.from = options.from;
		if(options.path) params.path = options.path;
		if(options.count) params.count = options.count;

		var url = createUrl(options, 'sample', params);

		return fetchXmlDocumentFromUrl(url);
	};

};

MTConnect.devices = function(doc){
	return $(doc).find('Device');
};

MTConnect.header = function(doc){
	return $(doc).find('Header');
};

MTConnect.dataItems = function(doc){
	var $doc = $(doc);
	if($doc.filter('MTConnectDevices').length>0){
		return $doc.find('DataItem');
	}
	else{
		return $doc.find('Samples,Events,Condition').children();
	}
};<|endoftext|>