<commit_before>window.onload = function () {
	var draw = document.getElementById('draw'),
		ctx,
		xClock,
		yClock,
		rClock;

	ctx = getCtx(draw);
	if (ctx === null) return;

	setSize(draw);

	xClock = draw.width / 2;
	yClock = draw.height / 2;
	rClock = xClock < yClock ? 0.7 * xClock : 0.7 * yClock;

	drawClock(ctx, xClock, yClock, rClock);

	setInterval(function () {
		ctx.clearRect(0, 0, draw.width, draw.height);
		drawClock(ctx, xClock, yClock, rClock);
	}, 1000);

};

function getCtx (canvas) {
	if (!canvas.getContext) {
		console.error('Your browser does not support the HTML5 <canvas>.');
		return null;
	}

	return canvas.getContext('2d');
}

function setSize (canvas) {
	canvas.width = document.body.clientWidth;
	canvas.height = document.body.clientHeight;
}

function drawClock (ctx, x, y, r) {
	var numbersAngle = 2 * Math.PI / 12,
		hourAngle = numbersAngle,
		minAngle = 2 * Math.PI / 60,
		date = new Date();

	document.body.style.backgroundColor = '#' + ("0" + date.getHours()).slice(-2) + ("0" + date.getMinutes()).slice(-2) + ("0" + date.getSeconds()).slice(-2);

	ctx.beginPath();
	// draw outer circle
	ctx.save();
	ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
	ctx.lineWidth = 5;
	ctx.arc(x, y, r, 0, 2 * Math.PI, false);
	ctx.fill();
	ctx.stroke();
	ctx.restore();

	ctx.beginPath();

	ctx.save();

	// translate to center
	ctx.translate(x, y);

	// draw seconds hand
	ctx.save();
	ctx.rotate(minAngle * date.getSeconds());
	ctx.moveTo(-2, 20);
	ctx.lineTo(0, - r + 30);
	ctx.lineTo(2, 20);
	ctx.restore();

	// draw minute hand
	ctx.save();
	ctx.rotate(minAngle * date.getMinutes());
	ctx.moveTo(-4, 20);
	ctx.lineTo(0, - r + 30);
	ctx.lineTo(4, 20);
	ctx.restore();

	// draw hour hand
	ctx.save();
	ctx.rotate(hourAngle * date.getHours());
	ctx.moveTo(-4, 20);
	ctx.lineTo(0, - r + 100);
	ctx.lineTo(4, 20);
	ctx.restore();

	// fill the path
	ctx.fill();

	// draw numbers
	ctx.font = 'bold 14px Arial';
	ctx.textAlign = 'center';
	ctx.textBaseline = 'middle';

	ctx.save();
	ctx.rotate(numbersAngle);
	for (i = 1; i <= 12; i++) {
		ctx.fillText(i, 0, - r + 20);
		ctx.rotate(numbersAngle);
	}
	ctx.restore();

	ctx.restore();
}
<commit_msg>Calc color based in ts<commit_after>window.onload = function () {
	var draw = document.getElementById('draw'),
		ctx,
		xClock,
		yClock,
		rClock;

	ctx = getCtx(draw);
	if (ctx === null) return;

	setSize(draw);

	xClock = draw.width / 2;
	yClock = draw.height / 2;
	rClock = xClock < yClock ? 0.7 * xClock : 0.7 * yClock;

	drawClock(ctx, xClock, yClock, rClock);

	setInterval(function () {
		ctx.clearRect(0, 0, draw.width, draw.height);
		drawClock(ctx, xClock, yClock, rClock);
	}, 1000);

};

function getCtx (canvas) {
	if (!canvas.getContext) {
		console.error('Your browser does not support the HTML5 <canvas>.');
		return null;
	}

	return canvas.getContext('2d');
}

function setSize (canvas) {
	canvas.width = document.body.clientWidth;
	canvas.height = document.body.clientHeight;
}

function drawClock (ctx, x, y, r) {
	var numbersAngle = 2 * Math.PI / 12,
		hourAngle = numbersAngle,
		minAngle = 2 * Math.PI / 60,
		date = new Date();

	document.body.style.backgroundColor = '#' + ((date.getTime()).toString()).slice(-6);

	ctx.beginPath();
	// draw outer circle
	ctx.save();
	ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
	ctx.lineWidth = 5;
	ctx.arc(x, y, r, 0, 2 * Math.PI, false);
	ctx.fill();
	ctx.stroke();
	ctx.restore();

	ctx.beginPath();

	ctx.save();

	// translate to center
	ctx.translate(x, y);

	// draw seconds hand
	ctx.save();
	ctx.rotate(minAngle * date.getSeconds());
	ctx.moveTo(-2, 20);
	ctx.lineTo(0, - r + 30);
	ctx.lineTo(2, 20);
	ctx.restore();

	// draw minute hand
	ctx.save();
	ctx.rotate(minAngle * date.getMinutes());
	ctx.moveTo(-4, 20);
	ctx.lineTo(0, - r + 30);
	ctx.lineTo(4, 20);
	ctx.restore();

	// draw hour hand
	ctx.save();
	ctx.rotate(hourAngle * date.getHours());
	ctx.moveTo(-4, 20);
	ctx.lineTo(0, - r + 100);
	ctx.lineTo(4, 20);
	ctx.restore();

	// fill the path
	ctx.fill();

	// draw numbers
	ctx.font = 'bold 14px Arial';
	ctx.textAlign = 'center';
	ctx.textBaseline = 'middle';

	ctx.save();
	ctx.rotate(numbersAngle);
	for (i = 1; i <= 12; i++) {
		ctx.fillText(i, 0, - r + 20);
		ctx.rotate(numbersAngle);
	}
	ctx.restore();

	ctx.restore();
}
<|endoftext|>


<commit_before>import _ from 'lodash';
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { Router, hashHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import config from '../lib/config';
window.DEBUG = config.DEBUG;
import Root from './containers/Root';
import routes from './routes';
import configureStore from './store/configureStore';
import './app.global.css';
import '../styles/main.less';

const store = configureStore();
const history = syncHistoryWithStore(hashHistory, store);

render(
  <Provider store={store}>
    <Router history={history} routes={routes} />
  </Provider>,
  document.getElementById('app')
);
<commit_msg>set to index route on app load<commit_after>import _ from 'lodash';
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { Router, hashHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import config from '../lib/config';
window.DEBUG = config.DEBUG;
import Root from './containers/Root';
import routes from './routes';
import configureStore from './store/configureStore';
import './app.global.css';
import '../styles/main.less';

const store = configureStore();
const history = syncHistoryWithStore(hashHistory, store);
hashHistory.push('/');
render(
  <Provider store={store}>
    <Router history={history} routes={routes} />
  </Provider>,
  document.getElementById('app')
);
<|endoftext|>


<commit_before>import { SHADING_SURVEY, STATION_ENTRANCE } from '../core/constants';
import { Page } from './Page';

class SelectionCommonPage extends Page {

	constructor ( frame, viewer, container, fileSelector ) {

		super( 'icon_explore', 'selection', _onTop, _onLeave );

		frame.addPage( this );

		this.surveyTree = viewer.getSurveyTree();
		this.currentTop = this.surveyTree;

		this.nodes = new WeakMap();
		this.leafSections = new WeakSet();
		this.lastSelected = null;
		this.lastSection = 0;
		this.lastShadingMode = viewer.shadingMode;
		this.currentHover = null;
		this.stringCompare = new Intl.Collator( 'en-GB', { numeric: true } ).compare;
		this.isOntop = false;

		const titleBar = document.createElement( 'div' );
		const cfg = viewer.ctx.cfg;

		titleBar.id = 'ui-path';
		titleBar.classList.add( 'header' );

		if ( viewer.isClipped ) {

			const span = document.createElement( 'span' );
			span.textContent = '\u25c0 ';

			this.addListener( titleBar, 'click', __handleLoadFull );

			titleBar.classList.add( 'reload' );

			const txt = document.createTextNode( this.currentTop.name );

			titleBar.appendChild( span );
			titleBar.appendChild( txt );

		} else {

			titleBar.textContent = this.currentTop.name;

			this.nodes.set( titleBar, this.currentTop );

		}

		this.titleBar = titleBar;
		this.appendChild( titleBar );

		this.addListener( this.page, 'mouseover', _handleMouseover );
		this.addListener( this.page, 'mouseleave', _handleMouseleave );

		this.addListener( this.page, 'click', _handleSelectSurveyClick );
		this.addListener( this.page, 'dblclick', _handleSelectSurveyDblClick );

		const self = this;

		let redraw = container.clientHeight; /* lgtm[js/unused-local-variable] */ // eslint-disable-line no-unused-vars

		this.addLine = function ( ul, child ) {

			if ( child === null ) return;

			const connections = child.isStation() ? child.effectiveConnections() : null;

			// track which sections have stations as children

			if ( connections !== null && ! this.leafSections.has( ul) ) this.leafSections.add( ul );

			// omit splays if now displaying

			if ( connections === 0 && ! viewer.splays && ! ( child.type & STATION_ENTRANCE ) ) return;

			const li  = document.createElement( 'li' );
			const text = ( child.comment === undefined ) ? child.name : child.name + ' ( ' + child.comment + ' )';
			const txt = document.createTextNode( text );

			let key;

			self.nodes.set( li, child );

			if ( viewer.section === child ) li.classList.add( 'selected' );

			if ( child.type === 0 ) {

				key = _makeKey( '\u2588 ', '#444444' );

				li.classList.add( 'section' );

			} else if ( child.type & STATION_ENTRANCE ) {

				key = _makeKey( '\u2229 ', cfg.themeColorCSS( 'stations.entrances.marker' ) );
				key.classList.add( 'cv-entrance' );

			} else if ( connections > 2 ) { // station at junction

				key = _makeKey( '\u25fc ', cfg.themeColorCSS( 'stations.junctions.marker' ) );

			} else if ( connections === 0 ) { // end of splay

				key = _makeKey( '\u25fb ', cfg.themeColorCSS( 'stations.default.marker' ) );

			} else { // normal station in middle or end of leg

				key = _makeKey( '\u25fc ', cfg.themeColorCSS( 'stations.default.marker' ) );

			}

			li.appendChild( key );
			li.appendChild( txt );

			if ( child.next ) {

				const duplicateTag = document.createElement( 'span' );

				duplicateTag.textContent = ' [linked station]';
				duplicateTag.classList.add( 'duplicate' );

				li.appendChild( duplicateTag );

			}

			if ( child.children.length > 0 ) {

				const descend = document.createElement( 'div' );

				descend.classList.add( 'descend-tree' );

				self.nodes.set( descend, child );

				li.appendChild( descend );

			}

			ul.appendChild( li );

		};

		this.displaySectionCommon = function ( top ) {

			const children = top.children;

			if ( ! top.sorted ) {

				children.sort( ( s1, s2 ) => this.stringCompare( s1.name, s2.name ) );

				top.sorted = true;

			}

			const ul = document.createElement( 'ul' );
			ul.classList.add( 'cv-tree' );

			top.forEachChild( child => this.addLine( ul, child ) );

			_colourSections( ul );

			this.currentTop = top;
			// this.lastSelected = null;
			this.lastShadingMode = viewer.shadingMode;

			return ul;

		};

		this.reloadSections = function () {

			const uls = this.page.getElementsByTagName( 'UL' );
			const targetSections = [];

			// find leaf sections that need reloading

			for ( let i = 0; i < uls.length; i++ ) {

				const ul = uls[ i ];
				if ( this.leafSections.has( ul ) ) targetSections.push( ul );

			}

			targetSections.forEach( ul => {

				const node = this.nodes.get( ul.previousSibling ) || this.currentTop;

				if ( node ) ul.replaceWith( this.displaySectionCommon( node ) );

			} );

		};

		this.onChange = _onChange;

		return;

		function _makeKey ( text, color ) {

			const key = document.createElement( 'span' );

			key.style.color = color;
			key.textContent = text;

			return key;

		}

		function _handleMouseleave ( /* event */ ) {

			viewer.highlight = self.surveyTree;
			viewer.popup = self.surveyTree;

		}

		function _handleMouseover ( event ) {

			const target = event.target;

			if ( target.nodeName !== 'LI' ) return;

			const node = self.nodes.get( target );

			if ( node !== self.currentHover ) {

				viewer.highlight = ( viewer.section !== node ) ? node : self.surveyTree;
				viewer.popup = node;

				self.currentHover = node;

			}

		}

		function _handleSelectSurveyClick ( event ) {

			event.stopPropagation();
			event.preventDefault();

			const target = event.target;
			const node = self.nodes.get( target );

			switch ( target.tagName ) {

			case 'LI':

				viewer.section = node;
				viewer.setPOI = true;

				target.classList.add( 'selected' );

				if ( self.lastSelected !== null ) self.lastSelected.classList.remove( 'selected' );

				self.lastSelected = target;

				break;

			case 'DIV':

				self.handleNext( target, node );
				break;

			case 'SPAN':

				if ( target.classList.contains( 'duplicate' ) ) {

					const node = self.nodes.get( target.parentNode );
					self.selectNode( node.next );

				} else {
					self.handleBack( target );
				}

				break;

			}

		}

		function _handleSelectSurveyDblClick ( event ) {

			event.stopPropagation();
			event.preventDefault();

			const target = event.target;
			const node = self.nodes.get( target );

			if ( ! target.classList.contains( 'section' ) ) return;

			if ( node !== self.surveyTree ) viewer.cut = true;

		}

		function _onChange( event ) {

			if ( ! viewer.surveyLoaded ) return;

			if ( event.name === 'splays' ) {

				self.reloadSections();
				return;
			}

			if (
				( self.lastSection !== viewer.section ) ||
				( self.lastShadingMode === SHADING_SURVEY && viewer.shadingMode !== SHADING_SURVEY ) ||
				( self.lastShadingMode !== SHADING_SURVEY && viewer.shadingMode === SHADING_SURVEY )
			) {

				_colourSections();

				self.lastShadingMode = viewer.shadingMode;
				self.lastSection = viewer.section;

			}

		}

		function _colourSections( ul ) {

			const root = ( ul === undefined ) ? self.page : ul;
			const lis = root.getElementsByTagName( 'li' );

			const surveyColourMapper = viewer.ctx.surveyColourMapper;
			const surveyColourMap = ( viewer.shadingMode === SHADING_SURVEY ) ? surveyColourMapper.getColourMap( viewer.section ) : null;

			for ( let i = 0; i < lis.length; i++ ) {

				const li = lis[ i ];
				const node = self.nodes.get( lis[ i ] );

				if ( node !== undefined && ! node.isStation() ) {

					const span = li.firstChild;
					const id = node.id;
					let colour;

					if ( surveyColourMap?.[ id ] !== undefined ) {

						colour = '#' + surveyColourMap[ id ].getHexString();

					} else {

						colour = '#444444';

					}

					span.style.color = colour;

				}

			}

		}

		function __handleLoadFull () {

			fileSelector.reload();

		}

		function _onTop( ) {

			self.isOntop = true;

		}

		function _onLeave( ) {

			self.isOntop = false;

		}

	}

	selectNode () {} // not implemented for side scrolling tree structure

}

export { SelectionCommonPage };<commit_msg>display duplicate count in tree<commit_after>import { SHADING_SURVEY, STATION_ENTRANCE } from '../core/constants';
import { Page } from './Page';

class SelectionCommonPage extends Page {

	constructor ( frame, viewer, container, fileSelector ) {

		super( 'icon_explore', 'selection', _onTop, _onLeave );

		frame.addPage( this );

		this.surveyTree = viewer.getSurveyTree();
		this.currentTop = this.surveyTree;

		this.nodes = new WeakMap();
		this.leafSections = new WeakSet();
		this.lastSelected = null;
		this.lastSection = 0;
		this.lastShadingMode = viewer.shadingMode;
		this.currentHover = null;
		this.stringCompare = new Intl.Collator( 'en-GB', { numeric: true } ).compare;
		this.isOntop = false;

		const titleBar = document.createElement( 'div' );
		const cfg = viewer.ctx.cfg;

		titleBar.id = 'ui-path';
		titleBar.classList.add( 'header' );

		if ( viewer.isClipped ) {

			const span = document.createElement( 'span' );
			span.textContent = '\u25c0 ';

			this.addListener( titleBar, 'click', __handleLoadFull );

			titleBar.classList.add( 'reload' );

			const txt = document.createTextNode( this.currentTop.name );

			titleBar.appendChild( span );
			titleBar.appendChild( txt );

		} else {

			titleBar.textContent = this.currentTop.name;

			this.nodes.set( titleBar, this.currentTop );

		}

		this.titleBar = titleBar;
		this.appendChild( titleBar );

		this.addListener( this.page, 'mouseover', _handleMouseover );
		this.addListener( this.page, 'mouseleave', _handleMouseleave );

		this.addListener( this.page, 'click', _handleSelectSurveyClick );
		this.addListener( this.page, 'dblclick', _handleSelectSurveyDblClick );

		const self = this;

		let redraw = container.clientHeight; /* lgtm[js/unused-local-variable] */ // eslint-disable-line no-unused-vars

		this.addLine = function ( ul, child ) {

			if ( child === null ) return;

			const connections = child.isStation() ? child.effectiveConnections() : null;

			// track which sections have stations as children

			if ( connections !== null && ! this.leafSections.has( ul) ) this.leafSections.add( ul );

			// omit splays if now displaying

			if ( connections === 0 && ! viewer.splays && ! ( child.type & STATION_ENTRANCE ) ) return;

			const li  = document.createElement( 'li' );
			const text = ( child.comment === undefined ) ? child.name : child.name + ' ( ' + child.comment + ' )';
			const txt = document.createTextNode( text );

			let key;

			self.nodes.set( li, child );

			if ( viewer.section === child ) li.classList.add( 'selected' );

			if ( child.type === 0 ) {

				key = _makeKey( '\u2588 ', '#444444' );

				li.classList.add( 'section' );

			} else if ( child.type & STATION_ENTRANCE ) {

				key = _makeKey( '\u2229 ', cfg.themeColorCSS( 'stations.entrances.marker' ) );
				key.classList.add( 'cv-entrance' );

			} else if ( connections > 2 ) { // station at junction

				key = _makeKey( '\u25fc ', cfg.themeColorCSS( 'stations.junctions.marker' ) );

			} else if ( connections === 0 ) { // end of splay

				key = _makeKey( '\u25fb ', cfg.themeColorCSS( 'stations.default.marker' ) );

			} else { // normal station in middle or end of leg

				key = _makeKey( '\u25fc ', cfg.themeColorCSS( 'stations.default.marker' ) );

			}

			li.appendChild( key );
			li.appendChild( txt );

			if ( child.next ) {

				let next = child.next;
				let count = 1;

				while ( next && next !== child ) {

					count++;
					next = next.next;

				}

				const duplicateTag = document.createElement( 'span' );

				duplicateTag.textContent = ` [linked station ${count}]`;
				duplicateTag.classList.add( 'duplicate' );

				li.appendChild( duplicateTag );

			}

			if ( child.children.length > 0 ) {

				const descend = document.createElement( 'div' );

				descend.classList.add( 'descend-tree' );

				self.nodes.set( descend, child );

				li.appendChild( descend );

			}

			ul.appendChild( li );

		};

		this.displaySectionCommon = function ( top ) {

			const children = top.children;

			if ( ! top.sorted ) {

				children.sort( ( s1, s2 ) => this.stringCompare( s1.name, s2.name ) );

				top.sorted = true;

			}

			const ul = document.createElement( 'ul' );
			ul.classList.add( 'cv-tree' );

			top.forEachChild( child => this.addLine( ul, child ) );

			_colourSections( ul );

			this.currentTop = top;
			// this.lastSelected = null;
			this.lastShadingMode = viewer.shadingMode;

			return ul;

		};

		this.reloadSections = function () {

			const uls = this.page.getElementsByTagName( 'UL' );
			const targetSections = [];

			// find leaf sections that need reloading

			for ( let i = 0; i < uls.length; i++ ) {

				const ul = uls[ i ];
				if ( this.leafSections.has( ul ) ) targetSections.push( ul );

			}

			targetSections.forEach( ul => {

				const node = this.nodes.get( ul.previousSibling ) || this.currentTop;

				if ( node ) ul.replaceWith( this.displaySectionCommon( node ) );

			} );

		};

		this.onChange = _onChange;

		return;

		function _makeKey ( text, color ) {

			const key = document.createElement( 'span' );

			key.style.color = color;
			key.textContent = text;

			return key;

		}

		function _handleMouseleave ( /* event */ ) {

			viewer.highlight = self.surveyTree;
			viewer.popup = self.surveyTree;

		}

		function _handleMouseover ( event ) {

			const target = event.target;

			if ( target.nodeName !== 'LI' ) return;

			const node = self.nodes.get( target );

			if ( node !== self.currentHover ) {

				viewer.highlight = ( viewer.section !== node ) ? node : self.surveyTree;
				viewer.popup = node;

				self.currentHover = node;

			}

		}

		function _handleSelectSurveyClick ( event ) {

			event.stopPropagation();
			event.preventDefault();

			const target = event.target;
			const node = self.nodes.get( target );

			switch ( target.tagName ) {

			case 'LI':

				viewer.section = node;
				viewer.setPOI = true;

				target.classList.add( 'selected' );

				if ( self.lastSelected !== null ) self.lastSelected.classList.remove( 'selected' );

				self.lastSelected = target;

				break;

			case 'DIV':

				self.handleNext( target, node );
				break;

			case 'SPAN':

				if ( target.classList.contains( 'duplicate' ) ) {

					const node = self.nodes.get( target.parentNode );
					self.selectNode( node.next );

				} else {
					self.handleBack( target );
				}

				break;

			}

		}

		function _handleSelectSurveyDblClick ( event ) {

			event.stopPropagation();
			event.preventDefault();

			const target = event.target;
			const node = self.nodes.get( target );

			if ( ! target.classList.contains( 'section' ) ) return;

			if ( node !== self.surveyTree ) viewer.cut = true;

		}

		function _onChange( event ) {

			if ( ! viewer.surveyLoaded ) return;

			if ( event.name === 'splays' ) {

				self.reloadSections();
				return;
			}

			if (
				( self.lastSection !== viewer.section ) ||
				( self.lastShadingMode === SHADING_SURVEY && viewer.shadingMode !== SHADING_SURVEY ) ||
				( self.lastShadingMode !== SHADING_SURVEY && viewer.shadingMode === SHADING_SURVEY )
			) {

				_colourSections();

				self.lastShadingMode = viewer.shadingMode;
				self.lastSection = viewer.section;

			}

		}

		function _colourSections( ul ) {

			const root = ( ul === undefined ) ? self.page : ul;
			const lis = root.getElementsByTagName( 'li' );

			const surveyColourMapper = viewer.ctx.surveyColourMapper;
			const surveyColourMap = ( viewer.shadingMode === SHADING_SURVEY ) ? surveyColourMapper.getColourMap( viewer.section ) : null;

			for ( let i = 0; i < lis.length; i++ ) {

				const li = lis[ i ];
				const node = self.nodes.get( lis[ i ] );

				if ( node !== undefined && ! node.isStation() ) {

					const span = li.firstChild;
					const id = node.id;
					let colour;

					if ( surveyColourMap?.[ id ] !== undefined ) {

						colour = '#' + surveyColourMap[ id ].getHexString();

					} else {

						colour = '#444444';

					}

					span.style.color = colour;

				}

			}

		}

		function __handleLoadFull () {

			fileSelector.reload();

		}

		function _onTop( ) {

			self.isOntop = true;

		}

		function _onLeave( ) {

			self.isOntop = false;

		}

	}

	selectNode () {} // not implemented for side scrolling tree structure

}

export { SelectionCommonPage };<|endoftext|>


<commit_before>
// special case for Android which sadly doesn't implement the canPlayType function (always returns '')
if (mejs.PluginDetector.ua.match(/Android 2\.[12]/) !== null) {
	HTMLMediaElement.canPlayType = function(type) {
		return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'probably' : '';
	};
}

// necessary detection (fixes for <IE9)
mejs.MediaFeatures = {
	init: function() {
		var
			nav = mejs.PluginDetector.nav,
			ua = mejs.PluginDetector.ua,
			i,
			v,
			html5Elements = ['source','track','audio','video'];

		// detect browsers
		this.isiPad = (ua.match(/iPad/i) !== null);
		this.isiPhone = (ua.match(/iPhone/i) !== null);
		this.isAndroid = (ua.match(/Android/i) !== null);
		this.isIE = (nav.appName.indexOf("Microsoft") != -1);
		this.isChrome = (ua.match(/Chrome/gi) !== null);

		// create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
		for (i=0; i<html5Elements.length; i++) {
			v = document.createElement(html5Elements[i]);
		}

		// detect native JavaScript fullscreen (Safari only, Chrome fails)
		this.hasNativeFullScreen = (typeof v.webkitEnterFullScreen !== 'undefined');
		if (this.isChrome) {
			this.hasNativeFullScreen = false;
		}
	}
};
mejs.MediaFeatures.init();
<commit_msg>- updated detection note<commit_after>
// special case for Android which sadly doesn't implement the canPlayType function (always returns '')
if (mejs.PluginDetector.ua.match(/Android 2\.[12]/) !== null) {
	HTMLMediaElement.canPlayType = function(type) {
		return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'probably' : '';
	};
}

// necessary detection (fixes for <IE9)
mejs.MediaFeatures = {
	init: function() {
		var
			nav = mejs.PluginDetector.nav,
			ua = mejs.PluginDetector.ua,
			i,
			v,
			html5Elements = ['source','track','audio','video'];

		// detect browsers (only the ones that have some kind of quirk we need to work around)
		this.isiPad = (ua.match(/iPad/i) !== null);
		this.isiPhone = (ua.match(/iPhone/i) !== null);
		this.isAndroid = (ua.match(/Android/i) !== null);
		this.isIE = (nav.appName.indexOf("Microsoft") != -1);
		this.isChrome = (ua.match(/Chrome/gi) !== null);

		// create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
		for (i=0; i<html5Elements.length; i++) {
			v = document.createElement(html5Elements[i]);
		}

		// detect native JavaScript fullscreen (Safari only, Chrome fails)
		this.hasNativeFullScreen = (typeof v.webkitEnterFullScreen !== 'undefined');
		if (this.isChrome) {
			this.hasNativeFullScreen = false;
		}
	}
};
mejs.MediaFeatures.init();
<|endoftext|>


<commit_before>require('dotenv').config();
const WebClient = require('@slack/client').WebClient;
const express = require('express');
const request = require('request');
const logger = require('morgan');
const sassMiddleware = require('node-sass-middleware');
const path = require('path');
const { IncomingWebhook } = require('@slack/client');
const Bot = require('./models/bot');
const bodyParser = require('body-parser');
const postInSlack = require('./lib/postInSlack');
const getLocation = require('./lib/getLocation');
const postMessage = require('./lib/slackWebClient').postMessage;
const weatherFor = require('./lib/weatherFor');
const sendHelp = require('./lib/sendHelp');
const SlackWebClient = require('./lib/slackWebClient');
const setUnits = require('./lib/setUnits');

const app = express();

app.use(logger('dev'));
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

function clientErrorHandler (err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' })
  } else {
    next(err)
  }
}

function errorHandler (err, req, res, next) {
  res.status(500)
  res.render('error', { error: err })
}

app.use(clientErrorHandler)
app.use(errorHandler)

const srcPath = __dirname + '/sass';
const destPath = __dirname + '/../public/styles';

if (process.env.NODE_ENV != 'production') {
  app.use('/styles', sassMiddleware({
    src: srcPath,
    dest: destPath,
    debug: true,
    prefix: '/styles',
    outputStyle: 'compressed',
    outputStyle: 'expanded'
  }));
}

app.set('view engine', 'pug');

app.use('/icons', express.static('public/icons'))
app.use('/styles', express.static('public/styles'));
app.use('/robots.txt', express.static('public/robots.txt'));

app.get('/', (req, res) => {
  res.render('index');
});
app.get('/success', (req, res) => {
  res.render('success');
});
app.get('/error', (req, res) => {
  res.render('error');
});
app.get('/help', (req, res) => {
  res.render('help');
});

app.post('/weather', (req, res) => {
  const message = req.body;
  const location = message.text.replace(/<@.*>/, '').replace(/![\w]*/, '');
  const responseURL = message.response_url;

  if (message.token !== process.env.SLACK_VERIFICATION_TOKEN) {
    res.sendStatus(400);
    return;
  }

  Bot.findOne({ teamID: message.team_id })
    .then((bot) => {
      const units = bot.units || 'us';

      if (message.text.match(/help\s*$/) || location.match(/^(?![\s\S])/)) {
        res.status(200).send({ text: sendHelp() });
      } else if (message.text.match(/set\s*/)) {
        res.status(200).send({ text: setUnits(bot, message) });
      } else {
        getLocation(location)
          .then((coords) => {
            res.status(200).send({ text: `Getting weather for ${location}` });
            return weatherFor(coords.lat, coords.lng, coords.location, units);
          })
          .then((weather) => {
            postInSlack(responseURL, weather, units);
          })
          .catch((err) => {
            console.log(err);
            res.status(200).send(
              `Sorry, I could not find any location called ${location}. Can you be more specific?\n\n Just type "/forecast help" if you need help!`
            );
          });
      }
    })
    .catch((err) => {
      console.log(err);
      res.sendStatus(400);
    });
});

app.get('/auth/slack/callback', (req, res) => {
  const data = {
    form: {
      client_id: process.env.SLACK_CLIENT_ID,
      client_secret: process.env.SLACK_CLIENT_SECRET,
      redirect_uri: process.env.REDIRECT_URI,
      code: req.query.code
    }
  };
  request.post('https://slack.com/api/oauth.access', data, (error, response, body) => {
    if (!error && response.statusCode == 200) {
      const json = JSON.parse(body);
      const teamID = json.team_id;
      const teamName = json.team_name;
      const accessToken = json.access_token;
      Bot.findOne({ teamID })
        .then((existingBot) => {
          if ( existingBot ) {
            existingBot.teamID = slackID;
            existingBot.accessToken = accessToken;
            existingBot.teamName = teamName;
            existingBot.save()
              .then(() => {
                return res.redirect('/success');
              });
          } else {
            new Bot({ teamID, accessToken, teamName }).save()
              .then((bot) => {
                res.redirect('/success');
              })
              .catch((_err) => {
                console.log(_err);
                res.redirect('/error');
              });
          }
        })
        .catch((err) => {
          console.log(err);
          res.redirect('/error');
        });
    } else {
      console.log("OAuth error");
      console.log(response.body);
    }
  });
});

module.exports = app;
<commit_msg>teamID<commit_after>require('dotenv').config();
const WebClient = require('@slack/client').WebClient;
const express = require('express');
const request = require('request');
const logger = require('morgan');
const sassMiddleware = require('node-sass-middleware');
const path = require('path');
const { IncomingWebhook } = require('@slack/client');
const Bot = require('./models/bot');
const bodyParser = require('body-parser');
const postInSlack = require('./lib/postInSlack');
const getLocation = require('./lib/getLocation');
const postMessage = require('./lib/slackWebClient').postMessage;
const weatherFor = require('./lib/weatherFor');
const sendHelp = require('./lib/sendHelp');
const SlackWebClient = require('./lib/slackWebClient');
const setUnits = require('./lib/setUnits');

const app = express();

app.use(logger('dev'));
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

function clientErrorHandler (err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' })
  } else {
    next(err)
  }
}

function errorHandler (err, req, res, next) {
  res.status(500)
  res.render('error', { error: err })
}

app.use(clientErrorHandler)
app.use(errorHandler)

const srcPath = __dirname + '/sass';
const destPath = __dirname + '/../public/styles';

if (process.env.NODE_ENV != 'production') {
  app.use('/styles', sassMiddleware({
    src: srcPath,
    dest: destPath,
    debug: true,
    prefix: '/styles',
    outputStyle: 'compressed',
    outputStyle: 'expanded'
  }));
}

app.set('view engine', 'pug');

app.use('/icons', express.static('public/icons'))
app.use('/styles', express.static('public/styles'));
app.use('/robots.txt', express.static('public/robots.txt'));

app.get('/', (req, res) => {
  res.render('index');
});
app.get('/success', (req, res) => {
  res.render('success');
});
app.get('/error', (req, res) => {
  res.render('error');
});
app.get('/help', (req, res) => {
  res.render('help');
});

app.post('/weather', (req, res) => {
  const message = req.body;
  const location = message.text.replace(/<@.*>/, '').replace(/![\w]*/, '');
  const responseURL = message.response_url;

  if (message.token !== process.env.SLACK_VERIFICATION_TOKEN) {
    res.sendStatus(400);
    return;
  }

  Bot.findOne({ teamID: message.team_id })
    .then((bot) => {
      const units = bot.units || 'us';

      if (message.text.match(/help\s*$/) || location.match(/^(?![\s\S])/)) {
        res.status(200).send({ text: sendHelp() });
      } else if (message.text.match(/set\s*/)) {
        res.status(200).send({ text: setUnits(bot, message) });
      } else {
        getLocation(location)
          .then((coords) => {
            res.status(200).send({ text: `Getting weather for ${location}` });
            return weatherFor(coords.lat, coords.lng, coords.location, units);
          })
          .then((weather) => {
            postInSlack(responseURL, weather, units);
          })
          .catch((err) => {
            console.log(err);
            res.status(200).send(
              `Sorry, I could not find any location called ${location}. Can you be more specific?\n\n Just type "/forecast help" if you need help!`
            );
          });
      }
    })
    .catch((err) => {
      console.log(err);
      res.sendStatus(400);
    });
});

app.get('/auth/slack/callback', (req, res) => {
  const data = {
    form: {
      client_id: process.env.SLACK_CLIENT_ID,
      client_secret: process.env.SLACK_CLIENT_SECRET,
      redirect_uri: process.env.REDIRECT_URI,
      code: req.query.code
    }
  };
  request.post('https://slack.com/api/oauth.access', data, (error, response, body) => {
    if (!error && response.statusCode == 200) {
      const json = JSON.parse(body);
      const teamID = json.team_id;
      const teamName = json.team_name;
      const accessToken = json.access_token;
      Bot.findOne({ teamID })
        .then((existingBot) => {
          if ( existingBot ) {
            existingBot.teamID = teamID;
            existingBot.accessToken = accessToken;
            existingBot.teamName = teamName;
            existingBot.save()
              .then(() => {
                return res.redirect('/success');
              });
          } else {
            new Bot({ teamID, accessToken, teamName }).save()
              .then((bot) => {
                res.redirect('/success');
              })
              .catch((_err) => {
                console.log(_err);
                res.redirect('/error');
              });
          }
        })
        .catch((err) => {
          console.log(err);
          res.redirect('/error');
        });
    } else {
      console.log("OAuth error");
      console.log(response.body);
    }
  });
});

module.exports = app;
<|endoftext|>


<commit_before>import instantsearch from 'instantsearch.js';
import {searchBox, hits, pagination, currentRefinedValues, menu, refinementList} from "instantsearch.js/es/widgets";

document.getElementById('search_query_query').addEventListener('keydown', function (e) {
    if (e.keyCode === 13) {
        e.preventDefault();
    }
});

var searchParameters = {};

if (decodeURI(location.search).match(/[<>]/)) {
    location.replace(location.pathname);
}

var searchThrottle = null;
var search = instantsearch({
    appId: algoliaConfig.app_id,
    apiKey: algoliaConfig.search_key,
    indexName: algoliaConfig.index_name,
    routing: {
        stateMapping: {
            stateToRoute: function (uiState) {
                return {
                    query: uiState.query && uiState.query.replace(new RegExp('([^\\s])--', 'g'), '$1-'),
                    type: uiState.menu && uiState.menu.type,
                    tags: uiState.refinementList && uiState.refinementList.tags && uiState.refinementList.tags.join('~'),
                    page: uiState.page,
                };
            },
            routeToState: function (routeState) {
                if (routeState.q) {
                    routeState.query = routeState.q;
                }

                if (
                    (routeState.query === undefined || routeState.query === '')
                    && (routeState.type === undefined || routeState.type === '')
                    && (routeState.tags === undefined || routeState.tags === '')
                ) {
                    return {};
                }

                return {
                    query: routeState.query || '',
                    menu: {
                        type: routeState.type
                    },
                    refinementList: {
                        tags: routeState.tags && routeState.tags.split('~'),
                    },
                    page: routeState.page
                };
            },
        },
    },
    searchFunction: function(helper) {
        var searchResults = document.querySelector('#search-container');

        if (helper.state.query === ''
            && helper.state.hierarchicalFacetsRefinements.type === undefined
            && (helper.state.disjunctiveFacetsRefinements.tags === undefined || helper.state.disjunctiveFacetsRefinements.tags.length === 0)
        ) {
            searchResults.classList.add('hidden');
        } else {
            searchResults.classList.remove('hidden');
        }

        if (searchThrottle) {
            clearTimeout(searchThrottle);
        }

        // force focus to prevent algolia from updating the search field input with the modified value
        document.getElementById('search_query_query').focus();

        helper.state.query = helper.state.query.replace(new RegExp('([^\\s])-', 'g'), '$1--');

        searchThrottle = setTimeout(function () {
            helper.search();
        }, 300);
    },
    searchParameters: searchParameters
});

var autofocus = false;
if (location.pathname == "/" || location.pathname == "/explore/") {
    autofocus = true;
}
search.addWidget(
    searchBox({
        container: '#search_query_query',
        magnifier: false,
        reset: false,
        wrapInput: false,
        autofocus: autofocus
    })
);

search.addWidget(
    hits({
        container: '.search-list',
        transformData: function (hit) {
            hit.url = '/packages/' + hit.name;
            if (hit.type === 'virtual-package') {
                hit.virtual = true;
                hit.url = '/providers/' + hit.name;
            }

            if (hit._highlightResult && hit._highlightResult.description.value && hit._highlightResult.description.value.length > 200) {
                hit._highlightResult.description.value = hit._highlightResult.description.value.substring(0, 200).replace(/<[a-z ]+$/, '');
            }

            hit.replacementPackageUrl = null

            if (hit.replacementPackage) {
                hit.replacementPackageUrl = hit.replacementPackage.indexOf('://') !== -1 ? hit.replacementPackage : ('/packages/' + hit.replacementPackage)
            }

            return hit;
        },
        templates: {
            empty: 'No packages found.',
            item: `

{{ language }}

                {{{ _highlightResult.name.value }}}
                {{#virtual}}
                    (Virtual Package)
                {{/virtual}}

{{{ _highlightResult.description.value }}}

            {{#abandoned}}

                 Abandoned!
                {{#replacementPackage}}
                    See {{ replacementPackage }}
                {{/replacementPackage}}

            {{/abandoned}}

            {{#meta}}

                     {{ meta.downloads_formatted }}
                     {{ meta.favers_formatted }}

            {{/meta}}

`
        },
        cssClasses: {
            root: 'packages',
            item: 'row'
        }
    })
);

search.addWidget(
    pagination({
        container: '.pagination',
        maxPages: 200,
        scrollTo: document.getElementById('search_query_query'),
        showFirstLast: false,
    })
);

search.addWidget(
    currentRefinedValues({
        container: '.search-facets-active-filters',
        clearAll: 'before',
        clearsQuery: false,
        cssClasses: {
            clearAll: 'pull-right'
        },
        templates: {
            header: 'Active filters',
            item: function (filter) {
                if ('tags' == filter.attributeName) {
                    return 'tag: ' + filter.name
                } else {
                    return filter.attributeName + ': ' + filter.name
                }
            }
        },
        onlyListedAttributes: true,
    })
);

search.addWidget(
    menu({
        container: '.search-facets-type',
        attributeName: 'type',
        limit: 15,
        showMore: true,
        templates: {
            header: 'Package type'
        }
    })
);

search.addWidget(
    refinementList({
        container: '.search-facets-tags',
        attributeName: 'tags',
        limit: 15,
        showMore: true,
        templates: {
            header: 'Tags'
        },
        searchForFacetValues:true
    })
);

search.start();
<commit_msg>Avoid searching for nothing<commit_after>import instantsearch from 'instantsearch.js';
import {searchBox, hits, pagination, currentRefinedValues, menu, refinementList} from "instantsearch.js/es/widgets";

document.getElementById('search_query_query').addEventListener('keydown', function (e) {
    if (e.keyCode === 13) {
        e.preventDefault();
    }
});

var searchParameters = {};

if (decodeURI(location.search).match(/[<>]/)) {
    location.replace(location.pathname);
}

var searchThrottle = null;
var search = instantsearch({
    appId: algoliaConfig.app_id,
    apiKey: algoliaConfig.search_key,
    indexName: algoliaConfig.index_name,
    routing: {
        stateMapping: {
            stateToRoute: function (uiState) {
                return {
                    query: uiState.query && uiState.query.replace(new RegExp('([^\\s])--', 'g'), '$1-'),
                    type: uiState.menu && uiState.menu.type,
                    tags: uiState.refinementList && uiState.refinementList.tags && uiState.refinementList.tags.join('~'),
                    page: uiState.page,
                };
            },
            routeToState: function (routeState) {
                if (routeState.q) {
                    routeState.query = routeState.q;
                }

                if (
                    (routeState.query === undefined || routeState.query === '')
                    && (routeState.type === undefined || routeState.type === '')
                    && (routeState.tags === undefined || routeState.tags === '')
                ) {
                    return {};
                }

                return {
                    query: routeState.query || '',
                    menu: {
                        type: routeState.type
                    },
                    refinementList: {
                        tags: routeState.tags && routeState.tags.split('~'),
                    },
                    page: routeState.page
                };
            },
        },
    },
    searchFunction: function(helper) {
        var searchResults = document.querySelector('#search-container');

        if (helper.state.query === ''
            && helper.state.hierarchicalFacetsRefinements.type === undefined
            && (helper.state.disjunctiveFacetsRefinements.tags === undefined || helper.state.disjunctiveFacetsRefinements.tags.length === 0)
        ) {
            searchResults.classList.add('hidden');
            return;
        } else {
            searchResults.classList.remove('hidden');
        }

        if (searchThrottle) {
            clearTimeout(searchThrottle);
        }

        // force focus to prevent algolia from updating the search field input with the modified value
        if (helper.state.query.match(/-/)) {
            document.getElementById('search_query_query').focus();
        }

        helper.state.query = helper.state.query.replace(new RegExp('([^\\s])-', 'g'), '$1--');

        searchThrottle = setTimeout(function () {
            helper.search();
        }, 300);
    },
    searchParameters: searchParameters
});

var autofocus = false;
if (location.pathname == "/" || location.pathname == "/explore/") {
    autofocus = true;
}
search.addWidget(
    searchBox({
        container: '#search_query_query',
        magnifier: false,
        reset: false,
        wrapInput: false,
        autofocus: autofocus
    })
);

search.addWidget(
    hits({
        container: '.search-list',
        transformData: function (hit) {
            hit.url = '/packages/' + hit.name;
            if (hit.type === 'virtual-package') {
                hit.virtual = true;
                hit.url = '/providers/' + hit.name;
            }

            if (hit._highlightResult && hit._highlightResult.description.value && hit._highlightResult.description.value.length > 200) {
                hit._highlightResult.description.value = hit._highlightResult.description.value.substring(0, 200).replace(/<[a-z ]+$/, '');
            }

            hit.replacementPackageUrl = null

            if (hit.replacementPackage) {
                hit.replacementPackageUrl = hit.replacementPackage.indexOf('://') !== -1 ? hit.replacementPackage : ('/packages/' + hit.replacementPackage)
            }

            return hit;
        },
        templates: {
            empty: 'No packages found.',
            item: `

{{ language }}

                {{{ _highlightResult.name.value }}}
                {{#virtual}}
                    (Virtual Package)
                {{/virtual}}

{{{ _highlightResult.description.value }}}

            {{#abandoned}}

                 Abandoned!
                {{#replacementPackage}}
                    See {{ replacementPackage }}
                {{/replacementPackage}}

            {{/abandoned}}

            {{#meta}}

                     {{ meta.downloads_formatted }}
                     {{ meta.favers_formatted }}

            {{/meta}}

`
        },
        cssClasses: {
            root: 'packages',
            item: 'row'
        }
    })
);

search.addWidget(
    pagination({
        container: '.pagination',
        maxPages: 200,
        scrollTo: document.getElementById('search_query_query'),
        showFirstLast: false,
    })
);

search.addWidget(
    currentRefinedValues({
        container: '.search-facets-active-filters',
        clearAll: 'before',
        clearsQuery: false,
        cssClasses: {
            clearAll: 'pull-right'
        },
        templates: {
            header: 'Active filters',
            item: function (filter) {
                if ('tags' == filter.attributeName) {
                    return 'tag: ' + filter.name
                } else {
                    return filter.attributeName + ': ' + filter.name
                }
            }
        },
        onlyListedAttributes: true,
    })
);

search.addWidget(
    menu({
        container: '.search-facets-type',
        attributeName: 'type',
        limit: 15,
        showMore: true,
        templates: {
            header: 'Package type'
        }
    })
);

search.addWidget(
    refinementList({
        container: '.search-facets-tags',
        attributeName: 'tags',
        limit: 15,
        showMore: true,
        templates: {
            header: 'Tags'
        },
        searchForFacetValues:true
    })
);

search.start();
<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');

var AngularParseGenerator = module.exports = function AngularParseGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });
  });

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(AngularParseGenerator, yeoman.generators.Base);

AngularParseGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    type: 'confirm',
    name: 'someOption',
    message: 'Would you like to enable this option?',
    default: true
  }];

  this.prompt(prompts, function (props) {
    this.someOption = props.someOption;

    cb();
  }.bind(this));
};

AngularParseGenerator.prototype.app = function app() {
  this.mkdir('app');
  this.mkdir('app/templates');

  this.copy('_package.json', 'package.json');
  this.copy('_bower.json', 'bower.json');
};

AngularParseGenerator.prototype.projectfiles = function projectfiles() {
  this.copy('editorconfig', '.editorconfig');
  this.copy('jshintrc', '.jshintrc');
};
<commit_msg>mudando pastas<commit_after>'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');

var AngularParseGenerator = module.exports = function AngularParseGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });
  });

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(AngularParseGenerator, yeoman.generators.Base);

AngularParseGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    name: 'projectName',
    message: 'What do you want to call your Project?'
  }];

  this.prompt(prompts, function (props) {
    this.someOption = props.someOption;

    cb();
  }.bind(this));
};

AngularParseGenerator.prototype.app = function app() {
  this.mkdir('app');
  this.mkdir('app/templates');

  this.copy('_package.json', 'package.json');
  this.copy('_bower.json', 'bower.json');
};

AngularParseGenerator.prototype.projectfiles = function projectfiles() {
  this.copy('editorconfig', '.editorconfig');
  this.copy('jshintrc', '.jshintrc');
};
<|endoftext|>


<commit_before>var EventEmitter = require("events").EventEmitter;
var lazy = require("lazy.js");
var objectPath = require("object-path");
var Util = require("../helpers/Util");

var AppDispatcher = require("../AppDispatcher");
var AppFormErrorMessages = require("../constants/AppFormErrorMessages");
var AppFormTransforms = require("./transforms/AppFormTransforms");
var AppFormModelPostProcess = require("./transforms/AppFormModelPostProcess");
var AppFormValidators = require("./validators/AppFormValidators");
var AppsStore = require("./AppsStore");
var AppsEvents = require("../events/AppsEvents");
var FormEvents = require("../events/FormEvents");

const defaultFieldValues = Object.freeze({
  cpus: 0.1,
  mem: 16,
  disk: 0,
  instances: 1
});

const duplicableRowFields = [
  "containerVolumes",
  "dockerPortMappings",
  "dockerParameters",
  "env",
  "healthChecks",
  "labels"
];

/**
 * Validation rules for individual fields and fieldsets (duplicable rows).
 * The array index of the rule is related to the error message index
 * in AppFormErrorMessages.
 *
 * fieldIds not listed here are considered valid by default.
 */
const validationRules = {
  "appId": [
    AppFormValidators.appIdNotEmpty,
    AppFormValidators.appIdNoWhitespaces,
    AppFormValidators.appIdValidChars,
    AppFormValidators.appIdWellFormedPath
  ],
  "constraints": [AppFormValidators.constraints],
  "containerVolumes": [
    AppFormValidators.containerVolumesContainerPathIsValid,
    AppFormValidators.containerVolumesHostPathIsValid,
    AppFormValidators.containerVolumesModeNotEmpty
  ],
  "cpus": [AppFormValidators.cpus],
  "disk": [AppFormValidators.disk],
  "dockerImage": [AppFormValidators.dockerImageNoWhitespaces],
  "dockerParameters": [AppFormValidators.dockerParameters],
  "dockerPortMappings": [
    AppFormValidators.dockerPortMappingsContainerPortIsValid,
    AppFormValidators.dockerPortMappingsHostPortIsValid,
    AppFormValidators.dockerPortMappingsServicePortIsValid,
    AppFormValidators.dockerPortMappingsProtocolValidType
  ],
  "env": [AppFormValidators.env],
  "executor": [AppFormValidators.executor],
  "healthChecks": [
    AppFormValidators.healthChecksProtocol,
    AppFormValidators.healthChecksCommandNotEmpty,
    AppFormValidators.healthChecksPathNotEmpty,
    AppFormValidators.healthChecksPortIndex,
    AppFormValidators.healthChecksGracePeriod,
    AppFormValidators.healthChecksInterval,
    AppFormValidators.healthChecksTimeout,
    AppFormValidators.healthChecksMaxConsecutiveFailures
  ],
  "instances": [AppFormValidators.instances],
  "labels": [AppFormValidators.labels],
  "mem": [AppFormValidators.mem],
  "ports": [AppFormValidators.ports]
};

/**
 * Translation of fieldId to the application model key.
 *
 * fieldIds not listed here are not set in the model.
 */
const resolveFieldIdToAppKeyMap = {
  appId: "id",
  acceptedResourceRoles: "acceptedResourceRoles",
  cmd: "cmd",
  constraints: "constraints",
  containerVolumes: "container.volumes",
  cpus: "cpus",
  disk: "disk",
  dockerImage: "container.docker.image",
  dockerNetwork: "container.docker.network",
  dockerParameters: "container.docker.parameters",
  dockerPortMappings: "container.docker.portMappings",
  dockerPrivileged: "container.docker.privileged",
  healthChecks: "healthChecks",
  instances: "instances",
  env: "env",
  executor: "executor",
  labels: "labels",
  mem: "mem",
  ports: "ports",
  uris: "uris",
  user: "user"
};

/**
 * Translation map for server-side validation error responses.
 *
 * Resolves an attribute/path to the corresponding form fieldId.
 */
const responseAttributePathToFieldIdMap = {
  "id": "appId",
  "/id": "appId",
  "/acceptedResourceRoles": "acceptedResourceRoles",
  "/cmd": "cmd",
  "/constraints": "constraints",
  "/container/docker/image": "dockerImage",
  "/container/docker/network": "dockerNetwork",
  "/container/docker/privileged": "dockerPrivileged",
  "/container/docker/parameters({INDEX})/key":
    "dockerParameters.{INDEX}.key",
  "/container/docker/parameters({INDEX})/value":
    "dockerParameters.{INDEX}.value",
  "/container/docker/portMappings({INDEX})/containerPort":
    "dockerPortMappings.{INDEX}.containerPort",
  "/container/docker/portMappings({INDEX})/hostPort":
    "dockerPortMappings.{INDEX}.hostPort",
  "/container/docker/portMappings({INDEX})/servicePort":
    "dockerPortMappings.{INDEX}.servicePort",
  "/container/docker/portMappings({INDEX})/protocol":
    "dockerPortMappings.{INDEX}.protocol",
  "/container/volumes({INDEX})/containerPath":
    "containerVolumes.{INDEX}.containerPath",
  "/container/volumes({INDEX})/hostPath":
    "containerVolumes.{INDEX}.hostPath",
  "/container/volumes({INDEX})/mode":
    "containerVolumes.{INDEX}.mode",
  "/cpus": "cpus",
  "/disk": "disk",
  "/env": "env",
  "/executor": "executor",
  "/healthChecks({INDEX})/command/value":
    "healthChecks.{INDEX}.command",
  "/healthChecks({INDEX})/path":
    "healthChecks.{INDEX}.path",
  "/healthChecks({INDEX})/intervalSeconds":
    "healthChecks.{INDEX}.intervalSeconds",
  "/healthChecks({INDEX})/portIndex":
    "healthChecks.{INDEX}.portIndex",
  "/healthChecks({INDEX})/timeoutSeconds":
    "healthChecks.{INDEX}.timeoutSeconds",
  "/healthChecks({INDEX})/gracePeriodSeconds":
    "healthChecks.{INDEX}.gracePeriodSeconds",
  "/healthChecks({INDEX})/maxConsecutiveFailures":
    "healthChecks.{INDEX}.maxConsecutiveFailures",
  "/instances": "instances",
  "/mem": "mem",
  "/labels": "labels",
  "/ports": "ports",
  "/uris": "uris",
  "/user": "user"
};

/**
 * Translation of a model key to fieldId.
 *
 * Not listed keys are taken as they are.
 */
const resolveAppKeyToFieldIdMap = {
  id: "appId",
  "container.docker.image": "dockerImage",
  "container.docker.network": "dockerNetwork",
  "container.docker.portMappings": "dockerPortMappings",
  "container.docker.parameters": "dockerParameters",
  "container.docker.privileged": "dockerPrivileged",
  "container.volumes": "containerVolumes",
  "healthChecks": "healthChecks"
};

function getValidationErrorIndex(fieldId, value) {
  if (validationRules[fieldId] == null) {
    return -1;
  }
  return validationRules[fieldId].findIndex((isValid) => !isValid(value));
}

function deleteErrorIndices(errorIndices, fieldId, consecutiveKey) {
  if (errorIndices[fieldId] && consecutiveKey != null) {
    delete errorIndices[fieldId][consecutiveKey];
    if (Object.keys(errorIndices[fieldId]).length === 0) {
      delete errorIndices[fieldId];
    }
  } else {
    delete errorIndices[fieldId];
  }
}

function rebuildModelFromFields(app, fields, fieldId) {
  const key = resolveFieldIdToAppKeyMap[fieldId];
  if (key) {
    const transform = AppFormTransforms.FieldToModel[fieldId];
    if (transform == null) {
      Util.objectPathSet(app, key, fields[fieldId]);
    } else {
      Util.objectPathSet(app, key, transform(fields[fieldId]));
    }
  }

  Object.keys(app).forEach((appKey) => {
    var postProcessor = AppFormModelPostProcess[appKey];
    if (postProcessor != null) {
      postProcessor(app);
    }
  });
}

function resolveResponseAttributePathToFieldId(attributePath) {
  var fieldId;
  // Check if attributePath contains an index like path(0)/attribute
  // Matches as defined: [0] : "(0)", [1]: "0"
  var matches = attributePath.match(/\(([0-9]+)\)/);
  if (matches != null) {
    let resolvePath = responseAttributePathToFieldIdMap[
      attributePath.replace(matches[0], "({INDEX})")
    ];
    if (resolvePath != null) {
      fieldId = resolvePath.replace("{INDEX}", matches[1]);
    }
  } else {
    fieldId = responseAttributePathToFieldIdMap[attributePath];
  }
  return fieldId;
}

function populateFieldsFromModel(app, fields) {
  // The env/labels-object should be treated as an object itself,
  // so it's excluded.
  var paths = Util.detectObjectPaths(app, null, ["env", "labels"]);

  paths.forEach((appKey) => {
    var fieldId = resolveAppKeyToFieldIdMap[appKey];
    if (fieldId == null) {
      fieldId = appKey;
    }
    const transform = AppFormTransforms.ModelToField[fieldId];
    if (transform == null) {
      fields[fieldId] = objectPath.get(app, appKey);
    } else {
      fields[fieldId] = transform(objectPath.get(app, appKey));
    }
  });
}

function insertField(fields, fieldId, index = null, value) {
  if (duplicableRowFields.indexOf(fieldId) !== -1) {
    Util.initKeyValue(fields, fieldId, []);
    if (index == null) {
      fields[fieldId].push(value);
    } else {
      fields[fieldId].splice(index, 0, value);
    }
  }
}

function updateField(fields, fieldId, index = null, value) {
  if (duplicableRowFields.indexOf(fieldId) !== -1) {
    Util.initKeyValue(fields, fieldId, []);
    fields[fieldId][index] = value;
  } else {
    fields[fieldId] = value;
  }
}

function deleteField(fields, fieldId, index) {
  if (duplicableRowFields.indexOf(fieldId) !== -1) {
    fields[fieldId].splice(index, 1);
  }
}

function processResponseErrors(responseErrors, response, statusCode) {
  if (statusCode >= 500) {
    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("unknownServerError");

  } else if (statusCode === 422 && response != null &&
      Util.isArray(response.errors)) {

    response.errors.forEach((error) => {
      var attributePath = error.attribute.length
        ? error.attribute
        : "general";
      var fieldId = resolveResponseAttributePathToFieldId(attributePath) ||
        attributePath;
      responseErrors[fieldId] =
        AppFormErrorMessages.lookupServerResponseMessage(error.error);
    });

  } else if (statusCode === 409 && response != null &&
      response.message != null) {

    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("errorPrefix") + " " +
      response.message;

  } else if (statusCode === 403 && response != null &&
      response.message != null) {

    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("forbiddenAccess");

  } else if (statusCode === 401 && response != null &&
      response.message != null) {

    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("unauthorizedAccess");

  } else if (statusCode === 400 && response != null &&
      Util.isArray(response.details)) {

    response.details.forEach((detail) => {
      var attributePath = detail.path.length
        ? detail.path
        : "general";
      var fieldId = resolveResponseAttributePathToFieldId(attributePath) ||
        attributePath;
      responseErrors[fieldId] = detail.errors.map((error) => {
        return AppFormErrorMessages.lookupServerResponseMessage(error);
      }).join(", ");
    });

  } else if (statusCode >= 300) {
    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("appCreation");
  }
}

var AppFormStore = lazy(EventEmitter.prototype).extend({
  app: {},
  fields: {},
  responseErrors: {},
  validationErrorIndices: {},
  initAndReset: function () {
    this.app = {};
    this.fields = {};
    this.validationErrorIndices = {};

    Object.keys(defaultFieldValues).forEach((fieldId) => {
      this.fields[fieldId] = defaultFieldValues[fieldId];
      rebuildModelFromFields(this.app, this.fields, fieldId);
    });
  },
  populateFieldsFromAppDefinition: function (app) {
    this.app = app;
    populateFieldsFromModel(app, this.fields);
  }
}).value();

function executeAction(action, setFieldFunction) {
  var actionType = action.actionType;
  var fieldId = action.fieldId;
  var value = action.value;
  var index = action.index;
  var errorIndices = AppFormStore.validationErrorIndices;
  var errorIndex = -1;

  if (actionType === FormEvents.INSERT || actionType === FormEvents.UPDATE) {
    errorIndex = getValidationErrorIndex(fieldId, value);

    if (errorIndex > -1) {
      if (value.consecutiveKey != null) {
        Util.initKeyValue(errorIndices, fieldId, []);
        errorIndices[fieldId][value.consecutiveKey] = errorIndex;
      } else {
        errorIndices[fieldId] = errorIndex;
      }
    } else {
      deleteErrorIndices(errorIndices, fieldId, value.consecutiveKey);
    }
  } else if (actionType === FormEvents.DELETE ) {
    deleteErrorIndices(errorIndices, fieldId, value.consecutiveKey);
  }

  setFieldFunction(AppFormStore.fields, fieldId, index, value);

  if (errorIndex === -1) {
    rebuildModelFromFields(AppFormStore.app, AppFormStore.fields, fieldId);
    AppFormStore.emit(FormEvents.CHANGE, fieldId);
  } else {
    AppFormStore.emit(FormEvents.FIELD_VALIDATION_ERROR);
  }
}

function onAppsErrorResponse(response, statusCode) {
  AppFormStore.responseErrors = {};
  processResponseErrors(AppFormStore.responseErrors, response, statusCode);
}

AppsStore.on(AppsEvents.CREATE_APP_ERROR, function (data, status) {
  onAppsErrorResponse(data, status);
});
AppsStore.on(AppsEvents.APPLY_APP_ERROR, function (data, isEditing, status) {
  onAppsErrorResponse(data, status);
});
AppsStore.on(AppsEvents.CREATE_APP, function () {
  AppFormStore.responseErrors = {};
});
AppsStore.on(AppsEvents.APPLY_APP, function () {
  AppFormStore.responseErrors = {};
});

AppDispatcher.register(function (action) {
  switch (action.actionType) {
    case FormEvents.INSERT:
      executeAction(action, insertField);
      break;
    case FormEvents.UPDATE:
      executeAction(action, updateField);
      break;
    case FormEvents.DELETE:
      executeAction(action, deleteField);
      break;
  }
});

module.exports = AppFormStore;
<commit_msg>Map apps-attribute on according form field<commit_after>var EventEmitter = require("events").EventEmitter;
var lazy = require("lazy.js");
var objectPath = require("object-path");
var Util = require("../helpers/Util");

var AppDispatcher = require("../AppDispatcher");
var AppFormErrorMessages = require("../constants/AppFormErrorMessages");
var AppFormTransforms = require("./transforms/AppFormTransforms");
var AppFormModelPostProcess = require("./transforms/AppFormModelPostProcess");
var AppFormValidators = require("./validators/AppFormValidators");
var AppsStore = require("./AppsStore");
var AppsEvents = require("../events/AppsEvents");
var FormEvents = require("../events/FormEvents");

const defaultFieldValues = Object.freeze({
  cpus: 0.1,
  mem: 16,
  disk: 0,
  instances: 1
});

const duplicableRowFields = [
  "containerVolumes",
  "dockerPortMappings",
  "dockerParameters",
  "env",
  "healthChecks",
  "labels"
];

/**
 * Validation rules for individual fields and fieldsets (duplicable rows).
 * The array index of the rule is related to the error message index
 * in AppFormErrorMessages.
 *
 * fieldIds not listed here are considered valid by default.
 */
const validationRules = {
  "appId": [
    AppFormValidators.appIdNotEmpty,
    AppFormValidators.appIdNoWhitespaces,
    AppFormValidators.appIdValidChars,
    AppFormValidators.appIdWellFormedPath
  ],
  "constraints": [AppFormValidators.constraints],
  "containerVolumes": [
    AppFormValidators.containerVolumesContainerPathIsValid,
    AppFormValidators.containerVolumesHostPathIsValid,
    AppFormValidators.containerVolumesModeNotEmpty
  ],
  "cpus": [AppFormValidators.cpus],
  "disk": [AppFormValidators.disk],
  "dockerImage": [AppFormValidators.dockerImageNoWhitespaces],
  "dockerParameters": [AppFormValidators.dockerParameters],
  "dockerPortMappings": [
    AppFormValidators.dockerPortMappingsContainerPortIsValid,
    AppFormValidators.dockerPortMappingsHostPortIsValid,
    AppFormValidators.dockerPortMappingsServicePortIsValid,
    AppFormValidators.dockerPortMappingsProtocolValidType
  ],
  "env": [AppFormValidators.env],
  "executor": [AppFormValidators.executor],
  "healthChecks": [
    AppFormValidators.healthChecksProtocol,
    AppFormValidators.healthChecksCommandNotEmpty,
    AppFormValidators.healthChecksPathNotEmpty,
    AppFormValidators.healthChecksPortIndex,
    AppFormValidators.healthChecksGracePeriod,
    AppFormValidators.healthChecksInterval,
    AppFormValidators.healthChecksTimeout,
    AppFormValidators.healthChecksMaxConsecutiveFailures
  ],
  "instances": [AppFormValidators.instances],
  "labels": [AppFormValidators.labels],
  "mem": [AppFormValidators.mem],
  "ports": [AppFormValidators.ports]
};

/**
 * Translation of fieldId to the application model key.
 *
 * fieldIds not listed here are not set in the model.
 */
const resolveFieldIdToAppKeyMap = {
  appId: "id",
  acceptedResourceRoles: "acceptedResourceRoles",
  cmd: "cmd",
  constraints: "constraints",
  containerVolumes: "container.volumes",
  cpus: "cpus",
  disk: "disk",
  dockerImage: "container.docker.image",
  dockerNetwork: "container.docker.network",
  dockerParameters: "container.docker.parameters",
  dockerPortMappings: "container.docker.portMappings",
  dockerPrivileged: "container.docker.privileged",
  healthChecks: "healthChecks",
  instances: "instances",
  env: "env",
  executor: "executor",
  labels: "labels",
  mem: "mem",
  ports: "ports",
  uris: "uris",
  user: "user"
};

/**
 * Translation map for server-side validation error responses.
 *
 * Resolves an attribute/path to the corresponding form fieldId.
 */
const responseAttributePathToFieldIdMap = {
  "id": "appId",
  "apps": "appId",
  "/id": "appId",
  "/acceptedResourceRoles": "acceptedResourceRoles",
  "/cmd": "cmd",
  "/constraints": "constraints",
  "/container/docker/image": "dockerImage",
  "/container/docker/network": "dockerNetwork",
  "/container/docker/privileged": "dockerPrivileged",
  "/container/docker/parameters({INDEX})/key":
    "dockerParameters.{INDEX}.key",
  "/container/docker/parameters({INDEX})/value":
    "dockerParameters.{INDEX}.value",
  "/container/docker/portMappings({INDEX})/containerPort":
    "dockerPortMappings.{INDEX}.containerPort",
  "/container/docker/portMappings({INDEX})/hostPort":
    "dockerPortMappings.{INDEX}.hostPort",
  "/container/docker/portMappings({INDEX})/servicePort":
    "dockerPortMappings.{INDEX}.servicePort",
  "/container/docker/portMappings({INDEX})/protocol":
    "dockerPortMappings.{INDEX}.protocol",
  "/container/volumes({INDEX})/containerPath":
    "containerVolumes.{INDEX}.containerPath",
  "/container/volumes({INDEX})/hostPath":
    "containerVolumes.{INDEX}.hostPath",
  "/container/volumes({INDEX})/mode":
    "containerVolumes.{INDEX}.mode",
  "/cpus": "cpus",
  "/disk": "disk",
  "/env": "env",
  "/executor": "executor",
  "/healthChecks({INDEX})/command/value":
    "healthChecks.{INDEX}.command",
  "/healthChecks({INDEX})/path":
    "healthChecks.{INDEX}.path",
  "/healthChecks({INDEX})/intervalSeconds":
    "healthChecks.{INDEX}.intervalSeconds",
  "/healthChecks({INDEX})/portIndex":
    "healthChecks.{INDEX}.portIndex",
  "/healthChecks({INDEX})/timeoutSeconds":
    "healthChecks.{INDEX}.timeoutSeconds",
  "/healthChecks({INDEX})/gracePeriodSeconds":
    "healthChecks.{INDEX}.gracePeriodSeconds",
  "/healthChecks({INDEX})/maxConsecutiveFailures":
    "healthChecks.{INDEX}.maxConsecutiveFailures",
  "/instances": "instances",
  "/mem": "mem",
  "/labels": "labels",
  "/ports": "ports",
  "/uris": "uris",
  "/user": "user"
};

/**
 * Translation of a model key to fieldId.
 *
 * Not listed keys are taken as they are.
 */
const resolveAppKeyToFieldIdMap = {
  id: "appId",
  "container.docker.image": "dockerImage",
  "container.docker.network": "dockerNetwork",
  "container.docker.portMappings": "dockerPortMappings",
  "container.docker.parameters": "dockerParameters",
  "container.docker.privileged": "dockerPrivileged",
  "container.volumes": "containerVolumes",
  "healthChecks": "healthChecks"
};

function getValidationErrorIndex(fieldId, value) {
  if (validationRules[fieldId] == null) {
    return -1;
  }
  return validationRules[fieldId].findIndex((isValid) => !isValid(value));
}

function deleteErrorIndices(errorIndices, fieldId, consecutiveKey) {
  if (errorIndices[fieldId] && consecutiveKey != null) {
    delete errorIndices[fieldId][consecutiveKey];
    if (Object.keys(errorIndices[fieldId]).length === 0) {
      delete errorIndices[fieldId];
    }
  } else {
    delete errorIndices[fieldId];
  }
}

function rebuildModelFromFields(app, fields, fieldId) {
  const key = resolveFieldIdToAppKeyMap[fieldId];
  if (key) {
    const transform = AppFormTransforms.FieldToModel[fieldId];
    if (transform == null) {
      Util.objectPathSet(app, key, fields[fieldId]);
    } else {
      Util.objectPathSet(app, key, transform(fields[fieldId]));
    }
  }

  Object.keys(app).forEach((appKey) => {
    var postProcessor = AppFormModelPostProcess[appKey];
    if (postProcessor != null) {
      postProcessor(app);
    }
  });
}

function resolveResponseAttributePathToFieldId(attributePath) {
  var fieldId;
  // Check if attributePath contains an index like path(0)/attribute
  // Matches as defined: [0] : "(0)", [1]: "0"
  var matches = attributePath.match(/\(([0-9]+)\)/);
  if (matches != null) {
    let resolvePath = responseAttributePathToFieldIdMap[
      attributePath.replace(matches[0], "({INDEX})")
    ];
    if (resolvePath != null) {
      fieldId = resolvePath.replace("{INDEX}", matches[1]);
    }
  } else {
    fieldId = responseAttributePathToFieldIdMap[attributePath];
  }
  return fieldId;
}

function populateFieldsFromModel(app, fields) {
  // The env/labels-object should be treated as an object itself,
  // so it's excluded.
  var paths = Util.detectObjectPaths(app, null, ["env", "labels"]);

  paths.forEach((appKey) => {
    var fieldId = resolveAppKeyToFieldIdMap[appKey];
    if (fieldId == null) {
      fieldId = appKey;
    }
    const transform = AppFormTransforms.ModelToField[fieldId];
    if (transform == null) {
      fields[fieldId] = objectPath.get(app, appKey);
    } else {
      fields[fieldId] = transform(objectPath.get(app, appKey));
    }
  });
}

function insertField(fields, fieldId, index = null, value) {
  if (duplicableRowFields.indexOf(fieldId) !== -1) {
    Util.initKeyValue(fields, fieldId, []);
    if (index == null) {
      fields[fieldId].push(value);
    } else {
      fields[fieldId].splice(index, 0, value);
    }
  }
}

function updateField(fields, fieldId, index = null, value) {
  if (duplicableRowFields.indexOf(fieldId) !== -1) {
    Util.initKeyValue(fields, fieldId, []);
    fields[fieldId][index] = value;
  } else {
    fields[fieldId] = value;
  }
}

function deleteField(fields, fieldId, index) {
  if (duplicableRowFields.indexOf(fieldId) !== -1) {
    fields[fieldId].splice(index, 1);
  }
}

function processResponseErrors(responseErrors, response, statusCode) {
  if (statusCode >= 500) {
    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("unknownServerError");

  } else if (statusCode === 422 && response != null &&
      Util.isArray(response.errors)) {

    response.errors.forEach((error) => {
      var attributePath = error.attribute.length
        ? error.attribute
        : "general";
      var fieldId = resolveResponseAttributePathToFieldId(attributePath) ||
        attributePath;
      responseErrors[fieldId] =
        AppFormErrorMessages.lookupServerResponseMessage(error.error);
    });

  } else if (statusCode === 409 && response != null &&
      response.message != null) {

    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("errorPrefix") + " " +
      response.message;

  } else if (statusCode === 403 && response != null &&
      response.message != null) {

    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("forbiddenAccess");

  } else if (statusCode === 401 && response != null &&
      response.message != null) {

    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("unauthorizedAccess");

  } else if (statusCode === 400 && response != null &&
      Util.isArray(response.details)) {

    response.details.forEach((detail) => {
      var attributePath = detail.path.length
        ? detail.path
        : "general";
      var fieldId = resolveResponseAttributePathToFieldId(attributePath) ||
        attributePath;
      responseErrors[fieldId] = detail.errors.map((error) => {
        return AppFormErrorMessages.lookupServerResponseMessage(error);
      }).join(", ");
    });

  } else if (statusCode >= 300) {
    responseErrors.general =
      AppFormErrorMessages.getGeneralMessage("appCreation");
  }
}

var AppFormStore = lazy(EventEmitter.prototype).extend({
  app: {},
  fields: {},
  responseErrors: {},
  validationErrorIndices: {},
  initAndReset: function () {
    this.app = {};
    this.fields = {};
    this.validationErrorIndices = {};

    Object.keys(defaultFieldValues).forEach((fieldId) => {
      this.fields[fieldId] = defaultFieldValues[fieldId];
      rebuildModelFromFields(this.app, this.fields, fieldId);
    });
  },
  populateFieldsFromAppDefinition: function (app) {
    this.app = app;
    populateFieldsFromModel(app, this.fields);
  }
}).value();

function executeAction(action, setFieldFunction) {
  var actionType = action.actionType;
  var fieldId = action.fieldId;
  var value = action.value;
  var index = action.index;
  var errorIndices = AppFormStore.validationErrorIndices;
  var errorIndex = -1;

  if (actionType === FormEvents.INSERT || actionType === FormEvents.UPDATE) {
    errorIndex = getValidationErrorIndex(fieldId, value);

    if (errorIndex > -1) {
      if (value.consecutiveKey != null) {
        Util.initKeyValue(errorIndices, fieldId, []);
        errorIndices[fieldId][value.consecutiveKey] = errorIndex;
      } else {
        errorIndices[fieldId] = errorIndex;
      }
    } else {
      deleteErrorIndices(errorIndices, fieldId, value.consecutiveKey);
    }
  } else if (actionType === FormEvents.DELETE ) {
    deleteErrorIndices(errorIndices, fieldId, value.consecutiveKey);
  }

  setFieldFunction(AppFormStore.fields, fieldId, index, value);

  if (errorIndex === -1) {
    rebuildModelFromFields(AppFormStore.app, AppFormStore.fields, fieldId);
    AppFormStore.emit(FormEvents.CHANGE, fieldId);
  } else {
    AppFormStore.emit(FormEvents.FIELD_VALIDATION_ERROR);
  }
}

function onAppsErrorResponse(response, statusCode) {
  AppFormStore.responseErrors = {};
  processResponseErrors(AppFormStore.responseErrors, response, statusCode);
}

AppsStore.on(AppsEvents.CREATE_APP_ERROR, function (data, status) {
  onAppsErrorResponse(data, status);
});
AppsStore.on(AppsEvents.APPLY_APP_ERROR, function (data, isEditing, status) {
  onAppsErrorResponse(data, status);
});
AppsStore.on(AppsEvents.CREATE_APP, function () {
  AppFormStore.responseErrors = {};
});
AppsStore.on(AppsEvents.APPLY_APP, function () {
  AppFormStore.responseErrors = {};
});

AppDispatcher.register(function (action) {
  switch (action.actionType) {
    case FormEvents.INSERT:
      executeAction(action, insertField);
      break;
    case FormEvents.UPDATE:
      executeAction(action, updateField);
      break;
    case FormEvents.DELETE:
      executeAction(action, deleteField);
      break;
  }
});

module.exports = AppFormStore;
<|endoftext|>


<commit_before>"use strict";

let express = require('express'),
	cookieParser = require('cookie-parser'),
    mUrl = require('url'),
    http = require('http'),
    monads = require('./monads.js'),
    CSteamCommunity = require('steamcommunity');

let SteamCommunity = new CSteamCommunity();

let opportunisticProcessing = function(options, callback) {
	let E = new monads.ErrorMonad()
	let instructions = [E.try('processing')];
	for (const operation of options) {
		instructions.push(operation);
		instructions.push(E.retry('processing'));
	}
	instructions.pop();
	instructions.push(callback);
	return E.do(...instructions);
};

let mutateInput = (mutate, fun) => function(err, string, cb) {
	try {fun(err, mutate(string), cb)} catch(error) {cb(error)};
};

let toSteamId = (string) => new CSteamCommunity.SteamID(string);

let toSteamUser = function(err, id, cb) {
	if (err) {
		cb(err);
		return;
	}
	if (!id) {
		cb('Empty input provided');
		return;
	}
    SteamCommunity.getSteamUser(id, cb);
};

let nameOutput = (name, fun) => (err, string, rawCb) => fun(err, string, (error, result) => rawCb(error, {'type':name, 'value' : result}));

let isEvenString = (string) => parseInt(string.slice(-1)) % 2;
let onlyIfNumeric = (fun=(x)=>x) => function(data) {
	if(parseInt(data)) {
		return fun(data);
	} else {
		throw `Expected numeric input, got ${data}`;
	}
};

let urlToSteamId = function (url) {
	let dissected = mUrl.parse(url);
	if(dissected.hostname == 'steamcommunity.com') // may or may not start with 'http://'
	{
		let pathArray = dissected.pathname.split('/');
		let trail = pathArray.pop();
		return (trail == '' ? pathArray.pop() : trail); // may or may not end with trailing slash
	}
	else { return null; }
};

let methods = {
	'asId64'	: nameOutput('id64', mutateInput(onlyIfNumeric(), toSteamUser)),
	'asId3Tail'	: nameOutput('id3', mutateInput(
		onlyIfNumeric((string) => toSteamId(`[U:1:${string}]`)),
		toSteamUser
	)),
	'asOldTail'	: nameOutput('old', mutateInput(
		onlyIfNumeric((string) => toSteamId(`STEAM_0:${isEvenString(string)}:${string}`)),
		toSteamUser
	)),
	'asValidId'	: nameOutput('valid', toSteamUser),
	'asUrl'		: nameOutput('url', mutateInput(urlToSteamId, toSteamUser))
};

let stringToSteamId = function(string, cb) {
	let methodsToTry = ['asId64', 'asId3Tail', 'asOldTail', 'asValidId', 'asUrl'].map((name) => methods[name]);
	opportunisticProcessing(methodsToTry, cb)(string);
}

const tests = {
    'steamID' : 'STEAM_0:0:61441014',
    'steamID3' : '[U:1:122882028]',
    'steamID64' : '76561198083147756',
    'customURL' : 'daerdemandt',
    'name' : 'Daerdemandt',
    'profile' : 'http://steamcommunity.com/profiles/76561198083147756'
};

let app = express();

function checkOddnessOutputInt (input) {
	let tailNumber = +input.split('').pop(); // WAAAAAAAAGH
	let isEven = (tailNumber === parseFloat(tailNumber) ? !(tailNumber % 2) : void 0); // boolean!
	return isEven ? '0' : '1';
}
let stringToSteamIdOld = function(string, cb) {
    const notFound = 'Error: The specified profile could not be found.';
    let tryAsId = function (string, cb) {
        try {
            let id = new CSteamCommunity.SteamID(string);
            SteamCommunity.getSteamUser(id, cb);
        } catch(error) {
            if (error.stack.startsWith('Error: SteamID must stand for an individual account in the public')) {
                cb(null, null); // not found
            } else if (error.stack.startsWith('Error: Unknown SteamID input format')) {
                cb('Unsupported format, but we are working on it'); //TODO: support URLs
            } else {
                cb(error);
            }
        };
    };

    SteamCommunity.getSteamUser(string, function(err, result) {
        if (!err) {
            cb(null, result);
        } else {
            if (err.stack.startsWith(notFound)) {
                let idParity = checkOddnessOutputInt(string);
		let queryMethodsArray = []; // decide if a particular query is sane, fill array up, then pass it to worker
		if (parseInt(string)) {

                    queryMethodsArray.push('STEAM_0:' + idParity + ':' + string);
		    queryMethodsArray.push(string);
                    if(Number.isSafeInteger(parseInt(string))) {
			queryMethodsArray.push('[U:1:' + string + ']');
		    }
		    queryMethodsArray.reverse();
                    tryUntilResult(queryMethodsArray, tryAsId, cb, null); // looks like v3 is the main priority
                } else // assuming URL or (exotic SOB!) uniform SteamID
		{
		    let asURLTrail = urlToSteamId(string);
		    if(parseInt(asURLTrail)) { // is a URL, also appearing to end in id64
			tryAsId(asURLTrail, cb); // assume community/profiles/id64 url template, operate
		    }
		    else { // uniform SteamID or a URL appearing to end in customURL
		    	   if (mUrl.parse(string).hostname == 'steamcommunity.com') { // can distinguish vaild hostname, MUST be a URL
			    	SteamCommunity.getSteamUser(asURLTrail, function(final_error, result){
				if(!final_error) {
					cb(null, result); // assume community/id/customID url template, operate
				} else {
					cb(final_error); // we support no more input formats for now. Pass error down.
				}

			});} else { // most definitely a uniform ID, if not, well, we can always pretend nothing happened.
				tryAsId(string, cb);
			}

		    }
		}
            }
        }
    });

};
///*
let tryUntilResult = function(items, process, successCallback, stubData) {
    if (0 == items.length) {
        successCallback(stubData);
    } else {
        let [current, rest] = [items[0], items.slice(1)];
        process(current, function(err, data) {
            if (err || data) {
                successCallback(err, data);
            } else { // no errors, but we need to try other options
                tryUntilResult(rest, process, successCallback, stubData);
            }
        });
    }
}
//*/
app.get('/api/arbitraryStringToSteamId', function(req, res, next) {
    let ret = function(error, data) {
        if (error) {
            res.status(500).send({'error' : error.stack})
        } else if (!data) {
            res.status(404).send({'error' : 'not found'});
        } else {
			console.log(data.type);
			data = data.value;
		let theID = data.steamID;
            res.send({
                'name' : data.name,
                'steamId64' : theID.toString(),
		'steam32AccountId' : theID.accountid,
		'steamId32' : theID.getSteam3RenderedID(),
		'steam2Old' : theID.getSteam2RenderedID(),
		'steam2New' : theID.getSteam2RenderedID(true),
                'customURL' : data.customURL,
		'profileURL' : 'http://steamcommunity.com/profiles/' + theID.toString(),
		'isGroupchat' : theID.isGroupChat(),
		'isSteamLobby' : theID.isLobby(),
                'memberSince' : data.memberSince,
                'isOnline' : data.onlineState
            }); //TODO: more fields here
        }
    };
    stringToSteamId(decodeURIComponent(req.query.string.trim()), ret);
});

app.get('/', function(req, res, next) {
    res.sendFile( '/static/' + 'index.html');
});

function processConvertQuery(request, response)
{
	response.status(501).send("STUB!");
}

app.post('/api/convert', processConvertQuery);

http.createServer(app).listen(process.env.PORT || 8080, function() {
    console.log('Listening on port ' + (process.env.PORT || 8080));
});
<commit_msg>Remove old code<commit_after>"use strict";

let express = require('express'),
	cookieParser = require('cookie-parser'),
    mUrl = require('url'),
    http = require('http'),
    monads = require('./monads.js'),
    CSteamCommunity = require('steamcommunity');

let SteamCommunity = new CSteamCommunity();

let opportunisticProcessing = function(options, callback) {
	let E = new monads.ErrorMonad()
	let instructions = [E.try('processing')];
	for (const operation of options) {
		instructions.push(operation);
		instructions.push(E.retry('processing'));
	}
	instructions.pop();
	instructions.push(callback);
	return E.do(...instructions);
};

let mutateInput = (mutate, fun) => function(err, string, cb) {
	try {fun(err, mutate(string), cb)} catch(error) {cb(error)};
};

let toSteamId = (string) => new CSteamCommunity.SteamID(string);

let toSteamUser = function(err, id, cb) {
	if (err) {
		cb(err);
		return;
	}
	if (!id) {
		cb('Empty input provided');
		return;
	}
    SteamCommunity.getSteamUser(id, cb);
};

let nameOutput = (name, fun) => (err, string, rawCb) => fun(err, string, (error, result) => rawCb(error, {'type':name, 'value' : result}));

let isEvenString = (string) => parseInt(string.slice(-1)) % 2;
let onlyIfNumeric = (fun=(x)=>x) => function(data) {
	if(parseInt(data)) {
		return fun(data);
	} else {
		throw `Expected numeric input, got ${data}`;
	}
};

let urlToSteamId = function (url) {
	let dissected = mUrl.parse(url);
	if(dissected.hostname == 'steamcommunity.com') // may or may not start with 'http://'
	{
		let pathArray = dissected.pathname.split('/');
		let trail = pathArray.pop();
		return (trail == '' ? pathArray.pop() : trail); // may or may not end with trailing slash
	}
	else { return null; }
};

let methods = {
	'asId64'	: nameOutput('id64', mutateInput(onlyIfNumeric(), toSteamUser)),
	'asId3Tail'	: nameOutput('id3', mutateInput(
		onlyIfNumeric((string) => toSteamId(`[U:1:${string}]`)),
		toSteamUser
	)),
	'asOldTail'	: nameOutput('old', mutateInput(
		onlyIfNumeric((string) => toSteamId(`STEAM_0:${isEvenString(string)}:${string}`)),
		toSteamUser
	)),
	'asValidId'	: nameOutput('valid', toSteamUser),
	'asUrl'		: nameOutput('url', mutateInput(urlToSteamId, toSteamUser))
};

let stringToSteamId = function(string, cb) {
	let methodsToTry = ['asId64', 'asId3Tail', 'asOldTail', 'asValidId', 'asUrl'].map((name) => methods[name]);
	opportunisticProcessing(methodsToTry, cb)(string);
}

const tests = {
    'steamID' : 'STEAM_0:0:61441014',
    'steamID3' : '[U:1:122882028]',
    'steamID64' : '76561198083147756',
    'customURL' : 'daerdemandt',
    'name' : 'Daerdemandt',
    'profile' : 'http://steamcommunity.com/profiles/76561198083147756'
};

let app = express();

///*
//TODO: implement opportunistingProcessing with something like this:
let tryUntilResult = function(items, process, successCallback, stubData) {
    if (0 == items.length) {
        successCallback(stubData);
    } else {
        let [current, rest] = [items[0], items.slice(1)];
        process(current, function(err, data) {
            if (err || data) {
                successCallback(err, data);
            } else { // no errors, but we need to try other options
                tryUntilResult(rest, process, successCallback, stubData);
            }
        });
    }
}
//*/
app.get('/api/arbitraryStringToSteamId', function(req, res, next) {
    let ret = function(error, data) {
        if (error) {
            res.status(500).send({'error' : error.stack})
        } else if (!data) {
            res.status(404).send({'error' : 'not found'});
        } else {
			console.log(data.type);
			data = data.value;
		let theID = data.steamID;
            res.send({
                'name' : data.name,
                'steamId64' : theID.toString(),
		'steam32AccountId' : theID.accountid,
		'steamId32' : theID.getSteam3RenderedID(),
		'steam2Old' : theID.getSteam2RenderedID(),
		'steam2New' : theID.getSteam2RenderedID(true),
                'customURL' : data.customURL,
		'profileURL' : 'http://steamcommunity.com/profiles/' + theID.toString(),
		'isGroupchat' : theID.isGroupChat(),
		'isSteamLobby' : theID.isLobby(),
                'memberSince' : data.memberSince,
                'isOnline' : data.onlineState
            }); //TODO: more fields here
        }
    };
    stringToSteamId(decodeURIComponent(req.query.string.trim()), ret);
});

app.get('/', function(req, res, next) {
    res.sendFile( '/static/' + 'index.html');
});

function processConvertQuery(request, response)
{
	response.status(501).send("STUB!");
}

app.post('/api/convert', processConvertQuery);

http.createServer(app).listen(process.env.PORT || 8080, function() {
    console.log('Listening on port ' + (process.env.PORT || 8080));
});
<|endoftext|>


<commit_before>$(function() {
  // Initialize lunr with the fields to be searched, plus the boost.
  window.idx = lunr(function () {
    this.field('id');
    this.field('postHeading');
    this.field('subHeading');
    this.field('content', { boost: 10 });
    this.field('date');
    this.field('tags');
    this.field('image');
  });

  // Get the generated search_data.json file so lunr.js can search it locally.
  window.data = $.getJSON('/search-data.json');

  // Wait for the data to load and add it to lunr
  window.data.then(function(loaded_data){
    $.each(loaded_data, function(index, value){
      window.idx.add(
        $.extend({ "id": index }, value)
      );
    });
  });

  // Event when the form is submitted
  $("#site_search").submit(function(event){
      event.preventDefault();
      var query = $("#search_box").val(); // Get the value from the search field
      var results = window.idx.search(query); // Get lunr to perform a search
      display_search_results(results); // Hand the results off to be displayed
  });

  function display_search_results(results) {
    // Wait for data to load
    window.data.then(function(loaded_data) {
      // Are there any results?
      if (results.length) {
		// Clear any old results
        $("#search_results").empty();
		// Hide blog entries
		$("#entries").hide();
        // Iterate over the results
        results.forEach(function(result,i) {
          var item = loaded_data[result.ref];
		  // Build a snippet of HTML for this result, add loop index
		  build_html(i, item.url, item.postHeading, item.subHeading, item.date, item.tags.split(', '));
        });
		// Create load more button
		build_load_more_button();
      } else {
        // If there are no results, let the user know.
		$("#no-results").css('display', 'block');
      }
    });
  }

  function build_html(index, url, heading, subHeading, date, tags)
  {
	  var heading_ = document.createElement("h3");
	  heading_.innerHTML = heading;

	  var subHeading_ = document.createElement("h5");
	  subHeading_.innerHTML = subHeading;

	  var date_ = document.createElement("span");
	  date_.setAttribute('class', 'w3-opacity');
	  date_.innerHTML = date;
	  var date__ = document.createElement("h5");
	  date__.appendChild(date_);

	  var tags__ = document.createElement("h5");
	  tags__.innerHTML = "Tags: "
	  for(var i=0; i<tags.length; i++)
	  {
		  var tag = tags[i];
		  var tagTitle = 'View posts tagged with "' + tag + '"';
		  var tagUrl = '/tag/' + tag;
		  var tagUrl_ = document.createElement("a");
		  tagUrl_.setAttribute('href', tagUrl);
		  tagUrl_.setAttribute('title', tagTitle);
		  tagUrl_.innerHTML = tag;
		  var tag_ = document.createElement("span");
		  tag_.setAttribute('class', 'w3-tag w3-black w3-margin-bottom');
		  tag_.appendChild(tagUrl_);
		  tags__.appendChild(tag_);
		  tags__.innerHTML += '\xa0';
	  }

	  var urlText = document.createElement("b");
	  urlText.innerHTML = "READ MORE >>";
	  var url_ = "window.location.href='" + url + "'";
	  var urlButton = document.createElement("button");
	  urlButton.setAttribute('class', 'w3-button w3-padding-large w3-white w3-border');
	  urlButton.setAttribute('onclick', url_);
	  urlButton.appendChild(urlText);
	  var url__ = document.createElement("p");
	  url__.appendChild(urlButton);

	  var postPreview = document.createElement("div");
	  postPreview.setAttribute('class', 'w3-container');
	  postPreview.appendChild(heading_);
	  postPreview.appendChild(subHeading_);
	  postPreview.appendChild(date__);
	  postPreview.appendChild(tags__);
	  postPreview.appendChild(url__);

	  var divider = document.createElement("hr");

	  var entryId = "blogEntry" + index;
	  var blogEntry = document.createElement("div");
	  blogEntry.setAttribute('id', entryId);
	  blogEntry.setAttribute('class', 'w3-card-4 w3-margin w3-white');
	  if(index > 4)
		  blogEntry.setAttribute('style', 'display:none');
	  blogEntry.appendChild(postPreview);
	  blogEntry.appendChild(divider);

	  $("#search_results").append(blogEntry);
  }

  function build_load_more_button()
  {
	var moreButton = document.createElement("button");
	moreButton.setAttribute('class', 'w3-button w3-black w3-padding-large w3-margin-bottom');
	moreButton.setAttribute('onclick', 'loadMoreEntries(this, "search_results", 6)');
	moreButton.innerHTML = "Load More";
	var moreButtonP = document.createElement("p");
	moreButtonP.setAttribute('style', 'text-align: center');
	moreButtonP.appendChild(moreButton);
	var moreButtonF = document.createElement("footer");
	moreButtonF.setAttribute('id', 'more_results');
	moreButtonF.setAttribute('class', 'w3-margin');
	moreButtonF.appendChild(moreButtonP);
	$("#search_results").append(moreButtonF);
  }

});<commit_msg>added clearing of search box and redirect to div<commit_after>$(function() {
  // Initialize lunr with the fields to be searched, plus the boost.
  window.idx = lunr(function () {
    this.field('id');
    this.field('postHeading');
    this.field('subHeading');
    this.field('content', { boost: 10 });
    this.field('date');
    this.field('tags');
    this.field('image');
  });

  // Get the generated search_data.json file so lunr.js can search it locally.
  window.data = $.getJSON('/search-data.json');

  // Wait for the data to load and add it to lunr
  window.data.then(function(loaded_data){
    $.each(loaded_data, function(index, value){
      window.idx.add(
        $.extend({ "id": index }, value)
      );
    });
  });

  // Event when the form is submitted
  $("#site_search").submit(function(event){
      event.preventDefault();
      var query = $("#search_box").val(); // Get the value from the search field
      var results = window.idx.search(query); // Get lunr to perform a search
      display_search_results(results); // Hand the results off to be displayed
  });

  function display_search_results(results) {
    // Wait for data to load
    window.data.then(function(loaded_data) {
      // Are there any results?
      if (results.length) {
		// Clear any old results
        $("#search_results").empty();
		// Hide blog entries
		$("#entries").hide();
		// Clear search box field
		$("#search_box").val = "";
        // Iterate over the results
        results.forEach(function(result,i) {
          var item = loaded_data[result.ref];
		  // Build a snippet of HTML for this result, add loop index
		  build_html(i, item.url, item.postHeading, item.subHeading, item.date, item.tags.split(', '));
        });
		// Create load more button
		build_load_more_button();
		// Redirect to search_results div
		window.location.href = "/#search_results";
      } else {
        // If there are no results, let the user know.
		$("#no-results").css('display', 'block');
      }
    });
  }

  function build_html(index, url, heading, subHeading, date, tags)
  {
	  var heading_ = document.createElement("h3");
	  heading_.innerHTML = heading;

	  var subHeading_ = document.createElement("h5");
	  subHeading_.innerHTML = subHeading;

	  var date_ = document.createElement("span");
	  date_.setAttribute('class', 'w3-opacity');
	  date_.innerHTML = date;
	  var date__ = document.createElement("h5");
	  date__.appendChild(date_);

	  var tags__ = document.createElement("h5");
	  tags__.innerHTML = "Tags: "
	  for(var i=0; i<tags.length; i++)
	  {
		  var tag = tags[i];
		  var tagTitle = 'View posts tagged with "' + tag + '"';
		  var tagUrl = '/tag/' + tag;
		  var tagUrl_ = document.createElement("a");
		  tagUrl_.setAttribute('href', tagUrl);
		  tagUrl_.setAttribute('title', tagTitle);
		  tagUrl_.innerHTML = tag;
		  var tag_ = document.createElement("span");
		  tag_.setAttribute('class', 'w3-tag w3-black w3-margin-bottom');
		  tag_.appendChild(tagUrl_);
		  tags__.appendChild(tag_);
		  tags__.innerHTML += '\xa0';
	  }

	  var urlText = document.createElement("b");
	  urlText.innerHTML = "READ MORE >>";
	  var url_ = "window.location.href='" + url + "'";
	  var urlButton = document.createElement("button");
	  urlButton.setAttribute('class', 'w3-button w3-padding-large w3-white w3-border');
	  urlButton.setAttribute('onclick', url_);
	  urlButton.appendChild(urlText);
	  var url__ = document.createElement("p");
	  url__.appendChild(urlButton);

	  var postPreview = document.createElement("div");
	  postPreview.setAttribute('class', 'w3-container');
	  postPreview.appendChild(heading_);
	  postPreview.appendChild(subHeading_);
	  postPreview.appendChild(date__);
	  postPreview.appendChild(tags__);
	  postPreview.appendChild(url__);

	  var divider = document.createElement("hr");

	  var entryId = "blogEntry" + index;
	  var blogEntry = document.createElement("div");
	  blogEntry.setAttribute('id', entryId);
	  blogEntry.setAttribute('class', 'w3-card-4 w3-margin w3-white');
	  if(index > 4)
		  blogEntry.setAttribute('style', 'display:none');
	  blogEntry.appendChild(postPreview);
	  blogEntry.appendChild(divider);

	  $("#search_results").append(blogEntry);
  }

  function build_load_more_button()
  {
	var moreButton = document.createElement("button");
	moreButton.setAttribute('class', 'w3-button w3-black w3-padding-large w3-margin-bottom');
	moreButton.setAttribute('onclick', 'loadMoreEntries(this, "search_results", 6)');
	moreButton.innerHTML = "Load More";
	var moreButtonP = document.createElement("p");
	moreButtonP.setAttribute('style', 'text-align: center');
	moreButtonP.appendChild(moreButton);
	var moreButtonF = document.createElement("footer");
	moreButtonF.setAttribute('id', 'more_results');
	moreButtonF.setAttribute('class', 'w3-margin');
	moreButtonF.appendChild(moreButtonP);
	$("#search_results").append(moreButtonF);
  }

});<|endoftext|>


<commit_before>var app = angular.module('calApp', ['ngAnimate', 'ui.router', 'hmTouchEvents']);
console.log('index loaded');<commit_msg>setUp<commit_after>function config($stateProvider) {
  $stateProvider
    .state('base',{
      url: '/',
      controller: function () {
        console.log('base state');
      }
    });
  };

config.$inject = ['$stateProvider']

var moduleName = 'calApp'

var app = angular.module(moduleName,
  [
  'ngAnimate',
  'ui.router',
  'hmTouchEvents'
  ]
  ).config(config);

export default moduleName<|endoftext|>