<commit_before>/*
 * DateJS Culture String File
 * Country Code: de-AT
 * Name: German (Austria)
 * Format: "key" : "value"
 * Key is the en-US term, Value is the Key in the current language.
 */
Date.CultureStrings = Date.CultureStrings || {};
Date.CultureStrings["de-AT"] = {
        "name": "de-AT",
        "englishName": "German (Austria)",
        "nativeName": "Deutsch (Österreich)",
        "Sunday": "Sonntag",
        "Monday": "Montag",
        "Tuesday": "Dienstag",
        "Wednesday": "Mittwoch",
        "Thursday": "Donnerstag",
        "Friday": "Freitag",
        "Saturday": "Samstag",
        "Sun": "Son",
        "Mon": "Mon",
        "Tue": "Die",
        "Wed": "Mit",
        "Thu": "Don",
        "Fri": "Fre",
        "Sat": "Sam",
        "Su": "So",
        "Mo": "Mo",
        "Tu": "Di",
        "We": "Mi",
        "Th": "Do",
        "Fr": "Fr",
        "Sa": "Sa",
        "S_Sun_Initial": "S",
        "M_Mon_Initial": "M",
        "T_Tue_Initial": "D",
        "W_Wed_Initial": "M",
        "T_Thu_Initial": "D",
        "F_Fri_Initial": "F",
        "S_Sat_Initial": "S",
        "January": "Jänner",
        "February": "Februar",
        "March": "März",
        "April": "April",
        "May": "Mai",
        "June": "Juni",
        "July": "Juli",
        "August": "August",
        "September": "September",
        "October": "Oktober",
        "November": "November",
        "December": "Dezember",
        "Jan_Abbr": "J(ä|a)n",
        "Feb_Abbr": "Feb",
        "Mar_Abbr": "(M(a|ä)r|Mrz)",
        "Apr_Abbr": "Apr",
        "May_Abbr": "Mai",
        "Jun_Abbr": "Jun",
        "Jul_Abbr": "Jul",
        "Aug_Abbr": "Aug",
        "Sep_Abbr": "Sep",
        "Oct_Abbr": "Okt",
        "Nov_Abbr": "Nov",
        "Dec_Abbr": "Dez",
        "AM": "",
        "PM": "",
        "firstDayOfWeek": 1,
        "twoDigitYearMax": 2029,
        "mdy": "dmy",
        "M/d/yyyy": "dd.MM.yyyy",
        "dddd, MMMM dd, yyyy": "dddd, dd. MMMM yyyy",
        "h:mm tt": "HH:mm",
        "h:mm:ss tt": "HH:mm:ss",
        "dddd, MMMM dd, yyyy h:mm:ss tt": "dddd, dd. MMMM yyyy HH:mm:ss",
        "yyyy-MM-ddTHH:mm:ss": "yyyy-MM-ddTHH:mm:ss",
        "yyyy-MM-dd HH:mm:ssZ": "yyyy-MM-dd HH:mm:ssZ",
        "ddd, dd MMM yyyy HH:mm:ss": "ddd, dd MMM yyyy HH:mm:ss",
        "MMMM dd": "dd MMMM",
        "MMMM, yyyy": "MMMM yyyy",
        "/jan(uary)?/": "jän(ner)?",
        "/feb(ruary)?/": "feb(ruar)?",
        "/mar(ch)?/": "mär(z)?",
        "/apr(il)?/": "apr(il)?",
        "/may/": "mai",
        "/jun(e)?/": "jun(i)?",
        "/jul(y)?/": "jul(i)?",
        "/aug(ust)?/": "aug(ust)?",
        "/sep(t(ember)?)?/": "sep(t(ember)?)?",
        "/oct(ober)?/": "okt(ober)?",
        "/nov(ember)?/": "nov(ember)?",
        "/dec(ember)?/": "dez(ember)?",
        "/^su(n(day)?)?/": "^sonntag",
        "/^mo(n(day)?)?/": "^montag",
        "/^tu(e(s(day)?)?)?/": "^dienstag",
        "/^we(d(nesday)?)?/": "^mittwoch",
        "/^th(u(r(s(day)?)?)?)?/": "^donnerstag",
        "/^fr(i(day)?)?/": "^freitag",
        "/^sa(t(urday)?)?/": "^samstag",
        "/^next/": "^nächste(r|s)?",
        "/^last|past|prev(ious)?/": "^letzte(r|s)?|vergangene(r)?|vorherige(r)?",
        "/^(\\+|aft(er)?|from|hence)/": "^(\\+|(da)?nach(er)?|von|daher)",
        "/^(\\-|bef(ore)?|ago)/": "^(\\-|(be|zu)?vor|früher)",
        "/^yes(terday)?/": "^gestern",
        "/^t(od(ay)?)?/": "^heute",
        "/^tom(orrow)?/": "^morgen",
        "/^n(ow)?/": "^jetzt|sofort|gleich",
        "/^ms|milli(second)?s?/": "^ms|milli(sekunde(n)?)?",
        "/^sec(ond)?s?/": "^sek(unde(n)?)?",
        "/^mn|min(ute)?s?/": "^mn|min(ute(n)?)?",
        "/^h(our)?s?/": "^h|st(d|unde(n)?)?",
        "/^w(eek)?s?/": "^w(oche(n)?)?",
        "/^m(onth)?s?/": "^m(onat(e)?)?",
        "/^d(ay)?s?/": "^d|t(ag(e)?)?",
        "/^y(ear)?s?/": "^y|j(ahr(e)?)?",
        "/^(a|p)/": "^(a|p)",
        "/^(a\\.?m?\\.?|p\\.?m?\\.?)/": "^(a\\.?m?\\.?|p\\.?m?\\.?)",
        "/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\\s*(\\+|\\-)\\s*\\d\\d\\d\\d?)|gmt|utc)/": "^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\\s*(\\+|\\-)\\s*\\d\\d\\d\\d?)|gmt|utc)",
        "/^\\s*(st|nd|rd|th)/": "^\\s*(st|nd|rd|th)",
        "/^\\s*(\\:|a(?!u|p)|p)/": "^\\s*(\\:|a(?!u|p)|p)",
        "LINT": "LINT",
        "TOT": "TOT",
        "CHAST": "CHAST",
        "NZST": "NZST",
        "NFT": "NFT",
        "SBT": "SBT",
        "AEST": "AEST",
        "ACST": "ACST",
        "JST": "JST",
        "CWST": "CWST",
        "CT": "CT",
        "ICT": "ICT",
        "MMT": "MMT",
        "BIOT": "BST",
        "NPT": "NPT",
        "IST": "IST",
        "PKT": "PKT",
        "AFT": "AFT",
        "MSK": "MSK",
        "IRST": "IRST",
        "FET": "FET",
        "EET": "EET",
        "CET": "CET",
        "UTC": "UTC",
        "GMT": "GMT",
        "CVT": "CVT",
        "GST": "GST",
        "BRT": "BRT",
        "NST": "NST",
        "AST": "AST",
        "EST": "EST",
        "CST": "CST",
        "MST": "MST",
        "PST": "PST",
        "AKST": "AKST",
        "MIT": "MIT",
        "HST": "HST",
        "SST": "SST",
        "BIT": "BIT",
        "CHADT": "CHADT",
        "NZDT": "NZDT",
        "AEDT": "AEDT",
        "ACDT": "ACDT",
        "AZST": "AZST",
        "IRDT": "IRDT",
        "EEST": "EEST",
        "CEST": "CEST",
        "BST": "BST",
        "PMDT": "PMDT",
        "ADT": "ADT",
        "NDT": "NDT",
        "EDT": "EDT",
        "CDT": "CDT",
        "MDT": "MDT",
        "PDT": "PDT",
        "AKDT": "AKDT",
        "HADT": "HADT"
};
Date.CultureStrings.lang = "de-AT";
<commit_msg>fixed german<commit_after>/*
 * DateJS Culture String File
 * Country Code: de-AT
 * Name: German (Austria)
 * Format: "key" : "value"
 * Key is the en-US term, Value is the Key in the current language.
 */
Date.CultureStrings = Date.CultureStrings || {};
Date.CultureStrings["de-AT"] = {
    "name": "de-AT",
    "englishName": "German (Austria)",
    "nativeName": "Deutsch (Österreich)",
    "Sunday": "Sonntag",
    "Monday": "Montag",
    "Tuesday": "Dienstag",
    "Wednesday": "Mittwoch",
    "Thursday": "Donnerstag",
    "Friday": "Freitag",
    "Saturday": "Samstag",
    "Sun": "Son",
    "Mon": "Mon",
    "Tue": "Die",
    "Wed": "Mit",
    "Thu": "Don",
    "Fri": "Fre",
    "Sat": "Sam",
    "Su": "So",
    "Mo": "Mo",
    "Tu": "Di",
    "We": "Mi",
    "Th": "Do",
    "Fr": "Fr",
    "Sa": "Sa",
    "S_Sun_Initial": "S",
    "M_Mon_Initial": "M",
    "T_Tue_Initial": "D",
    "W_Wed_Initial": "M",
    "T_Thu_Initial": "D",
    "F_Fri_Initial": "F",
    "S_Sat_Initial": "S",
    "January": "Jänner",
    "February": "Februar",
    "March": "März",
    "April": "April",
    "May": "Mai",
    "June": "Juni",
    "July": "Juli",
    "August": "August",
    "September": "September",
    "October": "Oktober",
    "November": "November",
    "December": "Dezember",
    "Jan_Abbr": "J(ä|a)n",
    "Feb_Abbr": "Feb",
    "Mar_Abbr": "(M(a|ä)r|Mrz)",
    "Apr_Abbr": "Apr",
    "May_Abbr": "Mai",
    "Jun_Abbr": "Jun",
    "Jul_Abbr": "Jul",
    "Aug_Abbr": "Aug",
    "Sep_Abbr": "Sep",
    "Oct_Abbr": "Okt",
    "Nov_Abbr": "Nov",
    "Dec_Abbr": "Dez",
    "AM": "",
    "PM": "",
    "firstDayOfWeek": 1,
    "twoDigitYearMax": 2029,
    "mdy": "dmy",
    "M/d/yyyy": "dd.MM.yyyy",
    "dddd, MMMM dd, yyyy": "dddd, dd. MMMM yyyy",
    "h:mm tt": "HH:mm",
    "h:mm:ss tt": "HH:mm:ss",
    "dddd, MMMM dd, yyyy h:mm:ss tt": "dddd, dd. MMMM yyyy HH:mm:ss",
    "yyyy-MM-ddTHH:mm:ss": "yyyy-MM-ddTHH:mm:ss",
    "yyyy-MM-dd HH:mm:ssZ": "yyyy-MM-dd HH:mm:ssZ",
    "ddd, dd MMM yyyy HH:mm:ss": "ddd, dd MMM yyyy HH:mm:ss",
    "MMMM dd": "dd MMMM",
    "MMMM, yyyy": "MMMM yyyy",
    "/jan(uary)?/": "jän(ner)?",
    "/feb(ruary)?/": "feb(ruar)?",
    "/mar(ch)?/": "mär(z)?",
    "/apr(il)?/": "apr(il)?",
    "/may/": "mai",
    "/jun(e)?/": "jun(i)?",
    "/jul(y)?/": "jul(i)?",
    "/aug(ust)?/": "aug(ust)?",
    "/sep(t(ember)?)?/": "sep(t(ember)?)?",
    "/oct(ober)?/": "okt(ober)?",
    "/nov(ember)?/": "nov(ember)?",
    "/dec(ember)?/": "dez(ember)?",
    "/^su(n(day)?)?/": "^sonntag",
    "/^mo(n(day)?)?/": "^montag",
    "/^tu(e(s(day)?)?)?/": "^dienstag",
    "/^we(d(nesday)?)?/": "^mittwoch",
    "/^th(u(r(s(day)?)?)?)?/": "^donnerstag",
    "/^fr(i(day)?)?/": "^freitag",
    "/^sa(t(urday)?)?/": "^samstag",
    "/^next/": "^nächste(r|s|n)?",
    "/^last|past|prev(ious)?/": "^letzte(r|s|n)?|vergangene(r|s|n)?|vorherige(r|s|n)?",
    "/^(\\+|aft(er)?|from|hence)/": "^(\\+|(da)?nach(er)?|von|daher|in)",
    "/^(\\-|bef(ore)?|ago)/": "^(\\-|(be|zu)?vor|früher)",
    "/^yes(terday)?/": "^gestern",
    "/^t(od(ay)?)?/": "^heute",
    "/^tom(orrow)?/": "^morgen",
    "/^n(ow)?/": "^jetzt|sofort|gleich",
    "/^ms|milli(second)?s?/": "^ms|milli(sekunde(n)?)?",
    "/^sec(ond)?s?/": "^sek(unde(n)?)?",
    "/^mn|min(ute)?s?/": "^mn|min(ute(n)?)?",
    "/^h(our)?s?/": "^h|st(d|unde(n)?)?",
    "/^w(eek)?s?/": "^w(oche(n)?)?",
    "/^m(onth)?s?/": "^m(onat(e)?)?",
    "/^d(ay)?s?/": "^d|t(ag(en)?)?",
    "/^y(ear)?s?/": "^y|j(ahr(en)?)?",
    "/^(a|p)/": "^(a|p)",
    "/^(a\\.?m?\\.?|p\\.?m?\\.?)/": "^(a\\.?m?\\.?|p\\.?m?\\.?)",
    "/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\\s*(\\+|\\-)\\s*\\d\\d\\d\\d?)|gmt|utc)/": "^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\\s*(\\+|\\-)\\s*\\d\\d\\d\\d?)|gmt|utc)",
    "/^\\s*(st|nd|rd|th)/": "^\\s*(st|nd|rd|th)",
    "/^\\s*(\\:|a(?!u|p)|p)/": "^\\s*(\\:|a(?!u|p)|p)",
    "LINT": "LINT",
    "TOT": "TOT",
    "CHAST": "CHAST",
    "NZST": "NZST",
    "NFT": "NFT",
    "SBT": "SBT",
    "AEST": "AEST",
    "ACST": "ACST",
    "JST": "JST",
    "CWST": "CWST",
    "CT": "CT",
    "ICT": "ICT",
    "MMT": "MMT",
    "BIOT": "BST",
    "NPT": "NPT",
    "IST": "IST",
    "PKT": "PKT",
    "AFT": "AFT",
    "MSK": "MSK",
    "IRST": "IRST",
    "FET": "FET",
    "EET": "EET",
    "CET": "CET",
    "UTC": "UTC",
    "GMT": "GMT",
    "CVT": "CVT",
    "GST": "GST",
    "BRT": "BRT",
    "NST": "NST",
    "AST": "AST",
    "EST": "EST",
    "CST": "CST",
    "MST": "MST",
    "PST": "PST",
    "AKST": "AKST",
    "MIT": "MIT",
    "HST": "HST",
    "SST": "SST",
    "BIT": "BIT",
    "CHADT": "CHADT",
    "NZDT": "NZDT",
    "AEDT": "AEDT",
    "ACDT": "ACDT",
    "AZST": "AZST",
    "IRDT": "IRDT",
    "EEST": "EEST",
    "CEST": "CEST",
    "BST": "BST",
    "PMDT": "PMDT",
    "ADT": "ADT",
    "NDT": "NDT",
    "EDT": "EDT",
    "CDT": "CDT",
    "MDT": "MDT",
    "PDT": "PDT",
    "AKDT": "AKDT",
    "HADT": "HADT"
};
Date.CultureStrings.lang = "de-AT";
<|endoftext|>


<commit_before>import { fatal } from 'utils/log';
import { missingPlugin } from 'config/errors';
import { magic } from 'config/environment';
import { ensureArray } from 'utils/array';
import { findInViewHierarchy } from 'shared/registry';
import arrayAdaptor from 'Ractive/static/adaptors/array/index';
import magicAdaptor from 'Ractive/static/adaptors/magic';
import magicArrayAdaptor from 'Ractive/static/adaptors/magicArray';
import { getElement } from 'utils/dom';
import { create, extend } from 'utils/object';
import runloop from 'global/runloop';
import config from 'Ractive/config/config';
import dataConfigurator from 'Ractive/config/custom/data';
import Fragment from 'virtualdom/Fragment';
import Viewmodel from 'viewmodel/Viewmodel';
import Hook from './prototype/shared/hooks/Hook';
import HookQueue from './prototype/shared/hooks/HookQueue';
import getComputationSignatures from './helpers/getComputationSignatures';

var constructHook = new Hook( 'construct' ),
	configHook = new Hook( 'config' ),
	initHook = new HookQueue( 'init' ),
	uid = 0,
	registryNames;

registryNames = [
	'adaptors',
	'components',
	'decorators',
	'easing',
	'events',
	'interpolators',
	'partials',
	'transitions'
];

export default initialiseRactiveInstance;

function initialiseRactiveInstance ( ractive, userOptions = {}, options = {} ) {
	var el, viewmodel;

	initialiseProperties( ractive, options );

	// TODO remove this, eventually
	Object.defineProperty( ractive, 'data', { get: deprecateRactiveData });

	// TODO don't allow `onconstruct` with `new Ractive()`, there's no need for it
	constructHook.fire( ractive, userOptions );

	// Add registries
	registryNames.forEach( name => {
		ractive[ name ] = extend( create( ractive.constructor[ name ] || null ), userOptions[ name ] );
	});

	// Create a viewmodel
	viewmodel = new Viewmodel({
		adapt: getAdaptors( ractive, ractive.adapt, userOptions ),
		data: dataConfigurator.init( ractive.constructor, ractive, userOptions ),
		computed: getComputationSignatures( ractive, extend( create( ractive.constructor.prototype.computed ), userOptions.computed ) ),
		mappings: options.mappings,
		ractive: ractive,
		onchange: () => runloop.addRactive( ractive )
	});

	ractive.viewmodel = viewmodel;
	viewmodel.debug = ractive.debug;

	// This can't happen earlier, because computed properties may call `ractive.get()`, etc
	viewmodel.init();

	// init config from Parent and options
	config.init( ractive.constructor, ractive, userOptions );

	// TODO this was moved from Viewmodel.extend - should be
	// rolled in with other config stuff
	if ( ractive.magic && !magic ) {
		throw new Error( 'Getters and setters (magic mode) are not supported in this browser' );
	}

	configHook.fire( ractive );
	initHook.begin( ractive );

	// // If this is a component with a function `data` property, call the function
	// // with `ractive` as context (unless the child was also a function)
	// if ( typeof ractive.constructor.prototype.data === 'function' && typeof userOptions.data !== 'function' ) {
	// 	viewmodel.reset( ractive.constructor.prototype.data.call( ractive ) || fatal( '`data` functions must return a data object' ) );
	// }

	// Render virtual DOM
	if ( ractive.template ) {
		let cssIds;

		if ( options.cssIds || ractive.cssId ) {
			cssIds = options.cssIds ? options.cssIds.slice() : [];

			if ( ractive.cssId ) {
				cssIds.push( ractive.cssId );
			}
		}

		ractive.fragment = new Fragment({
			template: ractive.template,
			root: ractive,
			owner: ractive, // saves doing `if ( this.parent ) { /*...*/ }` later on
			cssIds
		});
	}

	initHook.end( ractive );

	// render automatically ( if `el` is specified )
	if ( el = getElement( ractive.el ) ) {
		ractive.render( el, ractive.append );
	}
}

function getAdaptors ( ractive, protoAdapt, userOptions ) {
	var adapt, magic, modifyArrays;

	protoAdapt = protoAdapt.map( lookup );
	adapt = ensureArray( userOptions.adapt ).map( lookup );

	adapt = combine( protoAdapt, adapt );

	magic = 'magic' in userOptions ? userOptions.magic : ractive.magic;
	modifyArrays = 'modifyArrays' in userOptions ? userOptions.modifyArrays : ractive.modifyArrays;

	if ( magic ) {
		if ( !magic ) {
			throw new Error( 'Getters and setters (magic mode) are not supported in this browser' );
		}

		if ( modifyArrays ) {
			adapt.push( magicArrayAdaptor );
		}

		adapt.push( magicAdaptor );
	}

	if ( modifyArrays ) {
		adapt.push( arrayAdaptor );
	}

	return adapt;

	function lookup ( adaptor ) {
		if ( typeof adaptor === 'string' ) {
			adaptor = findInViewHierarchy( 'adaptors', ractive, adaptor );

			if ( !adaptor ) {
				fatal( missingPlugin( adaptor, 'adaptor' ) );
			}
		}

		return adaptor;
	}
}

function combine ( a, b ) {
	var c = a.slice(), i = b.length;

	while ( i-- ) {
		if ( !~c.indexOf( b[i] ) ) {
			c.push( b[i] );
		}
	}

	return c;
}

function initialiseProperties ( ractive, options ) {
	// Generate a unique identifier, for places where you'd use a weak map if it
	// existed
	ractive._guid = 'r-' + uid++;

	// events
	ractive._subs = create( null );

	// storage for item configuration from instantiation to reset,
	// like dynamic functions or original values
	ractive._config = {};

	// two-way bindings
	ractive._twowayBindings = create( null );

	// animations (so we can stop any in progress at teardown)
	ractive._animations = [];

	// nodes registry
	ractive.nodes = {};

	// live queries
	ractive._liveQueries = [];
	ractive._liveComponentQueries = [];

	// bound data functions
	ractive._boundFunctions = [];

	// properties specific to inline components
	if ( options.component ) {
		ractive.parent = options.parent;
		ractive.container = options.container || null;
		ractive.root = ractive.parent.root;

		ractive.component = options.component;
		options.component.instance = ractive;

		// for hackability, this could be an open option
		// for any ractive instance, but for now, just
		// for components and just for ractive...
		ractive._inlinePartials = options.inlinePartials;
	} else {
		ractive.root = ractive;
		ractive.parent = ractive.container = null;
	}
}

function deprecateRactiveData () {
	throw new Error( 'Using `ractive.data` is no longer supported - you must use the `ractive.get()` API instead' );
}
<commit_msg>fix daft mistake<commit_after>import { fatal } from 'utils/log';
import { missingPlugin } from 'config/errors';
import { magic as magicSupported } from 'config/environment';
import { ensureArray } from 'utils/array';
import { findInViewHierarchy } from 'shared/registry';
import arrayAdaptor from 'Ractive/static/adaptors/array/index';
import magicAdaptor from 'Ractive/static/adaptors/magic';
import magicArrayAdaptor from 'Ractive/static/adaptors/magicArray';
import { getElement } from 'utils/dom';
import { create, extend } from 'utils/object';
import runloop from 'global/runloop';
import config from 'Ractive/config/config';
import dataConfigurator from 'Ractive/config/custom/data';
import Fragment from 'virtualdom/Fragment';
import Viewmodel from 'viewmodel/Viewmodel';
import Hook from './prototype/shared/hooks/Hook';
import HookQueue from './prototype/shared/hooks/HookQueue';
import getComputationSignatures from './helpers/getComputationSignatures';

var constructHook = new Hook( 'construct' ),
	configHook = new Hook( 'config' ),
	initHook = new HookQueue( 'init' ),
	uid = 0,
	registryNames;

registryNames = [
	'adaptors',
	'components',
	'decorators',
	'easing',
	'events',
	'interpolators',
	'partials',
	'transitions'
];

export default initialiseRactiveInstance;

function initialiseRactiveInstance ( ractive, userOptions = {}, options = {} ) {
	var el, viewmodel;

	initialiseProperties( ractive, options );

	// TODO remove this, eventually
	Object.defineProperty( ractive, 'data', { get: deprecateRactiveData });

	// TODO don't allow `onconstruct` with `new Ractive()`, there's no need for it
	constructHook.fire( ractive, userOptions );

	// Add registries
	registryNames.forEach( name => {
		ractive[ name ] = extend( create( ractive.constructor[ name ] || null ), userOptions[ name ] );
	});

	// Create a viewmodel
	viewmodel = new Viewmodel({
		adapt: getAdaptors( ractive, ractive.adapt, userOptions ),
		data: dataConfigurator.init( ractive.constructor, ractive, userOptions ),
		computed: getComputationSignatures( ractive, extend( create( ractive.constructor.prototype.computed ), userOptions.computed ) ),
		mappings: options.mappings,
		ractive: ractive,
		onchange: () => runloop.addRactive( ractive )
	});

	ractive.viewmodel = viewmodel;
	viewmodel.debug = ractive.debug;

	// This can't happen earlier, because computed properties may call `ractive.get()`, etc
	viewmodel.init();

	// init config from Parent and options
	config.init( ractive.constructor, ractive, userOptions );

	configHook.fire( ractive );
	initHook.begin( ractive );

	// // If this is a component with a function `data` property, call the function
	// // with `ractive` as context (unless the child was also a function)
	// if ( typeof ractive.constructor.prototype.data === 'function' && typeof userOptions.data !== 'function' ) {
	// 	viewmodel.reset( ractive.constructor.prototype.data.call( ractive ) || fatal( '`data` functions must return a data object' ) );
	// }

	// Render virtual DOM
	if ( ractive.template ) {
		let cssIds;

		if ( options.cssIds || ractive.cssId ) {
			cssIds = options.cssIds ? options.cssIds.slice() : [];

			if ( ractive.cssId ) {
				cssIds.push( ractive.cssId );
			}
		}

		ractive.fragment = new Fragment({
			template: ractive.template,
			root: ractive,
			owner: ractive, // saves doing `if ( this.parent ) { /*...*/ }` later on
			cssIds
		});
	}

	initHook.end( ractive );

	// render automatically ( if `el` is specified )
	if ( el = getElement( ractive.el ) ) {
		ractive.render( el, ractive.append );
	}
}

function getAdaptors ( ractive, protoAdapt, userOptions ) {
	var adapt, magic, modifyArrays;

	protoAdapt = protoAdapt.map( lookup );
	adapt = ensureArray( userOptions.adapt ).map( lookup );

	adapt = combine( protoAdapt, adapt );

	magic = 'magic' in userOptions ? userOptions.magic : ractive.magic;
	modifyArrays = 'modifyArrays' in userOptions ? userOptions.modifyArrays : ractive.modifyArrays;

	if ( magic ) {
		if ( !magicSupported ) {
			throw new Error( 'Getters and setters (magic mode) are not supported in this browser' );
		}

		if ( modifyArrays ) {
			adapt.push( magicArrayAdaptor );
		}

		adapt.push( magicAdaptor );
	}

	if ( modifyArrays ) {
		adapt.push( arrayAdaptor );
	}

	return adapt;

	function lookup ( adaptor ) {
		if ( typeof adaptor === 'string' ) {
			adaptor = findInViewHierarchy( 'adaptors', ractive, adaptor );

			if ( !adaptor ) {
				fatal( missingPlugin( adaptor, 'adaptor' ) );
			}
		}

		return adaptor;
	}
}

function combine ( a, b ) {
	var c = a.slice(), i = b.length;

	while ( i-- ) {
		if ( !~c.indexOf( b[i] ) ) {
			c.push( b[i] );
		}
	}

	return c;
}

function initialiseProperties ( ractive, options ) {
	// Generate a unique identifier, for places where you'd use a weak map if it
	// existed
	ractive._guid = 'r-' + uid++;

	// events
	ractive._subs = create( null );

	// storage for item configuration from instantiation to reset,
	// like dynamic functions or original values
	ractive._config = {};

	// two-way bindings
	ractive._twowayBindings = create( null );

	// animations (so we can stop any in progress at teardown)
	ractive._animations = [];

	// nodes registry
	ractive.nodes = {};

	// live queries
	ractive._liveQueries = [];
	ractive._liveComponentQueries = [];

	// bound data functions
	ractive._boundFunctions = [];

	// properties specific to inline components
	if ( options.component ) {
		ractive.parent = options.parent;
		ractive.container = options.container || null;
		ractive.root = ractive.parent.root;

		ractive.component = options.component;
		options.component.instance = ractive;

		// for hackability, this could be an open option
		// for any ractive instance, but for now, just
		// for components and just for ractive...
		ractive._inlinePartials = options.inlinePartials;
	} else {
		ractive.root = ractive;
		ractive.parent = ractive.container = null;
	}
}

function deprecateRactiveData () {
	throw new Error( 'Using `ractive.data` is no longer supported - you must use the `ractive.get()` API instead' );
}
<|endoftext|>


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

( function( $ ) {

$.idleTimer = function( firstParam, elem, opts ) {

	// defaults that are to be stored as instance props on the elem
	opts = $.extend( {
		startImmediately: true,   //starts a timeout as soon as the timer is set up
		idle: false,              //indicates if the user is idle
		enabled: true,            //indicates if the idle timer is enabled
		timeout: 30000,           //the amount of time (ms) before the user is considered idle
		events: "mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove" // activity is one of these events
	}, opts );

	elem = elem || document;

	var jqElem = $( elem ),
		obj = jqElem.data("idleTimerObj") || {},

		/* (intentionally not documented)
		 * Toggles the idle state and fires an appropriate event.
		 * @return {void}
		 */
		toggleIdleState = function( myelem ) {

			// curse you, mozilla setTimeout lateness bug!
			if ( typeof myelem === "number" ) {
				myelem = undefined;
			}

			var obj = $.data( myelem || elem, "idleTimerObj" );

			//toggle the state
			obj.idle = !obj.idle;

			// reset timeout
			var elapsed = ( +new Date() ) - obj.olddate;
			obj.olddate = +new Date();

			// handle Chrome always triggering idle after js alert or comfirm popup
			if ( obj.idle && ( elapsed < opts.timeout ) ) {
				obj.idle = false;
				clearTimeout( $.idleTimer.tId );
				if ( opts.enabled ) {
					$.idleTimer.tId = setTimeout( toggleIdleState, opts.timeout );
				}
				return;
			}

			// create a custom event, but first, store the new state on the element
			// and then append that string to a namespace
			var event = $.Event( $.data( elem, "idleTimer", obj.idle ? "idle" : "active" ) + ".idleTimer" );
			$( elem ).trigger( event );
		},

		/**
		 * Stops the idle timer. This removes appropriate event handlers
		 * and cancels any pending timeouts.
		 * @return {void}
		 * @method stop
		 * @static
		 */
		stop = function( jqElem ) {

			var obj = jqElem.data("idleTimerObj") || {};

			//set to disabled
			obj.enabled = false;

			//clear any pending timeouts
			clearTimeout( obj.tId );

			//detach the event handlers
			jqElem.off(".idleTimer");
		};

	obj.olddate = obj.olddate || +new Date();

	if ( typeof firstParam === "number" ) {
		opts.timeout = firstParam;
	} else if ( firstParam === "destroy" ) {
		stop( jqElem );
		return this;
	} else if ( firstParam === "getElapsedTime" ) {
		return ( +new Date() ) - obj.olddate;
	}

	/* (intentionally not documented)
	 * Handles a user event indicating that the user isn't idle.
	 * @param {Event} event A DOM2-normalized event object.
	 * @return {void}
	 */
	jqElem.on( $.trim( ( opts.events + " " ).split(" ").join(".idleTimer ") ), function() {
		var obj = $.data( this, "idleTimerObj" );

		//clear any existing timeout
		clearTimeout( obj.tId );

		//if the idle timer is enabled
		if ( obj.enabled ){
			//if it's idle, that means the user is no longer idle
			if ( obj.idle ){
				toggleIdleState( this );
			}

			//set a new timeout
			obj.tId = setTimeout( toggleIdleState, obj.timeout );
		}
	});

	obj.idle = opts.idle;
	obj.enabled = opts.enabled;
	obj.timeout = opts.timeout;

	//set a timeout to toggle state. May wish to omit this in some situations
	if ( opts.startImmediately ) {
		obj.tId = setTimeout( toggleIdleState, obj.timeout );
	}

	// assume the user is active for the first x seconds.
	jqElem.data( "idleTimer", "active" );

	// store our instance on the object
	jqElem.data( "idleTimerObj", obj );
};

$.fn.idleTimer = function( firstParam, opts ) {
	// Allow omission of opts for backward compatibility
	if ( !opts ) {
		opts = {};
	}

	if ( this[0] ){
		$.idleTimer( firstParam, this[0], opts );
	}

	return this;
};

})( jQuery );
<commit_msg>Fix wrong value being returned if called with $(elem).idleTimer<commit_after>/*
 * Copyright (c) 2009 Nicholas C. Zakas
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

( function( $ ) {

$.idleTimer = function( firstParam, elem, opts ) {

	// defaults that are to be stored as instance props on the elem
	opts = $.extend( {
		startImmediately: true,   //starts a timeout as soon as the timer is set up
		idle: false,              //indicates if the user is idle
		enabled: true,            //indicates if the idle timer is enabled
		timeout: 30000,           //the amount of time (ms) before the user is considered idle
		events: "mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove" // activity is one of these events
	}, opts );

	elem = elem || document;

	var jqElem = $( elem ),
		obj = jqElem.data("idleTimerObj") || {},

		/* (intentionally not documented)
		 * Toggles the idle state and fires an appropriate event.
		 * @return {void}
		 */
		toggleIdleState = function( myelem ) {

			// curse you, mozilla setTimeout lateness bug!
			if ( typeof myelem === "number" ) {
				myelem = undefined;
			}

			var obj = $.data( myelem || elem, "idleTimerObj" );

			//toggle the state
			obj.idle = !obj.idle;

			// reset timeout
			var elapsed = ( +new Date() ) - obj.olddate;
			obj.olddate = +new Date();

			// handle Chrome always triggering idle after js alert or comfirm popup
			if ( obj.idle && ( elapsed < opts.timeout ) ) {
				obj.idle = false;
				clearTimeout( $.idleTimer.tId );
				if ( opts.enabled ) {
					$.idleTimer.tId = setTimeout( toggleIdleState, opts.timeout );
				}
				return;
			}

			// create a custom event, but first, store the new state on the element
			// and then append that string to a namespace
			var event = $.Event( $.data( elem, "idleTimer", obj.idle ? "idle" : "active" ) + ".idleTimer" );
			$( elem ).trigger( event );
		},

		/**
		 * Stops the idle timer. This removes appropriate event handlers
		 * and cancels any pending timeouts.
		 * @return {void}
		 * @method stop
		 * @static
		 */
		stop = function( jqElem ) {

			var obj = jqElem.data("idleTimerObj") || {};

			//set to disabled
			obj.enabled = false;

			//clear any pending timeouts
			clearTimeout( obj.tId );

			//detach the event handlers
			jqElem.off(".idleTimer");
		};

	obj.olddate = obj.olddate || +new Date();

	if ( typeof firstParam === "number" ) {
		opts.timeout = firstParam;
	} else if ( firstParam === "destroy" ) {
		stop( jqElem );
		return this;
	} else if ( firstParam === "getElapsedTime" ) {
		return ( +new Date() ) - obj.olddate;
	}

	/* (intentionally not documented)
	 * Handles a user event indicating that the user isn't idle.
	 * @param {Event} event A DOM2-normalized event object.
	 * @return {void}
	 */
	jqElem.on( $.trim( ( opts.events + " " ).split(" ").join(".idleTimer ") ), function() {
		var obj = $.data( this, "idleTimerObj" );

		//clear any existing timeout
		clearTimeout( obj.tId );

		//if the idle timer is enabled
		if ( obj.enabled ){
			//if it's idle, that means the user is no longer idle
			if ( obj.idle ){
				toggleIdleState( this );
			}

			//set a new timeout
			obj.tId = setTimeout( toggleIdleState, obj.timeout );
		}
	});

	obj.idle = opts.idle;
	obj.enabled = opts.enabled;
	obj.timeout = opts.timeout;

	//set a timeout to toggle state. May wish to omit this in some situations
	if ( opts.startImmediately ) {
		obj.tId = setTimeout( toggleIdleState, obj.timeout );
	}

	// assume the user is active for the first x seconds.
	jqElem.data( "idleTimer", "active" );

	// store our instance on the object
	jqElem.data( "idleTimerObj", obj );
};

$.fn.idleTimer = function( firstParam, opts ) {
	// Allow omission of opts for backward compatibility
	if ( !opts ) {
		opts = {};
	}

	if ( this[0] ){
		return $.idleTimer( firstParam, this[0], opts );
	}

	return this;
};

})( jQuery );
<|endoftext|>


<commit_before>+function() {

  function ImageZoomService() {
    this._scaleBase = 1.0
    this._target = null // Zoomable target
    this._window = window
    this._document = document
    this._body = document.body
    this._lastScrollPosition = null

    this._handleClick = this._handleClick.bind(this)
    this._handleKeyDown = this._handleKeyDown.bind(this)
    this._handleScroll = this._handleScroll.bind(this)
  }

  ImageZoomService.prototype = {
    init: function() {
      this._body.addEventListener('click', this._handleClick)
    },

    _zoom: function() {
      this._calculateZoom((function(translate, scale) {
        this._target.zoomIn(translate, scale)
      }).bind(this))

      this._document.addEventListener('keydown', this._handleKeyDown)
      this._document.addEventListener('scroll', this._handleScroll)
    },

    _close: function() {
      if (!this._target) return

      this._target.zoomOut()
      this._target = null

      this._document.removeEventListener('keydown', this._handleKeyDown)
      this._document.removeEventListener('scroll', this._handleScroll)
    },

    _calculateZoom: function(callback) {
      var imgRect = this._target.getRect()

      var windowCenter = {
        x: this._window.innerWidth / 2,
        y: this._window.innerHeight / 2
      }

      var imgHalfWidth = imgRect.width / 2
      var imgHalfHeight = imgRect.height / 2

      var imgCenter = {
        x: imgRect.left + imgHalfWidth,
        y: imgRect.top + imgHalfHeight
      }

      // The vector to translate image to the window center
      var translate = {
        x: windowCenter.x - imgCenter.x,
        y: windowCenter.y - imgCenter.y
      }

      // The distance between image edge and window edge
      var distFromImageEdgeToWindowEdge = {
        x: windowCenter.x - imgHalfWidth,
        y: windowCenter.y - imgHalfHeight
      }

      // The additional scale is based on the smaller value of
      // scaling horizontally and scaling vertically
      var scaleHorizontally = distFromImageEdgeToWindowEdge.x / imgHalfWidth
      var scaleVertically = distFromImageEdgeToWindowEdge.y / imgHalfHeight
      var scale = this._scaleBase + Math.min(scaleHorizontally, scaleVertically)

      callback(translate, scale)
    },

    _handleClick: function(event) {
      var target = event.target

      if (!target) return

      if (target.tagName === 'IMG' && target.hasAttribute('data-action')) {
        switch (target.getAttribute('data-action')) {
          case 'zoom':
            // Make the target image zoomable
            this._target = new Zoomable(target)
            this._zoom()
            break;
          case 'close':
            this._close()
            break;
          default:
            break;
        }
      } else {
        this._close()
      }
    },

    _handleKeyDown: function(event) {
      if (event.keyCode === 27) this._close() // Esc
    },

    _handleScroll: function(event) {
      var scrollTop = this._window.pageYOffset ||
      (this._document.documentElement || this._document.body.parentNode || this._document.body).scrollTop

      if (this._lastScrollPosition === null) this._lastScrollPosition = scrollTop
      var deltaY = this._lastScrollPosition - scrollTop
      if (Math.abs(deltaY) >= 40) {
        this._lastScrollPosition = null
        this._close()
      }
    }
  }

  /**
   * The zoomable target.
   */
  function Zoomable(target) {
    this._target = target
    this._overlay = null // An overlay that whites out the body
    this._rect = this._target.getBoundingClientRect()
    this._body = document.body

    this._handleTransitionEnd = this._handleTransitionEnd.bind(this)
  }

  Zoomable.prototype = {
    zoomIn: function(translate, scale) {
      this._target.setAttribute('data-action', 'close')
      this._target.classList.add('image-zoom-img')

      // Zoom in the image
      var transform = 'translate(' + translate.x + 'px,' + translate.y + 'px) ' +
      'scale(' + scale + ',' + scale + ')'

      setStyles(this._target, {
        '-webkit-transform': transform,
        '-ms-transform': transform,
        'transform': transform,
      })

      this._overlay = document.createElement('div')

      // If add class to overlay before transforming the image,
      // it will cause image flickering on Safari.
      this._overlay.classList.add('image-zoom-overlay')

      this._body.appendChild(this._overlay)

      // Use setTimeout to apply correct body opacity transition when
      // zooming in, otherwise the transition effect won't trigger.
      window.setTimeout((function() {
        this._body.classList.add('image-zoom-overlay-show')
      }).bind(this), 50)
    },

    zoomOut: function() {
      this._target.setAttribute('data-action', 'zoom')
      this._target.addEventListener('transitionend', this._handleTransitionEnd)
      this._body.classList.remove('image-zoom-overlay-show')

      // Zoom out the image
      setStyles(this._target, {
        '-webkit-transform': '',
        '-ms-transform': '',
        'transform': '',
      })
    },

    getRect: function() {
      return this._rect
    },

    _handleTransitionEnd: function(event) {
      if (this._target.getAttribute('data-action') === 'zoom') {
        this._body.removeChild(this._overlay)
        this._target.classList.remove('image-zoom-img')
      }

      this._target.removeEventListener('transitionend', this._handleTransitionEnd)
    }
  }

  /**
   * Set css styles.
   */
  function setStyles(element, styles) {
    for (var prop in styles) {
      element.style[prop] = styles[prop]
    }
  }

  document.addEventListener('DOMContentLoaded', function() {
    new ImageZoomService().init()
  })
}()
<commit_msg>clean up<commit_after>+function() {

  function ImageZoomService() {
    this._scaleBase = 1.0
    this._target = null // Zoomable target
    this._window = window
    this._document = document
    this._body = document.body
    this._lastScrollPosition = null

    this._handleClick = this._handleClick.bind(this)
    this._handleKeyDown = this._handleKeyDown.bind(this)
    this._handleScroll = this._handleScroll.bind(this)
  }

  ImageZoomService.prototype = {
    init: function() {
      this._body.addEventListener('click', this._handleClick)
    },

    _zoom: function() {
      this._calculateZoom((function(translate, scale) {
        this._target.zoomIn(translate, scale)
      }).bind(this))

      this._document.addEventListener('keydown', this._handleKeyDown)
      this._document.addEventListener('scroll', this._handleScroll)
    },

    _close: function() {
      if (!this._target) return

      this._target.zoomOut()
      this._target = null

      this._document.removeEventListener('keydown', this._handleKeyDown)
      this._document.removeEventListener('scroll', this._handleScroll)
    },

    _calculateZoom: function(callback) {
      var imgRect = this._target.getRect()

      var windowCenter = {
        x: this._window.innerWidth / 2,
        y: this._window.innerHeight / 2
      }

      var imgHalfWidth = imgRect.width / 2
      var imgHalfHeight = imgRect.height / 2

      var imgCenter = {
        x: imgRect.left + imgHalfWidth,
        y: imgRect.top + imgHalfHeight
      }

      // The vector to translate image to the window center
      var translate = {
        x: windowCenter.x - imgCenter.x,
        y: windowCenter.y - imgCenter.y
      }

      // The distance between image edge and window edge
      var distFromImageEdgeToWindowEdge = {
        x: windowCenter.x - imgHalfWidth,
        y: windowCenter.y - imgHalfHeight
      }

      // The additional scale is based on the smaller value of
      // scaling horizontally and scaling vertically
      var scaleHorizontally = distFromImageEdgeToWindowEdge.x / imgHalfWidth
      var scaleVertically = distFromImageEdgeToWindowEdge.y / imgHalfHeight
      var scale = this._scaleBase + Math.min(scaleHorizontally, scaleVertically)

      callback(translate, scale)
    },

    _handleClick: function(event) {
      var target = event.target

      if (!target) return

      if (target.tagName === 'IMG' && target.hasAttribute('data-action')) {
        switch (target.getAttribute('data-action')) {
          case 'zoom':
            // Make the target image zoomable
            this._target = new Zoomable(target)
            this._zoom()
            break;
          case 'close':
            this._close()
            break;
          default:
            break;
        }
      } else {
        this._close()
      }
    },

    _handleKeyDown: function(event) {
      if (event.keyCode === 27) this._close() // Esc
    },

    _handleScroll: function(event) {
      var scrollTop = this._window.pageYOffset ||
      (this._document.documentElement || this._body.parentNode || this._body).scrollTop

      if (this._lastScrollPosition === null) this._lastScrollPosition = scrollTop
      var deltaY = this._lastScrollPosition - scrollTop
      if (Math.abs(deltaY) >= 40) {
        this._lastScrollPosition = null
        this._close()
      }
    }
  }

  /**
   * The zoomable target.
   */
  function Zoomable(target) {
    this._target = target
    this._overlay = null // An overlay that whites out the body
    this._rect = this._target.getBoundingClientRect()
    this._body = document.body
    this._window = window

    this._handleTransitionEnd = this._handleTransitionEnd.bind(this)
  }

  Zoomable.prototype = {
    zoomIn: function(translate, scale) {
      this._target.setAttribute('data-action', 'close')
      this._target.classList.add('image-zoom-img')

      // Zoom in the image
      var transform = 'translate(' + translate.x + 'px,' + translate.y + 'px) ' +
      'scale(' + scale + ',' + scale + ')'

      setStyles(this._target, {
        '-webkit-transform': transform,
        '-ms-transform': transform,
        'transform': transform,
      })

      this._overlay = document.createElement('div')

      // If add class to overlay before transforming the image,
      // it will cause image flickering on Safari.
      this._overlay.classList.add('image-zoom-overlay')

      this._body.appendChild(this._overlay)

      // Use setTimeout to apply correct body opacity transition when
      // zooming in, otherwise the transition effect won't trigger.
      this._window.setTimeout((function() {
        this._body.classList.add('image-zoom-overlay-show')
      }).bind(this), 50)
    },

    zoomOut: function() {
      this._target.setAttribute('data-action', 'zoom')
      this._target.addEventListener('transitionend', this._handleTransitionEnd)
      this._body.classList.remove('image-zoom-overlay-show')

      // Zoom out the image
      setStyles(this._target, {
        '-webkit-transform': '',
        '-ms-transform': '',
        'transform': '',
      })
    },

    getRect: function() {
      return this._rect
    },

    _handleTransitionEnd: function(event) {
      if (this._target.getAttribute('data-action') === 'zoom') {
        this._body.removeChild(this._overlay)
        this._target.classList.remove('image-zoom-img')
      }

      this._target.removeEventListener('transitionend', this._handleTransitionEnd)
    }
  }

  /**
   * Set css styles.
   */
  function setStyles(element, styles) {
    for (var prop in styles) {
      element.style[prop] = styles[prop]
    }
  }

  document.addEventListener('DOMContentLoaded', function() {
    new ImageZoomService().init()
  })
}()
<|endoftext|>


<commit_before>/*
  Luke Mason 2014
  Angular directives which use Canvas to provide an editable context for images.
  Jcrop, used for cropping http://deepliquid.com/content/Jcrop.html
*/
/*Convert a file in the scope into an img src data attribute*/
angular.module('imgManipulation.directives', [])
  .directive('imgData', ['$parse',
    function($parse) {
      return {
        restrict: 'A',
        link: function(scope, element, attributes) {
          var imgData = scope.$eval(attributes.imgData);
          var width, height;
          var reader = new FileReader();
          reader.onload = function(e) {
            scope.$apply(function() {
              var img = new Image();
              img.onload = function() {
                element.attr('src', img.src);
                $(element).css('width', img.width + 'px');
                $(element).css('height', img.height + 'px');
              };
              img.src = reader.result;
              scope.$broadcast('loadedImg', img);
            });
          }
          reader.readAsDataURL(imgData);
        }
      };
    }
  ])
/* read a file from a url and convert it to a data src (this will only work for CORS images */
.directive('imgDataFromUri', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attributes) {
      // Create an empty canvas element
      var canvas = document.createElement("canvas");
      var img = new Image();
      img.onload = function() {
        console.log('loaded Image');
        canvas.width = img.width;
        canvas.height = img.height;
        // Copy the image contents to the canvas
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0);
        var dataURL = canvas.toDataURL("image/png");
        element.attr('src', dataURL);
        $(element).css('width', img.width + 'px');
        $(element).css('height', img.height + 'px');
      }
      img.crossOrigin = '';
      img.src = element.attr('src');
    }
  };
})
  .directive('imgThumb', ['$parse',
    function($parse) {
      return {
        restrict: 'A',
        link: function(scope, element, attributes) {
          scope.$on('loadedImg', function(e, img) {
            element.attr('src', img.src);
          });
          scope.$on('update', function(e, imgSRC) {
            element.attr('src', imgSRC);
          });
        }
      };
    }
  ])
/* add listeners for 'crop', 'rotate' and 'rest' brodcasts */
.directive('imgEditable', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attributes) {
      var jcrop_api;
      var croppedImage; //this will be used to support cancel of crop.
      var fullSize = new Image();
      var orig = new Image();
      scope.crop = false;
      scope.rotation = 0;
      fullSize.src = element.attr('src'); //load the src if it was already on the dom
      scope.$on('loadedImg', function(e, img) {
        fullSize.src = img.src; //if we are using one of the helpers to load img data this will load the fs once they finish
        orig.src = img.src;
      });
      //listen for actions
      scope.$on('crop', function() {
        scope.cropping = true;
        croppedImage = new Image();
        croppedImage.src = element.attr('src');
        //re-load the full size image, instead of the cropped on so that the user can crop wider
        element.attr('src', fullSize.src);
        $(element).css('width', fullSize.width + 'px');
        $(element).css('height', fullSize.height + 'px');

        //Init Jcrop with old selection if one exists
        if (scope.crop) {
          var pt1 = rotatePoint(scope.crop.x, scope.crop.y, orig.width, orig.height, scope.rotation);
          var pt2 = rotatePoint(scope.crop.x2, scope.crop.y2, orig.width, orig.height, scope.rotation);
          selectedInit = [pt1.x, pt1.y, pt2.x, pt2.y];
          $(element).Jcrop({
            setSelect: selectedInit
          }, function() {
            jcrop_api = this;
          });
        } else {
          $(element).Jcrop({}, function() {
            jcrop_api = this;
          });
        }
      });

      scope.$on('reset', function() {
        scope.crop = false;
        scope.rotation = 0;
        reset();
        //brodcast update
        scope.$broadcast('update', orig.src);
      });

      scope.$on('save', function() {
        if (scope.cropping) {
          croppedImage = null;
          //main crop function.
          scope.cropping = false;
          //Save the new crop to the scope
          var crop = jcrop_api.tellSelect();
          var p1 = rotatePoint(crop.x, crop.y, fullSize.width, fullSize.height, -scope.rotation);
          var p2 = rotatePoint(crop.x2, crop.y2, fullSize.width, fullSize.height, -scope.rotation);
          scope.crop = {
            x: p1.x,
            y: p1.y,
            x2: p2.x,
            y2: p2.y
          }; //save the crop in origin cords
          console.log(crop);
          console.log(scope.crop);
          //turn off jcrop
          jcrop_api.destroy();
          //apply the crop (requires canvas support)
          applyCrop(crop);
          //TODO Convert Crop to Orig Cords.
        }
      });

      scope.$on('cancel', function() {
        if (scope.cropping) {
          scope.cropping = false;
          element.attr('src', croppedImage.src);
          $(element).css('width', croppedImage.width + 'px');
          $(element).css('height', croppedImage.height + 'px');
          croppedImage = null;
          jcrop_api.destroy();
        }
        //extend if other methods need cancel support
      });

      //rotate
      scope.$on('rotate', function() {
        scope.rotation = (scope.rotation + 90) % 360;
        doRotate();
      });

      //Functions
      function reset() {
        croppedImage = null;
        element.attr('src', orig.src);
        $(element).css('width', orig.width + 'px');
        $(element).css('height', orig.height + 'px');
        fullSize.src = orig.src; //reset the saved crop image as well
      }

      function doRotate() {

        var img = new Image();
        img.onload = function() {
          var myImage;
          var rotating = false;
          var canvas = document.createElement("canvas");
          var ctx = canvas.getContext("2d");
          var cw, ch;
          canvas.width = img.width;
          canvas.height = img.height;
          cw = canvas.width;
          ch = canvas.height;
          ctx.drawImage(img, 0, 0, img.width, img.height);
          if (!rotating) {
            rotating = true;
            // store current data to an image
            myImage = new Image();
            myImage.src = canvas.toDataURL();
            myImage.onload = function() {
              // reset the canvas with new dimensions
              canvas.width = ch;
              canvas.height = cw;
              cw = canvas.width;
              ch = canvas.height;
              ctx.save();
              // translate and rotate
              ctx.translate(parseInt(cw), parseInt(ch / cw));
              ctx.rotate(Math.PI / 2);
              // draw the previows image, now rotated
              ctx.drawImage(myImage, 0, 0);
              ctx.restore();
              // clear the temporary image
              myImage = null;
              rotating = false;
              element.attr('src', canvas.toDataURL());
              $(element).css('width', cw + 'px');
              $(element).css('height', ch + 'px');
              scope.$broadcast('update', canvas.toDataURL());
              canvas = null;
            };
          }
        };
        img.src = element.attr('src');
        rotateFullSize();
      }

      function rotateFullSize() {
        //silently rotate the full size image in the background
        var img2 = new Image();
        img2.onload = function() {
          var myImage2, rotating2 = false;
          var canvas2 = document.createElement("canvas");
          var ctx2 = canvas2.getContext("2d");
          var cw2, ch2;
          canvas2.width = img2.width;
          canvas2.height = img2.height;
          cw2 = canvas2.width;
          ch2 = canvas2.height;
          ctx2.drawImage(img2, 0, 0, img2.width, img2.height);
          if (!rotating2) {
            rotating2 = true;
            // store current data to an image
            myImage2 = new Image();
            myImage2.src = canvas2.toDataURL();
            myImage2.onload = function() {
              // reset the canvas with new dimensions
              canvas2.width = ch2;
              canvas2.height = cw2;
              cw2 = canvas2.width;
              ch2 = canvas2.height;
              ctx2.save();
              // translate and rotate
              ctx2.translate(parseInt(cw2), parseInt(ch2 / cw2));
              ctx2.rotate(Math.PI / 2);
              // draw the previows image, now rotated
              ctx2.drawImage(myImage2, 0, 0);
              ctx2.restore();
              // clear the temporary image
              myImage2 = null;
              rotating2 = false;
              var newImgSrc = canvas2.toDataURL();
              canvas2 = null;
              fullSize.src = newImgSrc;
            };
          }
        };
        img2.src = fullSize.src;
      }

      function applyCrop(crop) {
        var cropImage = new Image();
        cropImage.src = element.attr('src');
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        var selected = crop;
        var cw = canvas.width;
        var ch = canvas.height;
        // create 2 temporary canvases
        var canvas1 = document.createElement("canvas");
        var ctx1 = canvas1.getContext("2d");
        var canvas2 = document.createElement("canvas");
        var ctx2 = canvas2.getContext("2d");
        var rectBB = getRotatedRectBB(selected.x, selected.y, selected.w, selected.h, 0);
        // clip the boundingbox of the crop rect
        // to a temporary canvas
        canvas1.width = canvas2.width = rectBB.width;
        canvas1.height = canvas2.height = rectBB.height;
        ctx1.drawImage(cropImage,
          rectBB.cx - rectBB.width / 2,
          rectBB.cy - rectBB.height / 2,
          rectBB.width,
          rectBB.height,
          0, 0, rectBB.width, rectBB.height);
        ctx2.translate(parseInt(canvas1.width / 2), parseInt(canvas1.height / 2));
        ctx2.drawImage(canvas1, parseInt(-canvas1.width / 2), parseInt(-canvas1.height / 2));
        // draw the rect to the display canvas
        var offX = rectBB.width / 2 - selected.w / 2;
        var offY = rectBB.height / 2 - selected.h / 2;
        canvas.width = selected.w;
        canvas.height = selected.h;
        cw = canvas.width;
        ch = canvas.height;
        ctx.drawImage(canvas2, -offX, -offY);
        element.attr('src', canvas.toDataURL());
        $(element).css('width', selected.w + 'px');
        $(element).css('height', selected.h + 'px');
        scope.$broadcast('update', canvas.toDataURL());
        cropImage = canvas = ctx = cw = ch = selected = ctx1 = ctx2 = canvas1 = canvas2 = rectBB = offX = offY = null;
      } // end crop using canvas.
      //helper functions

      function rotatePoint(pointX, pointY, width, height, angle) {
        if (angle === 0) {
          return {
            x: pointX,
            y: pointY
          }
        } else if (Math.abs(angle) === 180) {
          return {
            x: width - pointX,
            y: height - pointY
          }
        } else {
          var rad = angle * Math.PI / 180.0; //convert to rad
          var x = pointX - width / 2; //convert to normal grid
          var y = pointY - height / 2;
          var offsetX = height / 2,
            offsetY = width / 2;
          return {
            x: parseInt(Math.cos(rad) * x - Math.sin(rad) * y + offsetX),
            y: parseInt(Math.sin(rad) * x + Math.cos(rad) * y + offsetY)
          };
        }
      }

      function getRotatedRectBB(x, y, width, height, rAngle) {
        var absCos = Math.abs(Math.cos(rAngle));
        var absSin = Math.abs(Math.sin(rAngle));
        var cx = x + width / 2 * Math.cos(rAngle) - height / 2 * Math.sin(rAngle);
        var cy = y + width / 2 * Math.sin(rAngle) + height / 2 * Math.cos(rAngle);
        var w = width * absCos + height * absSin;
        var h = width * absSin + height * absCos;
        return ({
          cx: cx,
          cy: cy,
          width: w,
          height: h
        });
      }

    }
  }
});<commit_msg>updated comments<commit_after>/*
  Luke Mason 2014
  Angular directives which use Canvas to provide an editable context for images.
  Jcrop, used for cropping http://deepliquid.com/content/Jcrop.html
*/
/*Convert a file in the scope into an img src data attribute*/
angular.module('imgManipulation.directives', [])
  .directive('imgData', ['$parse',
    function($parse) {
      return {
        restrict: 'A',
        link: function(scope, element, attributes) {
          var imgData = scope.$eval(attributes.imgData);
          var width, height;
          var reader = new FileReader();
          reader.onload = function(e) {
            scope.$apply(function() {
              var img = new Image();
              img.onload = function() {
                element.attr('src', img.src);
                $(element).css('width', img.width + 'px');
                $(element).css('height', img.height + 'px');
              };
              img.src = reader.result;
              scope.$broadcast('loadedImg', img);
            });
          }
          reader.readAsDataURL(imgData);
        }
      };
    }
  ])
/* read a file from a url and convert it to a data src (this will only work for CORS images */
.directive('imgDataFromUri', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attributes) {
      // Create an empty canvas element
      var canvas = document.createElement("canvas");
      var img = new Image();
      img.onload = function() {
        console.log('loaded Image');
        canvas.width = img.width;
        canvas.height = img.height;
        // Copy the image contents to the canvas
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0);
        var dataURL = canvas.toDataURL("image/png");
        element.attr('src', dataURL);
        $(element).css('width', img.width + 'px');
        $(element).css('height', img.height + 'px');
      }
      img.crossOrigin = '';
      img.src = element.attr('src');
    }
  };
})
  .directive('imgThumb', ['$parse',
    function($parse) {
      return {
        restrict: 'A',
        link: function(scope, element, attributes) {
          scope.$on('loadedImg', function(e, img) {
            element.attr('src', img.src);
          });
          scope.$on('update', function(e, imgSRC) {
            element.attr('src', imgSRC);
          });
        }
      };
    }
  ])
/* add listeners for 'crop', 'rotate' and 'rest' brodcasts */
.directive('imgEditable', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attributes) {
      var jcrop_api;
      var croppedImage; //this will be used to support cancel of crop.
      var fullSize = new Image();
      var orig = new Image();
      scope.crop = false;
      scope.rotation = 0;
      fullSize.src = element.attr('src'); //load the src if it was already on the dom
      scope.$on('loadedImg', function(e, img) {
        fullSize.src = img.src; //if we are using one of the helpers to load img data this will load the fs once they finish
        orig.src = img.src;
      });
      //listen for actions
      scope.$on('crop', function() {
        scope.cropping = true;
        croppedImage = new Image();
        croppedImage.src = element.attr('src');
        //re-load the full size image, instead of the cropped on so that the user can crop wider
        element.attr('src', fullSize.src);
        $(element).css('width', fullSize.width + 'px');
        $(element).css('height', fullSize.height + 'px');

        //Init Jcrop with old selection if one exists
        if (scope.crop) {
          var pt1 = rotatePoint(scope.crop.x, scope.crop.y, orig.width, orig.height, scope.rotation);
          var pt2 = rotatePoint(scope.crop.x2, scope.crop.y2, orig.width, orig.height, scope.rotation);
          selectedInit = [pt1.x, pt1.y, pt2.x, pt2.y];
          $(element).Jcrop({
            setSelect: selectedInit
          }, function() {
            jcrop_api = this;
          });
        } else {
          $(element).Jcrop({}, function() {
            jcrop_api = this;
          });
        }
      });

      scope.$on('reset', function() {
        scope.crop = false;
        scope.rotation = 0;
        reset();
        //brodcast update
        scope.$broadcast('update', orig.src);
      });

      scope.$on('save', function() {
        if (scope.cropping) {
          croppedImage = null;
          //main crop function.
          scope.cropping = false;
          //Save the new crop to the scope
          var crop = jcrop_api.tellSelect();
          var p1 = rotatePoint(crop.x, crop.y, fullSize.width, fullSize.height, -scope.rotation);
          var p2 = rotatePoint(crop.x2, crop.y2, fullSize.width, fullSize.height, -scope.rotation);
          scope.crop = {
            x: p1.x,
            y: p1.y,
            x2: p2.x,
            y2: p2.y
          };
          //turn off jcrop
          jcrop_api.destroy();
          //apply the crop (requires canvas support)
          applyCrop(crop);
        }
      });

      scope.$on('cancel', function() {
        if (scope.cropping) {
          scope.cropping = false;
          element.attr('src', croppedImage.src);
          $(element).css('width', croppedImage.width + 'px');
          $(element).css('height', croppedImage.height + 'px');
          croppedImage = null;
          jcrop_api.destroy();
        }
        //extend if other methods need cancel support
      });

      //rotate
      scope.$on('rotate', function() {
        scope.rotation = (scope.rotation + 90) % 360;
        doRotate();
      });

      //Functions
      function reset() {
        croppedImage = null;
        element.attr('src', orig.src);
        $(element).css('width', orig.width + 'px');
        $(element).css('height', orig.height + 'px');
        fullSize.src = orig.src; //reset the saved crop image as well
      }

      function doRotate() {
        var img = new Image();
        img.onload = function() {
          var myImage;
          var rotating = false;
          var canvas = document.createElement("canvas");
          var ctx = canvas.getContext("2d");
          var cw, ch;
          canvas.width = img.width;
          canvas.height = img.height;
          cw = canvas.width;
          ch = canvas.height;
          ctx.drawImage(img, 0, 0, img.width, img.height);
          if (!rotating) {
            rotating = true;
            // store current data to an image
            myImage = new Image();
            myImage.src = canvas.toDataURL();
            myImage.onload = function() {
              // reset the canvas with new dimensions
              canvas.width = ch;
              canvas.height = cw;
              cw = canvas.width;
              ch = canvas.height;
              ctx.save();
              // translate and rotate
              ctx.translate(parseInt(cw), parseInt(ch / cw));
              ctx.rotate(Math.PI / 2);
              // draw the previows image, now rotated
              ctx.drawImage(myImage, 0, 0);
              ctx.restore();
              // clear the temporary image
              myImage = null;
              rotating = false;
              element.attr('src', canvas.toDataURL());
              $(element).css('width', cw + 'px');
              $(element).css('height', ch + 'px');
              scope.$broadcast('update', canvas.toDataURL());
              canvas = null;
            };
          }
        };
        img.src = element.attr('src');
        rotateFullSize();
      }

      function rotateFullSize() {
        //silently rotate the full size image in the background
        var img2 = new Image();
        img2.onload = function() {
          var myImage2, rotating2 = false;
          var canvas2 = document.createElement("canvas");
          var ctx2 = canvas2.getContext("2d");
          var cw2, ch2;
          canvas2.width = img2.width;
          canvas2.height = img2.height;
          cw2 = canvas2.width;
          ch2 = canvas2.height;
          ctx2.drawImage(img2, 0, 0, img2.width, img2.height);
          if (!rotating2) {
            rotating2 = true;
            // store current data to an image
            myImage2 = new Image();
            myImage2.src = canvas2.toDataURL();
            myImage2.onload = function() {
              // reset the canvas with new dimensions
              canvas2.width = ch2;
              canvas2.height = cw2;
              cw2 = canvas2.width;
              ch2 = canvas2.height;
              ctx2.save();
              // translate and rotate
              ctx2.translate(parseInt(cw2), parseInt(ch2 / cw2));
              ctx2.rotate(Math.PI / 2);
              // draw the previows image, now rotated
              ctx2.drawImage(myImage2, 0, 0);
              ctx2.restore();
              // clear the temporary image
              myImage2 = null;
              rotating2 = false;
              var newImgSrc = canvas2.toDataURL();
              canvas2 = null;
              fullSize.src = newImgSrc;
            };
          }
        };
        img2.src = fullSize.src;
      }

      function applyCrop(crop) {
        var cropImage = new Image();
        cropImage.src = element.attr('src');
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        var selected = crop;
        var cw = canvas.width;
        var ch = canvas.height;
        // create 2 temporary canvases
        var canvas1 = document.createElement("canvas");
        var ctx1 = canvas1.getContext("2d");
        var canvas2 = document.createElement("canvas");
        var ctx2 = canvas2.getContext("2d");
        var rectBB = getRotatedRectBB(selected.x, selected.y, selected.w, selected.h, 0);
        // clip the boundingbox of the crop rect
        // to a temporary canvas
        canvas1.width = canvas2.width = rectBB.width;
        canvas1.height = canvas2.height = rectBB.height;
        ctx1.drawImage(cropImage,
          rectBB.cx - rectBB.width / 2,
          rectBB.cy - rectBB.height / 2,
          rectBB.width,
          rectBB.height,
          0, 0, rectBB.width, rectBB.height);
        ctx2.translate(parseInt(canvas1.width / 2), parseInt(canvas1.height / 2));
        ctx2.drawImage(canvas1, parseInt(-canvas1.width / 2), parseInt(-canvas1.height / 2));
        // draw the rect to the display canvas
        var offX = rectBB.width / 2 - selected.w / 2;
        var offY = rectBB.height / 2 - selected.h / 2;
        canvas.width = selected.w;
        canvas.height = selected.h;
        cw = canvas.width;
        ch = canvas.height;
        ctx.drawImage(canvas2, -offX, -offY);
        element.attr('src', canvas.toDataURL());
        $(element).css('width', selected.w + 'px');
        $(element).css('height', selected.h + 'px');
        scope.$broadcast('update', canvas.toDataURL());
        cropImage = canvas = ctx = cw = ch = selected = ctx1 = ctx2 = canvas1 = canvas2 = rectBB = offX = offY = null;
      }

      //helper functions
      function rotatePoint(pointX, pointY, width, height, angle) {
        if (angle === 0) {
          return {
            x: pointX,
            y: pointY
          }
        } else if (Math.abs(angle) === 180) {
          return {
            x: width - pointX,
            y: height - pointY
          }
        } else {
          var rad = angle * Math.PI / 180.0; //convert to rad
          var x = pointX - width / 2; //convert to normal grid
          var y = pointY - height / 2;
          var offsetX = height / 2,
            offsetY = width / 2;
          return {
            x: parseInt(Math.cos(rad) * x - Math.sin(rad) * y + offsetX),
            y: parseInt(Math.sin(rad) * x + Math.cos(rad) * y + offsetY)
          };
        }
      }

      function getRotatedRectBB(x, y, width, height, rAngle) {
        var absCos = Math.abs(Math.cos(rAngle));
        var absSin = Math.abs(Math.sin(rAngle));
        var cx = x + width / 2 * Math.cos(rAngle) - height / 2 * Math.sin(rAngle);
        var cy = y + width / 2 * Math.sin(rAngle) + height / 2 * Math.cos(rAngle);
        var w = width * absCos + height * absSin;
        var h = width * absSin + height * absCos;
        return ({
          cx: cx,
          cy: cy,
          width: w,
          height: h
        });
      }

    }
  }
});<|endoftext|>


<commit_before>// @flow

/**
 * Philip Crotwell
 * University of South Carolina, 2016
 * http://www.seis.sc.edu
 */

 /*global DataView*/

import * as miniseed from './miniseed';
import * as RSVP from 'rsvp';
import moment from 'moment';

import {dataViewToString} from './util';

export const SEEDLINK_PROTOCOL = "SeedLink3.1";

RSVP.on('error', function(reason) {
  console.assert(false, reason);
});

export type SequencedDataRecord = {
  rawsequence: string,
  sequence: number,
  miniseed: miniseed.DataRecord
};

export class SeedlinkConnection {
  url: string;
  requestConfig: Array<string>;
  receiveMiniseedFn: (packet: SequencedDataRecord) => void;
  errorFn: (error: Error) => void;
  closeFn: null | (close: CloseEvent) => void;
  webSocket: WebSocket;
  command: string;
  /** creates a seedlink websocket connection to the given url.
    * requestConfig is an array of seedlink commands
    * like:
    *   [ 'STATION JSC CO',
    *     'SELECT 00BHZ.D' ]
    * and receiveMiniseedFn is the callback function that
    * will be invoked for each seedlink packet received
    * which contains 'sequence', a sequence number
    * and 'miniseed', a single miniseed record.
    * The connection is not made until the connect() method is called.
    */
  constructor(url: string, requestConfig: Array<string>, receiveMiniseedFn: (packet: SequencedDataRecord) => void, errorFn: (error: Error) => void) {
    this.url = url;
    this.requestConfig = requestConfig;
    this.receiveMiniseedFn = receiveMiniseedFn;
    this.errorFn = errorFn;
    this.closeFn = null;
    this.command = 'DATA';
  }
  setTimeCommand(startTime: moment) {
    this.command = "TIME "+moment(startTime).format("YYYY,MM,DD,HH,mm,ss");
  }
  setOnError(errorFn: (error: Error) => void) {
    this.errorFn = errorFn;
  }
  setOnClose(closeFn: (close: CloseEvent) => void) {
    this.closeFn = closeFn;
  }

  connect() {
    if (this.webSocket) {this.webSocket.close();}
    try {
      this.webSocket = new WebSocket(this.url, SEEDLINK_PROTOCOL);
      this.webSocket.binaryType = 'arraybuffer';
      const that = this;
      this.webSocket.onopen = function() {
        that.sendHello(that.webSocket)
        .then(function() {
          return that.sendCmdArray(that.webSocket, that.requestConfig);
        })
        .then(function() {
          return that.sendCmdArray(that.webSocket, [ that.command ]);
        })
        .then(function(val) {
          that.webSocket.onmessage = function(event) {
            that.handle(event);
          };
          that.webSocket.send('END\r');
          return val;
        }, function(err) {
          if (that.errorFn) {
            that.errorFn(err);
          } else {
            console.assert(false, err);
          }
          that.close();
        });
      };
      this.webSocket.onerror = function(err) {
        if (that.errorFn) {
          that.errorFn(err);
        } else {
          console.assert(false, err);
        }
      };
      this.webSocket.onclose = function(closeEvent) {
        if (that.closeFn) {
          that.closeFn(closeEvent);
        } else {
          console.log(`Received webSocket close: ${closeEvent.code} ${closeEvent.reason}`);
        }
        if (that.webSocket) {
          that.webSocket = null;
        }
      };
    } catch(err) {
      if (this.errorFn) {
        this.errorFn(err);
      } else {
        console.assert(false, err);
      }
    }
  }

  close(): void {
    if (this.webSocket) {
      this.webSocket.close();
    }
  }

  handle(event: MessageEvent ): void {
    //for flow
    const data = ((event.data: any): ArrayBuffer);
    if (data.byteLength < 64) {
      //assume text
    } else {
      this.handleMiniseed(event);
    }
  }

  handleMiniseed(event: MessageEvent): void {
    //for flow
    const data = ((event.data: any): ArrayBuffer);
    try {
       // let arrBuf = new ArrayBuffer(event.data);
        if (data.byteLength < 64) {
          this.errorFn(new Error("message too small to be miniseed: "+data.byteLength +" "+dataViewToString(new DataView(data))));
          return;
        }
        let slHeader = new DataView(data, 0, 8);
        // check for 'SL' at start
        if (slHeader.getInt8(0) === 83 && slHeader.getInt8(1) === 76) {
          let seqStr = '';
          for (let i=0; i<6; i++) {
            seqStr = seqStr + String.fromCharCode(slHeader.getInt8(2+i));
          }
          let dataView = new DataView(data, 8, data.byteLength-8);
          let out = {
            rawsequence: seqStr,
            sequence: parseInt(seqStr, 16),
            miniseed: miniseed.parseSingleDataRecord(dataView)
          };
          this.receiveMiniseedFn(out);
        } else {
          this.errorFn(new Error("Not a seedlink packet, no starting SL: "+slHeader.getInt8(0)+' '+slHeader.getInt8(1)));
        }
     } catch(e) {
        console.assert(false, e);
        this.errorFn("Error, closing seedlink. "+e);
        this.close();
     }
  }

  sendHello(webSocket: WebSocket): Promise<string> {
  let promise = new RSVP.Promise(function(resolve, reject) {
    webSocket.onmessage = function(event) {
      //for flow
      const data = ((event.data: any): ArrayBuffer);
      let replyMsg = dataViewToString(new DataView(data));
      let lines = replyMsg.trim().split('\r');
      if (lines.length === 2) {
        resolve(lines);
      } else {
        reject("not 2 lines: "+replyMsg);
      }
    };
    webSocket.send("HELLO\r");
  });
  return promise;
}

  sendCmdArray(webSocket: WebSocket, cmd: Array<string>): Promise<string> {
    let that = this;
    return cmd.reduce(function(accum: Promise<string>, next: string) {
      return accum.then(function() {
        return that.createCmdPromise(webSocket, next);
      });
    }, RSVP.resolve());
  }

  createCmdPromise(webSocket: WebSocket, mycmd: string): Promise<string> {
    let promise = new RSVP.Promise(function(resolve, reject) {
      webSocket.onmessage = function(event) {
        //for flow
        const data = ((event.data: any): ArrayBuffer);
        let replyMsg = dataViewToString(new DataView(data)).trim();
        if (replyMsg === 'OK') {
          resolve(replyMsg);
        } else {
          reject("msg not OK: "+replyMsg);
        }
      };
      webSocket.send(mycmd+'\r\n');
    });
    return promise;
  }
}
<commit_msg>flow errors<commit_after>// @flow

/**
 * Philip Crotwell
 * University of South Carolina, 2016
 * http://www.seis.sc.edu
 */

 /*global DataView*/

import * as miniseed from './miniseed';
import * as RSVP from 'rsvp';
import moment from 'moment';

import {dataViewToString} from './util';

export const SEEDLINK_PROTOCOL = "SeedLink3.1";

RSVP.on('error', function(reason) {
  console.assert(false, reason);
});

export type SequencedDataRecord = {
  rawsequence: string,
  sequence: number,
  miniseed: miniseed.DataRecord
};

export class SeedlinkConnection {
  url: string;
  requestConfig: Array<string>;
  receiveMiniseedFn: (packet: SequencedDataRecord) => void;
  errorFn: (error: Error) => void;
  closeFn: null | (close: CloseEvent) => void;
  webSocket: null | WebSocket;
  command: string;
  /** creates a seedlink websocket connection to the given url.
    * requestConfig is an array of seedlink commands
    * like:
    *   [ 'STATION JSC CO',
    *     'SELECT 00BHZ.D' ]
    * and receiveMiniseedFn is the callback function that
    * will be invoked for each seedlink packet received
    * which contains 'sequence', a sequence number
    * and 'miniseed', a single miniseed record.
    * The connection is not made until the connect() method is called.
    */
  constructor(url: string, requestConfig: Array<string>, receiveMiniseedFn: (packet: SequencedDataRecord) => void, errorFn: (error: Error) => void) {
    this.url = url;
    this.requestConfig = requestConfig;
    this.receiveMiniseedFn = receiveMiniseedFn;
    this.errorFn = errorFn;
    this.closeFn = null;
    this.command = 'DATA';
  }
  setTimeCommand(startTime: moment) {
    this.command = "TIME "+moment(startTime).format("YYYY,MM,DD,HH,mm,ss");
  }
  setOnError(errorFn: (error: Error) => void) {
    this.errorFn = errorFn;
  }
  setOnClose(closeFn: (close: CloseEvent) => void) {
    this.closeFn = closeFn;
  }

  connect() {
    if (this.webSocket) {this.webSocket.close();}
    try {
      const webSocket = new WebSocket(this.url, SEEDLINK_PROTOCOL);
      this.webSocket = webSocket
      webSocket.binaryType = 'arraybuffer';
      const that = this;
      webSocket.onopen = function() {
        that.sendHello(webSocket)
        .then(function() {
          return that.sendCmdArray(webSocket, that.requestConfig);
        })
        .then(function() {
          return that.sendCmdArray(webSocket, [ that.command ]);
        })
        .then(function(val) {
          webSocket.onmessage = function(event) {
            that.handle(event);
          };
          webSocket.send('END\r');
          return val;
        }, function(err) {
          if (that.errorFn) {
            that.errorFn(err);
          } else {
            console.assert(false, err);
          }
          that.close();
        });
      };
      webSocket.onerror = function(err) {
        if (that.errorFn) {
          that.errorFn(err);
        } else {
          console.assert(false, err);
        }
      };
      webSocket.onclose = function(closeEvent) {
        if (that.closeFn) {
          that.closeFn(closeEvent);
        } else {
          console.log(`Received webSocket close: ${closeEvent.code} ${closeEvent.reason}`);
        }
        if (that.webSocket) {
          that.webSocket = null;
        }
      };
    } catch(err) {
      if (this.errorFn) {
        this.errorFn(err);
      } else {
        console.assert(false, err);
      }
    }
  }

  close(): void {
    if (this.webSocket) {
      this.webSocket.close();
    }
  }

  handle(event: MessageEvent ): void {
    //for flow
    const data = ((event.data: any): ArrayBuffer);
    if (data.byteLength < 64) {
      //assume text
    } else {
      this.handleMiniseed(event);
    }
  }

  handleMiniseed(event: MessageEvent): void {
    //for flow
    const data = ((event.data: any): ArrayBuffer);
    try {
       // let arrBuf = new ArrayBuffer(event.data);
        if (data.byteLength < 64) {
          this.errorFn(new Error("message too small to be miniseed: "+data.byteLength +" "+dataViewToString(new DataView(data))));
          return;
        }
        let slHeader = new DataView(data, 0, 8);
        // check for 'SL' at start
        if (slHeader.getInt8(0) === 83 && slHeader.getInt8(1) === 76) {
          let seqStr = '';
          for (let i=0; i<6; i++) {
            seqStr = seqStr + String.fromCharCode(slHeader.getInt8(2+i));
          }
          let dataView = new DataView(data, 8, data.byteLength-8);
          let out = {
            rawsequence: seqStr,
            sequence: parseInt(seqStr, 16),
            miniseed: miniseed.parseSingleDataRecord(dataView)
          };
          this.receiveMiniseedFn(out);
        } else {
          this.errorFn(new Error("Not a seedlink packet, no starting SL: "+slHeader.getInt8(0)+' '+slHeader.getInt8(1)));
        }
     } catch(e) {
        console.assert(false, e);
        this.errorFn("Error, closing seedlink. "+e);
        this.close();
     }
  }

  sendHello(webSocket: WebSocket): Promise<string> {
  let promise = new RSVP.Promise(function(resolve, reject) {
    webSocket.onmessage = function(event) {
      //for flow
      const data = ((event.data: any): ArrayBuffer);
      let replyMsg = dataViewToString(new DataView(data));
      let lines = replyMsg.trim().split('\r');
      if (lines.length === 2) {
        resolve(lines);
      } else {
        reject("not 2 lines: "+replyMsg);
      }
    };
    webSocket.send("HELLO\r");
  });
  return promise;
}

  sendCmdArray(webSocket: WebSocket, cmd: Array<string>): Promise<string> {
    let that = this;
    return cmd.reduce(function(accum: Promise<string>, next: string) {
      return accum.then(function() {
        return that.createCmdPromise(webSocket, next);
      });
    }, RSVP.resolve());
  }

  createCmdPromise(webSocket: WebSocket, mycmd: string): Promise<string> {
    let promise = new RSVP.Promise(function(resolve, reject) {
      webSocket.onmessage = function(event) {
        //for flow
        const data = ((event.data: any): ArrayBuffer);
        let replyMsg = dataViewToString(new DataView(data)).trim();
        if (replyMsg === 'OK') {
          resolve(replyMsg);
        } else {
          reject("msg not OK: "+replyMsg);
        }
      };
      webSocket.send(mycmd+'\r\n');
    });
    return promise;
  }
}
<|endoftext|>


<commit_before>
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();
const s3 = new AWS.S3();

module.exports.redirect = (event, context, callback) => {
  const pathParams = event.pathParameters;
  const noRedirect = {
    statusCode: 200,
    headers: noCacheHeaders(),
    body: 'nothing to see here!'
  };

  if (!pathParams || !pathParams.id) {
    return callback(null, redirectResponse('https://wpb.is/PatrickBrandt'));
  }

  const id = pathParams.id.toLowerCase();
  // do something special for yours truly - serve home site
  if (id === 'patrickbrandt') {
    const params = {
      Bucket: process.env.wpbis_bucket,
      Key: 'index.html'
    };
    s3.getObject(params).promise()
      .then(data => {
        const response = {
          statusCode: 200,
          headers: {
            'Content-Type': 'text/html',
          },
          body: data.Body.toString(),
        };
        callback(null, response);
      })
      .catch(err => {
        console.log(err);
        callback(null, errorResponse());
      });
  } else {
    getUrl(id)
      .then(url => {
        if(!!url) {
          return callback(null, redirectResponse(url));
        }
        callback(null, noRedirect);
      })
      .catch(err => {
        console.log(err);
        callback(null, errorResponse());
      });
  }
};

function getUrl(id) {
  return new Promise((resolve, reject) => {
    const params = {
      TableName: process.env.urls_table,
      Key: { Id: id },
    };
    docClient.get(params, (err, data) => {
      if (err) return reject(err);
      let url = data.Item ? data.Item.Url : undefined;
      resolve(url);
    });
  });
}

function errorResponse() {
  return  {
    statusCode: 500,
    body: 'something bad happened',
  }
}

function redirectResponse(url) {
  return {
    statusCode: 301,
    headers: { Location: url, ...noCacheHeaders()},
  };
}

function noCacheHeaders() {
  return {
    'Cache-Control': 'no-cache, no-store, must-revalidate',
    Pragma: 'no-cache',
    Expires: 0,
  }
}
<commit_msg>const declaration tweak<commit_after>
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();
const s3 = new AWS.S3();

module.exports.redirect = (event, context, callback) => {
  const pathParams = event.pathParameters;
  const noRedirect = {
    statusCode: 200,
    headers: noCacheHeaders(),
    body: 'nothing to see here!'
  };

  if (!pathParams || !pathParams.id) {
    return callback(null, redirectResponse('https://wpb.is/PatrickBrandt'));
  }

  const id = pathParams.id.toLowerCase();
  // do something special for yours truly - serve home site
  if (id === 'patrickbrandt') {
    const params = {
      Bucket: process.env.wpbis_bucket,
      Key: 'index.html'
    };
    s3.getObject(params).promise()
      .then(data => {
        const response = {
          statusCode: 200,
          headers: {
            'Content-Type': 'text/html',
          },
          body: data.Body.toString(),
        };
        callback(null, response);
      })
      .catch(err => {
        console.log(err);
        callback(null, errorResponse());
      });
  } else {
    getUrl(id)
      .then(url => {
        if(!!url) {
          return callback(null, redirectResponse(url));
        }
        callback(null, noRedirect);
      })
      .catch(err => {
        console.log(err);
        callback(null, errorResponse());
      });
  }
};

function getUrl(id) {
  return new Promise((resolve, reject) => {
    const params = {
      TableName: process.env.urls_table,
      Key: { Id: id },
    };
    docClient.get(params, (err, data) => {
      if (err) return reject(err);
      const url = data.Item ? data.Item.Url : undefined;
      resolve(url);
    });
  });
}

function errorResponse() {
  return  {
    statusCode: 500,
    body: 'something bad happened',
  }
}

function redirectResponse(url) {
  return {
    statusCode: 301,
    headers: { Location: url, ...noCacheHeaders()},
  };
}

function noCacheHeaders() {
  return {
    'Cache-Control': 'no-cache, no-store, must-revalidate',
    Pragma: 'no-cache',
    Expires: 0,
  }
}
<|endoftext|>


<commit_before>export { default as hello } from './src/hello';

export { default as health } from './src/health';
<commit_msg>updated handler<commit_after>export { default as hello } from './src/hello';

export { default as health } from './src/health';

export { default as kms } from './src/kms';
<|endoftext|>


<commit_before>
'use strict';
var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

module.exports.saveEmailStatus = (event, context, callback) => {

	var addressList = [];

	console.log("Message", event.Records[0].Sns.Message);
	console.log("Mail", event.Records[0].Sns.Message.mail);

	if (event.Records[0].Sns.Message.mail.destination !== null) {
		event.Records[0].Sns.Message.mail.destination.forEach((addr) => {
			addressList.push(addr);
		})

		var status;
		if (event.Records[0].Sns.Message.mail.notificationType === "Delivery") {
			status = "Delivered";
		} else if (event.Records[0].Sns.Message.mail.bounce) {
			if (event.Records[0].Sns.Message.mail.bounce.bounceSubtype === "General") {
				status = "No domain";
			} else {
				status = "Bad email address";
			}
		} else {
			status = "Complaint";
		}

		var messageId = event.Records[0].Sns.Message.mail.messageId;

		var params = {
			"Key": {
				"MessageId": {
					S: messageId
				}
			},
			"ReturnValues":"NONE",
			"ExpressionAttributeNames": {
				"#AL": "Addresses",
				"#S":"Status"
			},
			"ExpressionAttributeValues": {
				":al": {
					"SS":addressList
				},
				":s": {
					"S":status
				}
			},
			"UpdateExpression": "SET #AL = :al, #S = :s",
  			"TableName": "SentEmailStatus"
		};

		postToDynamoDB(params).then((res) => {
			console.log("resForPost", res);
		})
	} else {
		console.log("Destination was null ");
	}
};

function postToDynamoDB(params) {
	return new Promise((resolve, reject) => {
		dynamodb.updateItem(params, (err, data) => {
			if (err) {
				console.log(err);
				console.log("These params were rejected: ", params);
				reject(err);
			} else {
				resolve(data);
			}
		})
	})
}
<commit_msg>try this<commit_after>'use strict';

var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

module.exports.saveEmailStatus = (event, context, callback) => {

	var addressList = [];

	console.log("message0", event.Records[0].Sns.Message);
  var message = event.Records[0].Sns.Message;
  console.log("message1: ", message);
  var mail = message.mail;
  console.log("mail", mail);
  var dest = mail.destination;
  console.log("dest", dest);

	if (dest !== null) {
		dest.forEach((addr) => {
			addressList.push(addr);
		});

		var status;
		if (event.Records[0].Sns.Message.mail.notificationType === "Delivery") {
			status = "Delivered";
		} else if (event.Records[0].Sns.Message.mail.bounce) {
			if (event.Records[0].Sns.Message.mail.bounce.bounceSubtype === "General") {
				status = "No domain";
			} else {
				status = "Bad email address";
			}
		} else {
			status = "Complaint";
		}

		var messageId = event.Records[0].Sns.Message.mail.messageId;

		var params = {
			"Key": {
				"MessageId": {
					S: messageId
				}
			},
			"ReturnValues":"NONE",
			"ExpressionAttributeNames": {
				"#AL": "Addresses",
				"#S":"Status"
			},
			"ExpressionAttributeValues": {
				":al": {
					"SS":addressList
				},
				":s": {
					"S":status
				}
			},
			"UpdateExpression": "SET #AL = :al, #S = :s",
  			"TableName": "SentEmailStatus"
		};

		postToDynamoDB(params).then((res) => {
			console.log("resForPost", res);
		});
	} else {
		console.log("Destination was null ");
	}
};

function postToDynamoDB(params) {
	return new Promise((resolve, reject) => {
		dynamodb.updateItem(params, (err, data) => {
			if (err) {
				console.log(err);
				console.log("These params were rejected: ", params);
				reject(err);
			} else {
				resolve(data);
			}
		})
	});
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the “License”); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import {camelizeKeys} from 'humps'
import {existsSync, readFileSync} from 'fs'
import {getPackageDir} from './paths'
import {join} from 'path'

const ENV_VAR = /^BORELA_JS_TOOLBOX_(.+)$/

export function getEnvFlags() {
  let result = {}
  for (let prop in process.env) {
    const MATCH = prop.match(ENV_VAR)
    if (MATCH)
      result[MATCH[1].toLowerCase()] = process.env[prop]
  }
  return camelizeKeys(result)
}

const PACKAGE_DIR = getPackageDir()
const PACKAGE_JSON_PATH = join(PACKAGE_DIR, 'package.json')
const BORELARC_PATH = join(PACKAGE_DIR, 'borelarc')
const BORELA_JSON_PATH = join(PACKAGE_DIR, 'borela.json')

export const PACKAGE_JSON = existsSync(PACKAGE_JSON_PATH)
  ? camelizeKeys(require(PACKAGE_JSON_PATH).borela)
  : {}

export const BORELARC = existsSync(BORELARC_PATH)
  ? camelizeKeys(JSON.parse(readFileSync(BORELARC_PATH)))
  : {}

export const BORELA_JSON = existsSync(BORELA_JSON_PATH)
  ? camelizeKeys(require(BORELA_JSON_PATH))
  : {}

export const CLI_ENV = process.env.TEMP_BORELA_JS_TOOLBOX
  ? camelizeKeys(JSON.parse(process.env.TEMP_BORELA_JS_TOOLBOX))
  : {}

export function getSettings() {
  let result = {
    ...getEnvFlags(),
    ...PACKAGE_JSON,
    ...BORELARC,
    ...BORELA_JSON,
    ...CLI_ENV,
  }

  // Default platforms inferred by the project’s type.
  if (!result.platforms) {
    switch (result.projectType) {
      case 'app':
      case 'cli':
        result.platforms = ['node']
        break
      case 'library':
        result.platforms = ['browsers', 'node']
        break
    }
  }

  // Default supported browsers inferred by the platform.
  if (result.platforms.includes('browsers') && !result.browsers)
    result.browsers = ['chrome >= 49', '>= 0.5%', 'last 2 versions', 'not dead']

  // Default supported NodeJS inferred by the platform.
  if (result.platforms.includes('node') && !result.node)
    result.node = '8.9'

  return result
}
<commit_msg>Fix typo in default platforms<commit_after>// Licensed under the Apache License, Version 2.0 (the “License”); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import {camelizeKeys} from 'humps'
import {existsSync, readFileSync} from 'fs'
import {getPackageDir} from './paths'
import {join} from 'path'

const ENV_VAR = /^BORELA_JS_TOOLBOX_(.+)$/

export function getEnvFlags() {
  let result = {}
  for (let prop in process.env) {
    const MATCH = prop.match(ENV_VAR)
    if (MATCH)
      result[MATCH[1].toLowerCase()] = process.env[prop]
  }
  return camelizeKeys(result)
}

const PACKAGE_DIR = getPackageDir()
const PACKAGE_JSON_PATH = join(PACKAGE_DIR, 'package.json')
const BORELARC_PATH = join(PACKAGE_DIR, 'borelarc')
const BORELA_JSON_PATH = join(PACKAGE_DIR, 'borela.json')

export const PACKAGE_JSON = existsSync(PACKAGE_JSON_PATH)
  ? camelizeKeys(require(PACKAGE_JSON_PATH).borela)
  : {}

export const BORELARC = existsSync(BORELARC_PATH)
  ? camelizeKeys(JSON.parse(readFileSync(BORELARC_PATH)))
  : {}

export const BORELA_JSON = existsSync(BORELA_JSON_PATH)
  ? camelizeKeys(require(BORELA_JSON_PATH))
  : {}

export const CLI_ENV = process.env.TEMP_BORELA_JS_TOOLBOX
  ? camelizeKeys(JSON.parse(process.env.TEMP_BORELA_JS_TOOLBOX))
  : {}

export function getSettings() {
  let result = {
    ...getEnvFlags(),
    ...PACKAGE_JSON,
    ...BORELARC,
    ...BORELA_JSON,
    ...CLI_ENV,
  }

  // Default platforms inferred by the project’s type.
  if (!result.platforms) {
    switch (result.projectType) {
      case 'app':
      case 'cli':
        result.platforms = ['node']
        break
      case 'library':
        result.platforms = ['browser', 'node']
        break
    }
  }

  // Default supported browsers inferred by the platform.
  if (result.platforms.includes('browsers') && !result.browsers)
    result.browsers = ['chrome >= 49', '>= 0.5%', 'last 2 versions', 'not dead']

  // Default supported NodeJS inferred by the platform.
  if (result.platforms.includes('node') && !result.node)
    result.node = '8.9'

  return result
}
<|endoftext|>


<commit_before>/**
 * Default settings.
 *
 * @type {Object}
 */
const defaults = {
  activateCallback:     null,
  activateDelay:        100,
  activateOnHover:      false,
  allowDuplicates:      true,
  allowMultiple:        false,
  anchorParentSelector: 'sup',
  anchorPattern:        /(fn|footnote|note)[:\-_\d]/gi,
  dismissDelay:         300,
  dismissOnUnhover:     false,
  footnoteParentClass:  'footnote',
  footnoteSelector:     'li',
  hoverDelay:           250,
  numberResetSelector:  null,
  scope:                null,
  contentTemplate:      '<aside class="littlefoot-footnote is-positioned-bottom" data-footnote-id="<%= id %>" data-footnote-number="<%= number %>" alt="Footnote <%= number %>">

<%= content %>

',
  buttonTemplate:       '
<button class="littlefoot-footnote__button littlefoot-footnote__button__ellipsis" id="<%= reference %>" data-footnote-id="<%= id %>" data-footnote-number="<%= number %>" alt="See Footnote <%= number %>" rel="footnote" data-littlefoot-footnote="<%= content %>"><svg viewbox="0 0 31 6" preserveAspectRatio="xMidYMid"><circle r="3" cx="3" cy="3" fill="white"></circle><circle r="3" cx="15" cy="3" fill="white"></circle><circle r="3" cx="27" cy="3" fill="white"></circle></svg></button>
',
}

/**
 * Settings factory.
 * @param  {Object} options Littlefoot options.
 * @return {Object}         Settings.
 */
function createSettings(options) {

  const store = Object.assign({}, defaults, options)

  /**
   * Settings prototype.
   *
   * @type {Object}
   */
  const Settings = {
    /**
     * Returns the value of the passed setting.
     *
     * @param  {String} key The setting to retrieve.
     * @return {*}          The value of the passed setting.
     */
    get(key) {
      return store[key]
    },

    /**
     * Updates the specified setting(s) with the value(s) you pass.
     *
     * @param  {String} key   The setting name as a string or an object containing
     *                        setting-new value pairs.
     * @param  {*}      value The new value, if the first argument was a string.
     */
    set(key, value) {
      store[key] = value
    },
  }

  return Object.assign(Object.create(Settings), store)
}

export default createSettings
<commit_msg>Improved keyboard navigation of scrollable footnotes<commit_after>/**
 * Default settings.
 *
 * @type {Object}
 */
const defaults = {
  activateCallback:     null,
  activateDelay:        100,
  activateOnHover:      false,
  allowDuplicates:      true,
  allowMultiple:        false,
  anchorParentSelector: 'sup',
  anchorPattern:        /(fn|footnote|note)[:\-_\d]/gi,
  dismissDelay:         300,
  dismissOnUnhover:     false,
  footnoteParentClass:  'footnote',
  footnoteSelector:     'li',
  hoverDelay:           250,
  numberResetSelector:  null,
  scope:                null,
  contentTemplate:      '<aside class="littlefoot-footnote is-positioned-bottom" data-footnote-id="<%= id %>" data-footnote-number="<%= number %>" alt="Footnote <%= number %>">

<%= content %>

',
  buttonTemplate:       '
<button class="littlefoot-footnote__button littlefoot-footnote__button__ellipsis" id="<%= reference %>" data-footnote-id="<%= id %>" data-footnote-number="<%= number %>" alt="See Footnote <%= number %>" rel="footnote" data-littlefoot-footnote="<%= content %>"><svg viewbox="0 0 31 6" preserveAspectRatio="xMidYMid"><circle r="3" cx="3" cy="3" fill="white"></circle><circle r="3" cx="15" cy="3" fill="white"></circle><circle r="3" cx="27" cy="3" fill="white"></circle></svg></button>
',
}

/**
 * Settings factory.
 * @param  {Object} options Littlefoot options.
 * @return {Object}         Settings.
 */
function createSettings(options) {

  const store = Object.assign({}, defaults, options)

  /**
   * Settings prototype.
   *
   * @type {Object}
   */
  const Settings = {
    /**
     * Returns the value of the passed setting.
     *
     * @param  {String} key The setting to retrieve.
     * @return {*}          The value of the passed setting.
     */
    get(key) {
      return store[key]
    },

    /**
     * Updates the specified setting(s) with the value(s) you pass.
     *
     * @param   {String} key   The setting name as a string or an object containing
     *                         setting-new value pairs.
     * @param   {*}      value The new value, if the first argument was a string.
     * @returns {null}
     */
    set(key, value) {
      store[key] = value
    },
  }

  return Object.assign(Object.create(Settings), store)
}

export default createSettings
<|endoftext|>