<commit_before>var VLC = {
	makeRequest: function(player, params) {
		var url = 'http://' + player.server + '/requests/status.json';
		var headers = { 'Authorization': 'Basic ' + base64_encode(':' + player.password) };
		http('GET', url, params, headers, function(xhr) {
			if (xhr.status >= 300) {
				return appMessageQueue.send({type:TYPE.VLC, status:'Error', title:'Server error: HTTP ' + xhr.statusText});
			}
			var res = JSON.parse(xhr.responseText);
			var title = res.information || player.title;
			title = title.category || player.title;
			title = title.meta || player.title;
			title = title.filename || player.title;
			title = title.substring(0,30);
			var status = res.state ? capitaliseFirstLetter(res.state) : 'Unknown';
			status = status.substring(0,30);
			var volume = res.volume || 0;
			volume = (volume / 512) * 200;
			volume = (volume > 200) ? 200 : volume;
			volume = Math.round(volume);
			var length = res.length || 0;
			var seek = res.time || 0;
			seek = length ? (seek / length) * 100 : 0;
			seek = Math.round(seek);
			appMessageQueue.send({type:TYPE.VLC, title:title, status:status, volume:volume, seek:seek});
		}, function(e) {
			appMessageQueue.send({type:TYPE.VLC, status:'Error', title:e});
		});
	},

	handleAppMessage: function(payload) {
		var player = Skipstone.players[payload.player];
		var request = payload.request || null;
		var params = {};

		if (!isset(player.server)) {
			return appMessageQueue.send({type:TYPE.VLC, status:'Error', title:'Server not set.'});
		}

		switch (request) {
			case REQUEST.PLAY_PAUSE:
				params.command = 'pl_pause';
				break;
			case REQUEST.VOLUME_INCREMENT:
				params.command = 'volume';
				params.val = '+12.8';
				break;
			case REQUEST.VOLUME_DECREMENT:
				params.command = 'volume';
				params.val = '-12.8';
				break;
			case REQUEST.VOLUME_MIN:
				params.command = 'volume';
				params.val = '0';
				break;
			case REQUEST.VOLUME_MAX:
				params.command = 'volume';
				params.val = '512';
				break;
			case REQUEST.FORWARD_SHORT:
				params.command = 'seek';
				params.val = '+10S';
				break;
			case REQUEST.FORWARD_LONG:
				params.command = 'seek';
				params.val = '+1M';
				break;
			case REQUEST.BACKWARD_SHORT:
				params.command = 'seek';
				params.val = '-10S';
				break;
			case REQUEST.BACKWARD_LONG:
				params.command = 'seek';
				params.val = '-1M';
				break;
			case REQUEST.NEXT:
				params.command = 'pl_next';
				break;
			case REQUEST.PREV:
				params.command = 'pl_previous';
				break;
		}

		VLC.makeRequest(player, params);
	}
};
<commit_msg>Changed volume steps for VLC from 12.8 to 12 to support locales using comma<commit_after>var VLC = {
	makeRequest: function(player, params) {
		var url = 'http://' + player.server + '/requests/status.json';
		var headers = { 'Authorization': 'Basic ' + base64_encode(':' + player.password) };
		http('GET', url, params, headers, function(xhr) {
			if (xhr.status >= 300) {
				return appMessageQueue.send({type:TYPE.VLC, status:'Error', title:'Server error: HTTP ' + xhr.statusText});
			}
			var res = JSON.parse(xhr.responseText);
			var title = res.information || player.title;
			title = title.category || player.title;
			title = title.meta || player.title;
			title = title.filename || player.title;
			title = title.substring(0,30);
			var status = res.state ? capitaliseFirstLetter(res.state) : 'Unknown';
			status = status.substring(0,30);
			var volume = res.volume || 0;
			volume = (volume / 512) * 200;
			volume = (volume > 200) ? 200 : volume;
			volume = Math.round(volume);
			var length = res.length || 0;
			var seek = res.time || 0;
			seek = length ? (seek / length) * 100 : 0;
			seek = Math.round(seek);
			appMessageQueue.send({type:TYPE.VLC, title:title, status:status, volume:volume, seek:seek});
		}, function(e) {
			appMessageQueue.send({type:TYPE.VLC, status:'Error', title:e});
		});
	},

	handleAppMessage: function(payload) {
		var player = Skipstone.players[payload.player];
		var request = payload.request || null;
		var params = {};

		if (!isset(player.server)) {
			return appMessageQueue.send({type:TYPE.VLC, status:'Error', title:'Server not set.'});
		}

		switch (request) {
			case REQUEST.PLAY_PAUSE:
				params.command = 'pl_pause';
				break;
			case REQUEST.VOLUME_INCREMENT:
				params.command = 'volume';
				params.val = '+12';
				break;
			case REQUEST.VOLUME_DECREMENT:
				params.command = 'volume';
				params.val = '-12';
				break;
			case REQUEST.VOLUME_MIN:
				params.command = 'volume';
				params.val = '0';
				break;
			case REQUEST.VOLUME_MAX:
				params.command = 'volume';
				params.val = '512';
				break;
			case REQUEST.FORWARD_SHORT:
				params.command = 'seek';
				params.val = '+10S';
				break;
			case REQUEST.FORWARD_LONG:
				params.command = 'seek';
				params.val = '+1M';
				break;
			case REQUEST.BACKWARD_SHORT:
				params.command = 'seek';
				params.val = '-10S';
				break;
			case REQUEST.BACKWARD_LONG:
				params.command = 'seek';
				params.val = '-1M';
				break;
			case REQUEST.NEXT:
				params.command = 'pl_next';
				break;
			case REQUEST.PREV:
				params.command = 'pl_previous';
				break;
		}

		VLC.makeRequest(player, params);
	}
};
<|endoftext|>


<commit_before>
class Page {

	constructor ( id, x18nPrefix, onTop, onLeave ) {

		const tab  = document.createElement( 'div' );
		const page = document.createElement( 'div' );

		page.classList.add( 'page' );

		tab.classList.add( id );
		tab.classList.add( 'tab' );

		this.page = page;
		this.tab = tab;
		this.onTop = onTop;
		this.frame = null;
		this.onLeave = onLeave;
		this.slide = undefined;
		this.x18nPrefix = x18nPrefix + '.';
		this.onChange = null;
		this.id = id;

	}

	i18n ( text ) {

		const cfg = this.frame.ctx.cfg;
		const tr = cfg.i18n( this.x18nPrefix + text );

		return ( tr === undefined ) ? text : tr;

	}

	addListener ( obj, name, handler ) {

		this.frame.addListener( obj, name, handler );
		// redirect to frame method - allows later rework to page specific destruction

	}

	tabHandleClick ( event ) {

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

		this.open();

	}

	open () {

		const tab = this.tab;
		const pages = this.frame.pages;

		tab.classList.add( 'toptab' );

		this.frame.onScreen( this.i18n( 'title' ) );
		this.frame.openPageId = this.id;

		pages.forEach( page => {

			const otherPage = page.page;
			const otherTab = page.tab;
			const owner = page.owner;

			if ( otherTab === tab ) {

				otherPage.style.display = 'block';

			} else {

				otherPage.style.display = 'none';

				if ( otherTab.classList.contains( 'toptab' ) ) {

					otherTab.classList.remove( 'toptab' );

					if ( owner.onLeave !== undefined ) owner.onLeave();

				}

			}

		} );

	}

	appendChild ( domElement ) {

		this.page.appendChild( domElement );

		return domElement;

	}

	addHeader ( text ) {

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

		div.classList.add( 'header' );
		div.textContent = this.i18n( text );

		this.page.appendChild( div );

		return div;

	}

	addCollapsingHeader ( text ) {

		const div = this.addHeader( text );

		div.classList.add( 'header_full' );

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

		container.classList.add( 'container_full' );

		this.page.appendChild( container );

		this.addListener( div, 'click', () => {

			if ( div.classList.contains( 'header_collapsed' ) ) {

				this.addListener( container, 'transitionend', _onReveal );
				container.classList.remove( 'container_collapsed' );

			} else {

				this.addListener( container, 'transitionend', _onCollapse );
				container.classList.add( 'container_collapsed' );

			}

			function _onReveal () {

				container.removeEventListener( 'transitionend', _onReveal );
				div.classList.remove( 'header_collapsed' );

			}

			function _onCollapse () {

				container.removeEventListener( 'transitionend', _onCollapse );
				div.classList.add( 'header_collapsed' );

			}

		} );

		return container;

	}

	addText ( text ) {

		const p = this.addLine( text );

		p.classList.add( 'spaced' );

		return p;

	}

	addLine ( text ) {

		const p = document.createElement( 'p' );

		p.textContent = text;

		this.page.appendChild( p );

		return p;

	}

	addBlankLine () {

		const b = document.createElement( 'br' );

		this.page.appendChild( b );

		return b;

	}

	addLink ( url, text ) {

		const a = document.createElement( 'a' );

		a.href = url;
		a.textContent = text;
		a.target = '_blank';

		this.page.appendChild( a );

		return a;

	}

	makeLabel ( title, labelClass, idFor = 'na' ) {

		const label = document.createElement( 'label' );

		label.textContent = this.i18n( title );
		label.htmlFor = idFor;
		label.classList.add( labelClass );

		return label;

	}

	addSelect ( title, obj, trgObj, property, replace ) {

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

		div.classList.add( 'control' );

		if ( obj instanceof Array ) {

			obj.forEach( element => {

				const opt = document.createElement( 'option' );

				opt.value = element;
				opt.text = element;

				if ( opt.value === trgObj[ property ] ) opt.selected = true;

				select.add( opt, null );

			} );

		} else {

			for ( const p in obj ) {

				const opt = document.createElement( 'option' );

				// translate each space delimited substring of ui text
				opt.text = p.split( ' ' ).reduce( ( res, val ) => { return res + ' ' + this.i18n( val ); }, '' ).trim();
				opt.value = obj[ p ];

				if ( opt.value == trgObj[ property ] ) opt.selected = true;

				select.add( opt, null );

			}

		}

		const frame = this.frame;

		this.addListener( select, 'change', function onChange ( event ) { frame.inHandler = true; trgObj[ property ] = event.target.value; frame.inHandler = false; } );

		frame.controls[ property ] = select;

		div.appendChild( this.makeLabel( title, 'cv-select' ) );
		div.appendChild( select );

		if ( replace === undefined ) {

			this.page.appendChild( div );

		} else {

			this.page.replaceChild( div, replace );

		}

		return div;

	}

	addFileSelect ( title, obj, trgObj, property ) {

		const frame = this.frame;
		const div = this.addSelect( title, obj, trgObj, property );

		const label = div.firstChild;
		const id = 'cv-' + frame.getSeq();

		label.for = id;
		label.classList.add( 'cv-file-label' );

		const input = document.createElement( 'input' );

		input.id = id;
		input.classList.add( 'cv-file' );
		input.type = 'file';
		input.accept = '.svx,.lox,.plt';
		input.multiple = true;

		this.addListener( input, 'change', function _handleFileChange () {

			const count = input.files.length;
			const files = [];

			if ( count > 0 ) {

				for ( let i = 0; i < count; i++ ) files.push( input.files[ i ] );

				trgObj[ property ] = files;

			}

		} );

		label.appendChild( input );

		return div;

	}

	addCheckbox ( title, obj, property ) {

		const frame = this.frame;
		const cb    = document.createElement( 'input' );
		const div   = document.createElement( 'div' );

		const id = 'cv-' + frame.getSeq();

		div.classList.add( 'control' );

		cb.type = 'checkbox';
		cb.checked = obj[ property ];
		cb.id = id;

		this.addListener( cb, 'change', _checkboxChanged );

		frame.controls[ property ] = cb;

		div.appendChild( cb );
		div.appendChild( this.makeLabel( title, 'check', id ) );

		this.page.appendChild( div );

		return div;

		function _checkboxChanged ( event ) {

			frame.inHandler = true;

			obj[ property ] = event.target.checked;

			frame.inHandler = false;

		}

	}

	addRange ( title, obj, property ) {

		const frame = this.frame;
		const div = document.createElement( 'div' );
		const range = document.createElement( 'input' );

		div.classList.add( 'control' );

		range.type = 'range';

		range.min = 0;
		range.max = 1;

		range.step = 0.05;
		range.value = obj[ property ];

		this.addListener( range, 'input', _rangeChanged );

		frame.controls[ property ] = range;

		div.appendChild( this.makeLabel( title, 'cv-range' ) );
		div.appendChild( range );

		this.page.appendChild( div );

		return div;

		function _rangeChanged ( event ) {

			frame.inHandler = true;

			obj[ property ] = event.target.value;

			frame.inHandler = false;

		}

	}

	addSlide ( domElement, depth ) {

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

		slide.classList.add( 'slide' );
		slide.style.zIndex = 200 - depth;

		slide.appendChild( domElement );

		this.page.appendChild( slide );

		this.slide = slide;
		this.slideDepth = depth;

		return slide;

	}

	replaceSlide ( domElement, depth ) {

		const newSlide = document.createElement( 'div' );
		const page = this.page;

		let oldSlide = this.slide;

		let redraw; // eslint-disable-line no-unused-vars

		newSlide.classList.add( 'slide' );
		newSlide.style.zIndex = 200 - depth;

		if ( depth < this.slideDepth ) {

			newSlide.classList.add( 'slide-out' );

		}

		newSlide.appendChild( domElement );

		page.appendChild( newSlide );

		if ( depth > this.slideDepth ) {

			oldSlide.addEventListener( 'transitionend', afterSlideOut );
			oldSlide.classList.add( 'slide-out' );

			redraw = oldSlide.clientHeight; // lgtm

		} else if ( depth < this.slideDepth ) {

			newSlide.addEventListener( 'transitionend', afterSlideIn );

			redraw = newSlide.clientHeight; // lgtm

			newSlide.classList.remove( 'slide-out' );

		} else {

			page.removeChild( oldSlide );

		}

		this.slide = newSlide;
		this.slideDepth = depth;

		return newSlide;

		function afterSlideOut () {

			oldSlide.removeEventListener( 'transitionend', afterSlideOut );
			page.removeChild( oldSlide );

			oldSlide = null;

		}

		function afterSlideIn () {

			page.removeChild( oldSlide );
			newSlide.removeEventListener( 'transitionend', afterSlideIn );

			oldSlide = null;

		}

	}

	addButton ( title, func ) {

		const button = document.createElement( 'button' );

		button.type = 'button';
		button.textContent = this.i18n( title );

		this.addListener( button, 'click', func );

		this.page.appendChild( button );

		return button;

	}

	addTextBox ( title, placeholder, getResultGetter ) {

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

		let value;

		input.type = 'text';
		input.placeholder = placeholder;

		div.appendChild( this.makeLabel( title, 'text' ) );
		div.appendChild( input );

		this.page.appendChild( div );

		this.addListener( input, 'change', function ( e ) { value = e.target.value; return true; } );

		getResultGetter( _result );

		return div;

		function _result() {

			input.value = '';
			return value;

		}

	}

	addDownloadButton ( title, urlProvider, fileName ) {

		const a = document.createElement( 'a' );

		if ( typeof a.download === 'undefined' ) return null;

		this.addListener( a, 'click', () => { a.href = urlProvider( a ); } );

		a.textContent = this.i18n( title );
		a.type = 'download';
		a.download = fileName;
		a.href = 'javascript:void();';

		a.classList.add( 'download' );

		this.page.appendChild( a );

		return a;

	}

	static canDownload () {

		const a = document.createElement( 'a' );
		return ( typeof a.download !== 'undefined' );

	}

	download ( data, fileName ) {

		const a = document.createElement( 'a' );

		if ( typeof a.download === 'undefined' ) return null;

		a.type = 'download';
		a.download = fileName;
		a.href = data;
		a.click();

	}

	addColor ( title, name ) {

		const frame = this.frame;
		const cb    = document.createElement( 'input' );
		const div   = document.createElement( 'div' );
		const cfg = frame.ctx.cfg;

		const id = 'cv-' + frame.getSeq();

		div.classList.add( 'control' );
		div.classList.add( 'color' );

		cb.type = 'color';
		cb.value = cfg.themeColorHex( name ),

		cb.id = id;

		this.addListener( cb, 'change', _colorChanged );

		frame.controls[ name ] = cb;

		div.appendChild( cb );
		div.appendChild( this.makeLabel( title, 'color', id ) );

		this.page.appendChild( div );

		this.addListener( cfg, 'colors', e => { if (e.name === 'all' ) cb.value = cfg.themeColorHex( name ); } );

		return div;

		function _colorChanged ( event ) {

			frame.inHandler = true;

			cfg.setThemeColorCSS( name, event.target.value );

			frame.inHandler = false;

		}

	}

	addLogo () {

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

		img.classList.add( 'logo' );
		img.title = 'logo';

		this.appendChild( img );

	}

	dispose () {
		if ( this._dispose ) this._dispose();
	}

}

export { Page };<commit_msg>restore scroll position when tabbing between ui pages<commit_after>
class Page {

	constructor ( id, x18nPrefix, onTop, onLeave ) {

		const tab  = document.createElement( 'div' );
		const page = document.createElement( 'div' );

		page.classList.add( 'page' );

		tab.classList.add( id );
		tab.classList.add( 'tab' );

		this.page = page;
		this.tab = tab;
		this.onTop = onTop;
		this.frame = null;
		this.onLeave = onLeave;
		this.slide = undefined;
		this.x18nPrefix = x18nPrefix + '.';
		this.onChange = null;
		this.id = id;
		this.lastScrollY = 0;

	}

	i18n ( text ) {

		const cfg = this.frame.ctx.cfg;
		const tr = cfg.i18n( this.x18nPrefix + text );

		return ( tr === undefined ) ? text : tr;

	}

	addListener ( obj, name, handler ) {

		this.frame.addListener( obj, name, handler );
		// redirect to frame method - allows later rework to page specific destruction

	}

	tabHandleClick ( event ) {

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

		this.open();

	}

	open () {

		const thisTab = this.tab;
		const pages = this.frame.pages;
		const frameDiv = this.frame.frame;

		thisTab.classList.add( 'toptab' );

		this.frame.onScreen( this.i18n( 'title' ) );
		this.frame.openPageId = this.id;

		pages.forEach( page => {

			const pageDiv = page.page;
			const tabDiv = page.tab;
			const owner = page.owner;

			if ( tabDiv !== thisTab ) {

				if ( tabDiv.classList.contains( 'toptab' ) ) {

					// previously open page
					owner.lastScrollY = frameDiv.scrollTop;
					tabDiv.classList.remove( 'toptab' );

					if ( owner.onLeave !== undefined ) owner.onLeave();

				}

				pageDiv.style.display = 'none';

			}

		} );

		this.page.style.display = 'block';
		frameDiv.scrollTo( 0, this.lastScrollY );

	}

	appendChild ( domElement ) {

		this.page.appendChild( domElement );

		return domElement;

	}

	addHeader ( text ) {

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

		div.classList.add( 'header' );
		div.textContent = this.i18n( text );

		this.page.appendChild( div );

		return div;

	}

	addCollapsingHeader ( text ) {

		const div = this.addHeader( text );

		div.classList.add( 'header_full' );

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

		container.classList.add( 'container_full' );

		this.page.appendChild( container );

		this.addListener( div, 'click', () => {

			if ( div.classList.contains( 'header_collapsed' ) ) {

				this.addListener( container, 'transitionend', _onReveal );
				container.classList.remove( 'container_collapsed' );

			} else {

				this.addListener( container, 'transitionend', _onCollapse );
				container.classList.add( 'container_collapsed' );

			}

			function _onReveal () {

				container.removeEventListener( 'transitionend', _onReveal );
				div.classList.remove( 'header_collapsed' );

			}

			function _onCollapse () {

				container.removeEventListener( 'transitionend', _onCollapse );
				div.classList.add( 'header_collapsed' );

			}

		} );

		return container;

	}

	addText ( text ) {

		const p = this.addLine( text );

		p.classList.add( 'spaced' );

		return p;

	}

	addLine ( text ) {

		const p = document.createElement( 'p' );

		p.textContent = text;

		this.page.appendChild( p );

		return p;

	}

	addBlankLine () {

		const b = document.createElement( 'br' );

		this.page.appendChild( b );

		return b;

	}

	addLink ( url, text ) {

		const a = document.createElement( 'a' );

		a.href = url;
		a.textContent = text;
		a.target = '_blank';

		this.page.appendChild( a );

		return a;

	}

	makeLabel ( title, labelClass, idFor = 'na' ) {

		const label = document.createElement( 'label' );

		label.textContent = this.i18n( title );
		label.htmlFor = idFor;
		label.classList.add( labelClass );

		return label;

	}

	addSelect ( title, obj, trgObj, property, replace ) {

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

		div.classList.add( 'control' );

		if ( obj instanceof Array ) {

			obj.forEach( element => {

				const opt = document.createElement( 'option' );

				opt.value = element;
				opt.text = element;

				if ( opt.value === trgObj[ property ] ) opt.selected = true;

				select.add( opt, null );

			} );

		} else {

			for ( const p in obj ) {

				const opt = document.createElement( 'option' );

				// translate each space delimited substring of ui text
				opt.text = p.split( ' ' ).reduce( ( res, val ) => { return res + ' ' + this.i18n( val ); }, '' ).trim();
				opt.value = obj[ p ];

				if ( opt.value == trgObj[ property ] ) opt.selected = true;

				select.add( opt, null );

			}

		}

		const frame = this.frame;

		this.addListener( select, 'change', function onChange ( event ) { frame.inHandler = true; trgObj[ property ] = event.target.value; frame.inHandler = false; } );

		frame.controls[ property ] = select;

		div.appendChild( this.makeLabel( title, 'cv-select' ) );
		div.appendChild( select );

		if ( replace === undefined ) {

			this.page.appendChild( div );

		} else {

			this.page.replaceChild( div, replace );

		}

		return div;

	}

	addFileSelect ( title, obj, trgObj, property ) {

		const frame = this.frame;
		const div = this.addSelect( title, obj, trgObj, property );

		const label = div.firstChild;
		const id = 'cv-' + frame.getSeq();

		label.for = id;
		label.classList.add( 'cv-file-label' );

		const input = document.createElement( 'input' );

		input.id = id;
		input.classList.add( 'cv-file' );
		input.type = 'file';
		input.accept = '.svx,.lox,.plt';
		input.multiple = true;

		this.addListener( input, 'change', function _handleFileChange () {

			const count = input.files.length;
			const files = [];

			if ( count > 0 ) {

				for ( let i = 0; i < count; i++ ) files.push( input.files[ i ] );

				trgObj[ property ] = files;

			}

		} );

		label.appendChild( input );

		return div;

	}

	addCheckbox ( title, obj, property ) {

		const frame = this.frame;
		const cb    = document.createElement( 'input' );
		const div   = document.createElement( 'div' );

		const id = 'cv-' + frame.getSeq();

		div.classList.add( 'control' );

		cb.type = 'checkbox';
		cb.checked = obj[ property ];
		cb.id = id;

		this.addListener( cb, 'change', _checkboxChanged );

		frame.controls[ property ] = cb;

		div.appendChild( cb );
		div.appendChild( this.makeLabel( title, 'check', id ) );

		this.page.appendChild( div );

		return div;

		function _checkboxChanged ( event ) {

			frame.inHandler = true;

			obj[ property ] = event.target.checked;

			frame.inHandler = false;

		}

	}

	addRange ( title, obj, property ) {

		const frame = this.frame;
		const div = document.createElement( 'div' );
		const range = document.createElement( 'input' );

		div.classList.add( 'control' );

		range.type = 'range';

		range.min = 0;
		range.max = 1;

		range.step = 0.05;
		range.value = obj[ property ];

		this.addListener( range, 'input', _rangeChanged );

		frame.controls[ property ] = range;

		div.appendChild( this.makeLabel( title, 'cv-range' ) );
		div.appendChild( range );

		this.page.appendChild( div );

		return div;

		function _rangeChanged ( event ) {

			frame.inHandler = true;

			obj[ property ] = event.target.value;

			frame.inHandler = false;

		}

	}

	addSlide ( domElement, depth ) {

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

		slide.classList.add( 'slide' );
		slide.style.zIndex = 200 - depth;

		slide.appendChild( domElement );

		this.page.appendChild( slide );

		this.slide = slide;
		this.slideDepth = depth;

		return slide;

	}

	replaceSlide ( domElement, depth ) {

		const newSlide = document.createElement( 'div' );
		const page = this.page;

		let oldSlide = this.slide;

		let redraw; // eslint-disable-line no-unused-vars

		newSlide.classList.add( 'slide' );
		newSlide.style.zIndex = 200 - depth;

		if ( depth < this.slideDepth ) {

			newSlide.classList.add( 'slide-out' );

		}

		newSlide.appendChild( domElement );

		page.appendChild( newSlide );

		if ( depth > this.slideDepth ) {

			oldSlide.addEventListener( 'transitionend', afterSlideOut );
			oldSlide.classList.add( 'slide-out' );

			redraw = oldSlide.clientHeight; // lgtm

		} else if ( depth < this.slideDepth ) {

			newSlide.addEventListener( 'transitionend', afterSlideIn );

			redraw = newSlide.clientHeight; // lgtm

			newSlide.classList.remove( 'slide-out' );

		} else {

			page.removeChild( oldSlide );

		}

		this.slide = newSlide;
		this.slideDepth = depth;

		return newSlide;

		function afterSlideOut () {

			oldSlide.removeEventListener( 'transitionend', afterSlideOut );
			page.removeChild( oldSlide );

			oldSlide = null;

		}

		function afterSlideIn () {

			page.removeChild( oldSlide );
			newSlide.removeEventListener( 'transitionend', afterSlideIn );

			oldSlide = null;

		}

	}

	addButton ( title, func ) {

		const button = document.createElement( 'button' );

		button.type = 'button';
		button.textContent = this.i18n( title );

		this.addListener( button, 'click', func );

		this.page.appendChild( button );

		return button;

	}

	addTextBox ( title, placeholder, getResultGetter ) {

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

		let value;

		input.type = 'text';
		input.placeholder = placeholder;

		div.appendChild( this.makeLabel( title, 'text' ) );
		div.appendChild( input );

		this.page.appendChild( div );

		this.addListener( input, 'change', function ( e ) { value = e.target.value; return true; } );

		getResultGetter( _result );

		return div;

		function _result() {

			input.value = '';
			return value;

		}

	}

	addDownloadButton ( title, urlProvider, fileName ) {

		const a = document.createElement( 'a' );

		if ( typeof a.download === 'undefined' ) return null;

		this.addListener( a, 'click', () => { a.href = urlProvider( a ); } );

		a.textContent = this.i18n( title );
		a.type = 'download';
		a.download = fileName;
		a.href = 'javascript:void();';

		a.classList.add( 'download' );

		this.page.appendChild( a );

		return a;

	}

	static canDownload () {

		const a = document.createElement( 'a' );
		return ( typeof a.download !== 'undefined' );

	}

	download ( data, fileName ) {

		const a = document.createElement( 'a' );

		if ( typeof a.download === 'undefined' ) return null;

		a.type = 'download';
		a.download = fileName;
		a.href = data;
		a.click();

	}

	addColor ( title, name ) {

		const frame = this.frame;
		const cb    = document.createElement( 'input' );
		const div   = document.createElement( 'div' );
		const cfg = frame.ctx.cfg;

		const id = 'cv-' + frame.getSeq();

		div.classList.add( 'control' );
		div.classList.add( 'color' );

		cb.type = 'color';
		cb.value = cfg.themeColorHex( name ),

		cb.id = id;

		this.addListener( cb, 'change', _colorChanged );

		frame.controls[ name ] = cb;

		div.appendChild( cb );
		div.appendChild( this.makeLabel( title, 'color', id ) );

		this.page.appendChild( div );

		this.addListener( cfg, 'colors', e => { if (e.name === 'all' ) cb.value = cfg.themeColorHex( name ); } );

		return div;

		function _colorChanged ( event ) {

			frame.inHandler = true;

			cfg.setThemeColorCSS( name, event.target.value );

			frame.inHandler = false;

		}

	}

	addLogo () {

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

		img.classList.add( 'logo' );
		img.title = 'logo';

		this.appendChild( img );

	}

	dispose () {
		if ( this._dispose ) this._dispose();
	}

}

export { Page };<|endoftext|>


<commit_before>import decamelize from 'decamelize';
import XMLWriter from 'xml-writer';

const XSLFOElementType = Symbol('xslfo.element');

const twoPartProperties = [
    'block-progression-dimension.maximum',
    'block-progression-dimension.minimum',
    'block-progression-dimension.optimum',
    'border-before-width.conditional',
    'border-before-width.length',
    'border-separation.block-progression-direction',
    'border-separation.inline-progression-direction',
    'inline-progression-dimension.maximum',
    'inline-progression-dimension.minimum',
    'inline-progression-dimension.optimum',
    'keep-together.within-column',
    'keep-together.within-line',
    'keep-together.within-page',
    'keep-with-next.within-line',
    'keep-with-previous.within-line',
    'leader-length.maximum',
    'leader-length.minimum',
    'leader-length.optimum',
    'line-height.conditionality',
    'line-height.maximum',
    'line-height.minimum',
    'line-height.optimum',
    'line-height.precedence',
    'space-after.precedence',
    'space-before.conditionality',
    'space-before.maximum',
    'space-before.minimum',
    'space-before.optimum',
    'space-before.precedence',
    'space.minimum'
].map(p => p.replace(/[.].*/, ''));

function fixAttributeName(attributeName) {
    attributeName = decamelize(attributeName, '-');

    let splitFrom = twoPartProperties.find(p => attributeName.indexOf(p) === 0);

    if (splitFrom) {
        return `${splitFrom}.${attributeName.substring(splitFrom.length + 1)}`
    }
    else {
        return attributeName;
    }
}

function renderAttributes(attributes) {
    if (!attributes) return;

    return Object.keys(attributes).reduce((prev, curr) => prev + (attributes[curr] !== undefined ? ' ' + fixAttributeName(curr) + '="' + attributes[curr] + '"' : ''), '');
}

export function createElement(type, props, ...children) {
    let element = {
        $$typeof: XSLFOElementType,
        type,
        props: { ...props }
    }

    if (children) element.props.children = children;

    return element;
}

function elementToStream(element, writer) {
    if (!element) return;

    if (typeof(element) === 'string') {
        writer.text(element);
    }
    else if (Array.isArray(element)) {
        Array.prototype.forEach.call(element, (e) => elementToStream(e, writer));
    }
    else {
        writer.startElementNS('fo', element.tag);

        for (let attributeName in element.attributes) {
            writer.writeAttribute(fixAttributeName(attributeName), element.attributes[attributeName]);
        }

        elementToStream(element.children, writer);

        writer.endElement();
    }
}

function renderToXmlWriter(element, writer) {
    let elementTree = process(element);

    writer.startDocument('1.0', 'UTF-8');
    elementToStream(elementTree, writer);
    writer.endDocument();
}

function renderToString(element) {
    let writer = new XMLWriter(true);
    renderToXmlWriter(element, writer);

    return writer.toString();
}

function renderToStream(element, stream) {
    let writer = new XMLWriter(true, stream.write.bind(stream));
    renderToXmlWriter(element, writer);
}

export class Component {
    constructor(props) {
        this.props = props;
    }

    render() {
        throw new Error('inherit this class, fool.');
    }
}

const Children = {
    map(children, fn, thisArg) {
        if (Array.isArray(children)) {
            Array.prototype.forEach.call(children, (child) => Children.map(child, fn, thisArg));
        }
        else {
            return fn.call(thisArg, children);
        }
    }
}

function process(element) {
    if (!element) return element;

    if (typeof(element) === 'string') {
        return element;
    }
    else if (Array.isArray(element)) {
        return element.map(process);
    }
    else {
        if (element.$$typeof !== XSLFOElementType) throw Error("Not an XSLFOElement");
        if (typeof(element.type) === 'string') {
            let { children, ...attributes } = element.props;

            children = process(children);

            return {
                tag: decamelize(element.type, '-'),
                attributes,
                children
            };
        }
        else {
            let type, childTree;

            if (typeof(element.type === 'function')) {
                let type = new element.type(element.props);

                if (type.render) {
                    childTree = type.render();
                }
                else {
                    childTree = type;
                }
            }
            else {
                throw new Error("I don't know what this is...");
            }

            return process(childTree);
        }
    }
}

function cloneElement(element, props, ...children) {
    let { props: originalProps, children: originalChildren, ...rest } = element;

    return {
        ...rest,
        props: Object.assign(Object.create(null), originalProps, props),
        children: (children ? children : originalChildren)
    };
}

export default {
    createElement,
    renderToString,
    renderToStream,
    Component,
    Children,
    process,
    cloneElement
};
<commit_msg>dangerouslySetInnerXML<commit_after>import decamelize from 'decamelize';
import XMLWriter from 'xml-writer';

const XSLFOElementType = Symbol('xslfo.element');

const twoPartProperties = [
    'block-progression-dimension.maximum',
    'block-progression-dimension.minimum',
    'block-progression-dimension.optimum',
    'border-before-width.conditional',
    'border-before-width.length',
    'border-separation.block-progression-direction',
    'border-separation.inline-progression-direction',
    'inline-progression-dimension.maximum',
    'inline-progression-dimension.minimum',
    'inline-progression-dimension.optimum',
    'keep-together.within-column',
    'keep-together.within-line',
    'keep-together.within-page',
    'keep-with-next.within-line',
    'keep-with-previous.within-line',
    'leader-length.maximum',
    'leader-length.minimum',
    'leader-length.optimum',
    'line-height.conditionality',
    'line-height.maximum',
    'line-height.minimum',
    'line-height.optimum',
    'line-height.precedence',
    'space-after.precedence',
    'space-before.conditionality',
    'space-before.maximum',
    'space-before.minimum',
    'space-before.optimum',
    'space-before.precedence',
    'space.minimum'
].map(p => p.replace(/[.].*/, ''));

function fixAttributeName(attributeName) {
    attributeName = decamelize(attributeName, '-');

    let splitFrom = twoPartProperties.find(p => attributeName.indexOf(p) === 0);

    if (splitFrom) {
        return `${splitFrom}.${attributeName.substring(splitFrom.length + 1)}`
    }
    else {
        return attributeName;
    }
}

function renderAttributes(attributes) {
    if (!attributes) return;

    return Object.keys(attributes).reduce((prev, curr) => prev + (attributes[curr] !== undefined ? ' ' + fixAttributeName(curr) + '="' + attributes[curr] + '"' : ''), '');
}

export function createElement(type, props, ...children) {
    let element = {
        $$typeof: XSLFOElementType,
        type,
        props: { ...props }
    }

    if (children) element.props.children = children;

    return element;
}

function elementToStream(element, writer) {
    if (!element) return;

    if (typeof(element) === 'string') {
        writer.text(element);
    }
    else if (Array.isArray(element)) {
        Array.prototype.forEach.call(element, (e) => elementToStream(e, writer));
    }
    else {
        writer.startElementNS('fo', element.tag);

        let innerXML;

        for (let attributeName in element.attributes) {
            if (attributeName === 'dangerouslySetInnerXML') {
                innerXML = element.attributes[attributeName].__xml;
            }
            else {
                writer.writeAttribute(fixAttributeName(attributeName), element.attributes[attributeName]);
            }
        }

        if (innerXML) {
            writer.writeRaw(innerXML);
        }
        else {
            elementToStream(element.children, writer);
        }

        writer.endElement();
    }
}

function renderToXmlWriter(element, writer) {
    let elementTree = process(element);

    writer.startDocument('1.0', 'UTF-8');
    elementToStream(elementTree, writer);
    writer.endDocument();
}

function renderToString(element) {
    let writer = new XMLWriter(true);
    renderToXmlWriter(element, writer);

    return writer.toString();
}

function renderToStream(element, stream) {
    let writer = new XMLWriter(true, stream.write.bind(stream));
    renderToXmlWriter(element, writer);
}

export class Component {
    constructor(props) {
        this.props = props;
    }

    render() {
        throw new Error('inherit this class, fool.');
    }
}

const Children = {
    map(children, fn, thisArg) {
        if (Array.isArray(children)) {
            Array.prototype.forEach.call(children, (child) => Children.map(child, fn, thisArg));
        }
        else {
            return fn.call(thisArg, children);
        }
    }
}

function process(element) {
    if (!element) return element;

    if (typeof(element) === 'string') {
        return element;
    }
    else if (Array.isArray(element)) {
        return element.map(process);
    }
    else {
        if (element.$$typeof !== XSLFOElementType) throw Error("Not an XSLFOElement");
        if (typeof(element.type) === 'string') {
            let { children, ...attributes } = element.props;

            children = process(children);

            return {
                tag: decamelize(element.type, '-'),
                attributes,
                children
            };
        }
        else {
            let type, childTree;

            if (typeof(element.type === 'function')) {
                let type = new element.type(element.props);

                if (type.render) {
                    childTree = type.render();
                }
                else {
                    childTree = type;
                }
            }
            else {
                throw new Error("I don't know what this is...");
            }

            return process(childTree);
        }
    }
}

function cloneElement(element, props, ...children) {
    let { props: originalProps, children: originalChildren, ...rest } = element;

    return {
        ...rest,
        props: Object.assign(Object.create(null), originalProps, props),
        children: (children ? children : originalChildren)
    };
}

export default {
    createElement,
    renderToString,
    renderToStream,
    Component,
    Children,
    process,
    cloneElement
};
<|endoftext|>


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

/**
 * @fileoverview
 * Registers a language handler for Swift
 *
 *
 * To use, include prettify.js and this file in your HTML page.
 * Then put your code in an HTML tag like
 *
(my swift code)

 * This file supports the following language extensions:
 *     lang-swift - Swift
 *
 * I used https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AboutTheLanguageReference.html
 * as the basis for this. In particular, I targeted the revision from
 * 2015-04-08. Swift is still evolving, and this was the latest version
 * available at the time. I will keep the code unoptimized to ease changes that come with new Swift standards.
 *
 * @author cerech@google.com
 */

PR['registerLangHandler'](
    PR['createSimpleLexer'](
        [
          //whitespace
          [PR['PR_PLAIN'],                /^[ \n\r\t\v\f\0]+/, null, ' \n\r\t\v\f\0'],
          //string literals
          [PR['PR_STRING'],               /^".*?"/, null, '"'],
        ],
        [
          //floating point literals
          [PR['PR_LITERAL'],              /^(?:(?:0x[\da-fA-F][\da-fA-F_]*\.[\da-fA-F][\da-fA-F_]*[pP]?)|(?:\d[\d_]*\.\d[\d_]*[eE]?))[+-]?\d[\d_]*/, null],
          //integer literals
          [PR['PR_LITERAL'],              /^-?(?:(?:0(?:(?:b[01][01_]*)|(?:o[0-7][0-7_]*)|(?:x[\da-fA-F][\da-fA-F_]*)))|(?:\d[\d_]*))/, null],
          //some other literals
          [PR['PR_LITERAL'],              /^(?:true|false|nil)\b/, null],
          //keywords
          [PR['PR_KEYWORD'],              /^\b(?:__COLUMN__|__FILE__|__FUNCTION__|__LINE__|associativity|as|break|case|class|continue|convenience|default|deinit|didSet|do|dynamic|dynamicType|enum|fallthrough|final|for|func|get|import|infix|init|inout|internal|in|is|lazy|left|let|mutating|none|nonmutating|operator|optional|override|postfix|precedence|prefix|private|protocol|Protocol|public|required|return|right|safe|self|set|static|struct|subscript|super|switch|Type|typealias|unowned|unsafe|var|weak|while|willSet)\b/, null],
          //double slash comments
          [PR['PR_COMMENT'],              /^\/\/.*?[\n\r]/, null],
          //slash star comments
          [PR['PR_COMMENT'],              /^\/\*[\s\S]*?(?:\*\/|$)/, null],
          //punctuation
          [PR['PR_PUNCTUATION'],          /^<<=|<=|<<|>>=|>=|>>|===|==|\.\.\.|&&=|\.\.<|!==|!=|&=|~=|~|\(|\)|\[|\]|{|}|@|#|;|\.|,|:|\|\|=|\?\?|\|\||&&|&\*|&\+|&-|&=|\+=|-=|\/=|\*=|\^=|%=|\|=|->|`|==|\+\+|--|\/|\+|!|\*|%|<|>|&|\||\^|\?|=|-|_/, null],
          [PR['PR_TYPE'],                 /^\b(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null]   //borrowing the type regex given by the main program for C-family languages
        ]),
    ['swift']);
<commit_msg>Fix oversight in Swift string literal regex.<commit_after>// Copyright (C) 2015 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview
 * Registers a language handler for Swift
 *
 *
 * To use, include prettify.js and this file in your HTML page.
 * Then put your code in an HTML tag like
 *
(my swift code)

 * This file supports the following language extensions:
 *     lang-swift - Swift
 *
 * I used https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AboutTheLanguageReference.html
 * as the basis for this. In particular, I targeted the revision from
 * 2015-04-08. Swift is still evolving, and this was the latest version
 * available at the time. I will keep the code unoptimized to ease changes that come with new Swift standards.
 *
 * @author cerech@google.com
 */

PR['registerLangHandler'](
    PR['createSimpleLexer'](
        [
          //whitespace
          [PR['PR_PLAIN'],                /^[ \n\r\t\v\f\0]+/, null, ' \n\r\t\v\f\0'],
          //string literals
          [PR['PR_STRING'],               /^"(?:[^"\\]|(?:\\.)|(?:\\\((?:[^"\\)]|\\.)*\)))*"/, null, '"'],
        ],
        [
          //floating point literals
          [PR['PR_LITERAL'],              /^(?:(?:0x[\da-fA-F][\da-fA-F_]*\.[\da-fA-F][\da-fA-F_]*[pP]?)|(?:\d[\d_]*\.\d[\d_]*[eE]?))[+-]?\d[\d_]*/, null],
          //integer literals
          [PR['PR_LITERAL'],              /^-?(?:(?:0(?:(?:b[01][01_]*)|(?:o[0-7][0-7_]*)|(?:x[\da-fA-F][\da-fA-F_]*)))|(?:\d[\d_]*))/, null],
          //some other literals
          [PR['PR_LITERAL'],              /^(?:true|false|nil)\b/, null],
          //keywords
          [PR['PR_KEYWORD'],              /^\b(?:__COLUMN__|__FILE__|__FUNCTION__|__LINE__|associativity|as|break|case|class|continue|convenience|default|deinit|didSet|do|dynamic|dynamicType|enum|fallthrough|final|for|func|get|import|infix|init|inout|internal|in|is|lazy|left|let|mutating|none|nonmutating|operator|optional|override|postfix|precedence|prefix|private|protocol|Protocol|public|required|return|right|safe|self|set|static|struct|subscript|super|switch|Type|typealias|unowned|unsafe|var|weak|while|willSet)\b/, null],
          //double slash comments
          [PR['PR_COMMENT'],              /^\/\/.*?[\n\r]/, null],
          //slash star comments
          [PR['PR_COMMENT'],              /^\/\*[\s\S]*?(?:\*\/|$)/, null],
          //punctuation
          [PR['PR_PUNCTUATION'],          /^<<=|<=|<<|>>=|>=|>>|===|==|\.\.\.|&&=|\.\.<|!==|!=|&=|~=|~|\(|\)|\[|\]|{|}|@|#|;|\.|,|:|\|\|=|\?\?|\|\||&&|&\*|&\+|&-|&=|\+=|-=|\/=|\*=|\^=|%=|\|=|->|`|==|\+\+|--|\/|\+|!|\*|%|<|>|&|\||\^|\?|=|-|_/, null],
          [PR['PR_TYPE'],                 /^\b(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null]   //borrowing the type regex given by the main program for C-family languages
        ]),
    ['swift']);
<|endoftext|>


<commit_before>/** section: Language, related to: Array
 *    $A(iterable) -> Array
 *
 *  Accepts an array-like collection (anything with numeric indices) and returns
 *  its equivalent as an actual Array object.
 *  This method is a convenience alias of [[Array.from]], but is the preferred way
 *  of casting to an Array.
 **/
function $A(iterable) {
  if (!iterable) return [];
  // Safari <2.0.4 crashes when accessing property of a node list with property accessor.
  // It nevertheless works fine with `in` operator, which is why we use it here
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

/** section: Language, related to: Array
 *  $w(string) -> Array
 *  - string (String): A string with zero or more spaces.
 *
 *  Splits a string into an array, treating all whitespace as delimiters.
 *
 *  Equivalent to Ruby's `%w{foo bar}` or Perl's `qw(foo bar)`.
**/
function $w(string) {
  if (!Object.isString(string)) return [];
  string = string.strip();
  return string ? string.split(/\s+/) : [];
}

/** alias of: $A
 *  Array.from(iterable) -> Array
**/
Array.from = $A;

/** section: Language
 * class Array
 *  includes Enumerable
 *
 *  Prototype extends all native JavaScript arrays with quite a few powerful
 *  methods.
 *
 *  This is done in two ways:
 *
 *  * It mixes in the [[Enumerable]] module, which brings in a ton of methods.
 *  * It adds quite a few extra methods, which are documented in this section.
 *
 *  With Prototype, arrays become much, much more than the trivial objects we
 *  used to manipulate, limiting ourselves to using their `length` property and
 *  their `[]` indexing operator. They become very powerful objects that
 *  greatly simplify the code for 99% of the common use cases involving them.
 *
 *
Why you should stop using for...in to iterate

 *
 *  Many JavaScript authors have been misled into using the `for...in` JavaScript
 *  construct to loop over array elements. This kind of code just won't work
 *  with Prototype.
 *
 *  The ECMA 262 standard, which defines ECMAScript 3rd edition, supposedly
 *  implemented by all major browsers including MSIE, defines ten methods
 *  on Array (§15.4.4), including nice methods like `concat`, `join`, `pop`, and
 *  `push`.
 *
 *  This same standard explicitly defines that the `for...in` construct (§12.6.4)
 *  exists to enumerate the properties of the object appearing on the right side
 *  of the `in` keyword. Only properties specifically marked as _non-enumerable_
 *  are ignored by such a loop. By default, the `prototype` and `length`
 *  properties are so marked, which prevents you from enumerating over array
 *  methods when using for...in. This comfort led developers to use `for...in` as a
 *  shortcut for indexing loops, when it is not its actual purpose.
 *
 *  However, Prototype has no way to mark the methods it adds to
 *  `Array.prototype` as non-enumerable. Therefore, using `for...in` on arrays
 *  when using Prototype will enumerate all extended methods as well, such as
 *  those coming from the [[Enumerable]] module, and those Prototype puts in the
 *  Array namespace (listed further below).
 *
 *
What you should use instead

 *
 *  You can revert to vanilla loops:
 *
 *      for (var index = 0; index < myArray.length; ++index) {
 *        var item = myArray[index];
 *        // Your code working on item here...
 *      }
 *
 *  Or you can use iterators, such as [[Array#each]]:
 *
 *      myArray.each(function(item) {
 *        // Your code working on item here...
 *      });
 *
 *
 *  The inability to use `for...in` on arrays is not much of a burden: as you'll
 *  see, most of what you used to loop over arrays for can be concisely done
 *  using the new methods provided by Array or the mixed-in [[Enumerable]]
 *  module. So manual loops should be fairly rare.
 *
 *
 *
A note on performance

 *
 *  Should you have a very large array, using iterators with lexical closures
 *  (anonymous functions that you pass to the iterators and that get invoked at
 *  every loop iteration) in methods like [[Array#each]] — _or_ relying on
 *  repetitive array construction (such as uniq), may yield unsatisfactory
 *  performance. In such cases, you're better off writing manual indexing loops,
 *  but take care then to cache the length property and use the prefix `++`
 *  operator:
 *
 *      // Custom loop with cached length property: maximum full-loop
 *      // performance on very large arrays!
 *      for (var index = 0, len = myArray.length; index < len; ++index) {
 *        var item = myArray[index];
 *        // Your code working on item here...
 *      }
 *
**/

(function() {
  var arrayProto = Array.prototype,
      slice = arrayProto.slice,
      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available

  function each(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  }
  if (!_each) _each = each;

  /**
   *  Array#clear() -> Array
   *  Empties an array.
  **/
  function clear() {
    this.length = 0;
    return this;
  }

  /**
   *  Array#first() -> ?
   *  Returns the array's first item.
  **/
  function first() {
    return this[0];
  }

  /**
   *  Array#last() -> ?
   *  Returns the array's last item.
  **/
  function last() {
    return this[this.length - 1];
  }

  /**
   *  Array#compact() -> Array
   *  Returns a copy of the array without any `null` or `undefined` values.
  **/
  function compact() {
    return this.select(function(value) {
      return value != null;
    });
  }

  /**
   *  Array#flatten() -> Array
   *  Returns a "flat" (one-dimensional) version of the array.
   *
   *  Nested arrays are recursively injected "inline." This can prove very
   *  useful when handling the results of a recursive collection algorithm,
   *  for instance.
  **/
  function flatten() {
    return this.inject([], function(array, value) {
      if (Object.isArray(value))
        return array.concat(value.flatten());
      array.push(value);
      return array;
    });
  }

  /**
   *  Array#without(value...) -> Array
   *  - value (?): A value to exclude.
   *
   *  Produces a new version of the array that does not contain any of the
   *  specified values.
  **/
  function without() {
    var values = slice.call(arguments, 0);
    return this.select(function(value) {
      return !values.include(value);
    });
  }

  /**
   *  Array#reverse([inline = false]) -> Array
   *  - inline (Boolean): Whether to modify the array in place. If `false`,
   *      clones the original array first.
   *
   *  Returns the reversed version of the array.
  **/
  function reverse(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  }

  /**
   *  Array#uniq([sorted = false]) -> Array
   *  - sorted (Boolean): Whether the array has already been sorted. If `true`,
   *      a less-costly algorithm will be used.
   *
   *  Produces a duplicate-free version of an array. If no duplicates are
   *  found, the original array is returned.
  **/
  function uniq(sorted) {
    return this.inject([], function(array, value, index) {
      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
        array.push(value);
      return array;
    });
  }

  /**
   *  Array#intersect(array) -> Array
   *  - array (Array): A collection of values.
   *
   *  Returns an array containing every item that is shared between the two
   *  given arrays.
  **/
  function intersect(array) {
    return this.uniq().findAll(function(item) {
      return array.detect(function(value) { return item === value });
    });
  }

  /** alias of: Array#clone
   *  Array#toArray() -> Array
  **/

  /**
   *  Array#clone() -> Array
   *
   *  Returns a duplicate of the array, leaving the original array intact.
  **/
  function clone() {
    return slice.call(this, 0);
  }

  /** related to: Enumerable#size
   *  Array#size() -> Number
   *  Returns the size of the array.
   *
   *  This is just a local optimization of the mixed-in [[Enumerable#size]]
   *  which avoids array cloning and uses the array's native length property.
  **/
  function size() {
    return this.length;
  }

  /** related to: Object.inspect
   *  Array#inspect() -> String
   *
   *  Returns the debug-oriented string representation of an array.
  **/
  function inspect() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }

  /** related to: Object.toJSON
   *  Array#toJSON() -> String
   *
   *  Returns a JSON string representation of the array.
  **/
  function toJSON() {
    var results = [];
    this.each(function(object) {
      var value = Object.toJSON(object);
      if (!Object.isUndefined(value)) results.push(value);
    });
    return '[' + results.join(', ') + ']';
  }

  /**
   *  Array#indexOf(item[, offset = 0]) -> Number
   *  - item (?): A value that may or may not be in the array.
   *  - offset (Number): The number of initial items to skip before beginning the
   *      search.
   *
   *  Returns the position of the first occurrence of `item` within the array — or
   *  `-1` if `item` doesn't exist in the array.
  **/
  function indexOf(item, i) {
    i || (i = 0);
    var length = this.length;
    if (i < 0) i = length + i;
    for (; i < length; i++)
      if (this[i] === item) return i;
    return -1;
  }

  /** related to: Array#indexOf
   *  Array#lastIndexOf(item[, offset]) -> Number
   *  - item (?): A value that may or may not be in the array.
   *  - offset (Number): The number of items at the end to skip before beginning
   *      the search.
   *
   *  Returns the position of the last occurrence of `item` within the array — or
   *  `-1` if `item` doesn't exist in the array.
  **/
  function lastIndexOf(item, i) {
    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
    var n = this.slice(0, i).reverse().indexOf(item);
    return (n < 0) ? n : i - n - 1;
  }

  // Replaces a built-in function. No PDoc needed.
  function concat() {
    var array = slice.call(this, 0), item;
    for (var i = 0, length = arguments.length; i < length; i++) {
      item = arguments[i];
      if (Object.isArray(item) && !('callee' in item)) {
        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
          array.push(item[j]);
      } else {
        array.push(item);
      }
    }
    return array;
  }

  Object.extend(arrayProto, Enumerable);

  if (!arrayProto._reverse)
    arrayProto._reverse = arrayProto.reverse;

  Object.extend(arrayProto, {
    _each:     _each,
    clear:     clear,
    first:     first,
    last:      last,
    compact:   compact,
    flatten:   flatten,
    without:   without,
    reverse:   reverse,
    uniq:      uniq,
    intersect: intersect,
    clone:     clone,
    toArray:   clone,
    size:      size,
    inspect:   inspect,
    toJSON:    toJSON
  });

  // fix for opera
  var CONCAT_ARGUMENTS_BUGGY = (function() {
    return [].concat(arguments)[0][0] !== 1;
  })(1,2)

  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;

  // use native browser JS 1.6 implementation if available
  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();
<commit_msg>doc: port old docs for Array#clear<commit_after>/** section: Language, related to: Array
 *    $A(iterable) -> Array
 *
 *  Accepts an array-like collection (anything with numeric indices) and returns
 *  its equivalent as an actual Array object.
 *  This method is a convenience alias of [[Array.from]], but is the preferred way
 *  of casting to an Array.
 **/
function $A(iterable) {
  if (!iterable) return [];
  // Safari <2.0.4 crashes when accessing property of a node list with property accessor.
  // It nevertheless works fine with `in` operator, which is why we use it here
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

/** section: Language, related to: Array
 *  $w(string) -> Array
 *  - string (String): A string with zero or more spaces.
 *
 *  Splits a string into an array, treating all whitespace as delimiters.
 *
 *  Equivalent to Ruby's `%w{foo bar}` or Perl's `qw(foo bar)`.
**/
function $w(string) {
  if (!Object.isString(string)) return [];
  string = string.strip();
  return string ? string.split(/\s+/) : [];
}

/** alias of: $A
 *  Array.from(iterable) -> Array
**/
Array.from = $A;

/** section: Language
 * class Array
 *  includes Enumerable
 *
 *  Prototype extends all native JavaScript arrays with quite a few powerful
 *  methods.
 *
 *  This is done in two ways:
 *
 *  * It mixes in the [[Enumerable]] module, which brings in a ton of methods.
 *  * It adds quite a few extra methods, which are documented in this section.
 *
 *  With Prototype, arrays become much, much more than the trivial objects we
 *  used to manipulate, limiting ourselves to using their `length` property and
 *  their `[]` indexing operator. They become very powerful objects that
 *  greatly simplify the code for 99% of the common use cases involving them.
 *
 *
Why you should stop using for...in to iterate

 *
 *  Many JavaScript authors have been misled into using the `for...in` JavaScript
 *  construct to loop over array elements. This kind of code just won't work
 *  with Prototype.
 *
 *  The ECMA 262 standard, which defines ECMAScript 3rd edition, supposedly
 *  implemented by all major browsers including MSIE, defines ten methods
 *  on Array (§15.4.4), including nice methods like `concat`, `join`, `pop`, and
 *  `push`.
 *
 *  This same standard explicitly defines that the `for...in` construct (§12.6.4)
 *  exists to enumerate the properties of the object appearing on the right side
 *  of the `in` keyword. Only properties specifically marked as _non-enumerable_
 *  are ignored by such a loop. By default, the `prototype` and `length`
 *  properties are so marked, which prevents you from enumerating over array
 *  methods when using for...in. This comfort led developers to use `for...in` as a
 *  shortcut for indexing loops, when it is not its actual purpose.
 *
 *  However, Prototype has no way to mark the methods it adds to
 *  `Array.prototype` as non-enumerable. Therefore, using `for...in` on arrays
 *  when using Prototype will enumerate all extended methods as well, such as
 *  those coming from the [[Enumerable]] module, and those Prototype puts in the
 *  Array namespace (listed further below).
 *
 *
What you should use instead

 *
 *  You can revert to vanilla loops:
 *
 *      for (var index = 0; index < myArray.length; ++index) {
 *        var item = myArray[index];
 *        // Your code working on item here...
 *      }
 *
 *  Or you can use iterators, such as [[Array#each]]:
 *
 *      myArray.each(function(item) {
 *        // Your code working on item here...
 *      });
 *
 *
 *  The inability to use `for...in` on arrays is not much of a burden: as you'll
 *  see, most of what you used to loop over arrays for can be concisely done
 *  using the new methods provided by Array or the mixed-in [[Enumerable]]
 *  module. So manual loops should be fairly rare.
 *
 *
 *
A note on performance

 *
 *  Should you have a very large array, using iterators with lexical closures
 *  (anonymous functions that you pass to the iterators and that get invoked at
 *  every loop iteration) in methods like [[Array#each]] — _or_ relying on
 *  repetitive array construction (such as uniq), may yield unsatisfactory
 *  performance. In such cases, you're better off writing manual indexing loops,
 *  but take care then to cache the length property and use the prefix `++`
 *  operator:
 *
 *      // Custom loop with cached length property: maximum full-loop
 *      // performance on very large arrays!
 *      for (var index = 0, len = myArray.length; index < len; ++index) {
 *        var item = myArray[index];
 *        // Your code working on item here...
 *      }
 *
**/

(function() {
  var arrayProto = Array.prototype,
      slice = arrayProto.slice,
      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available

  function each(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  }
  if (!_each) _each = each;

  /**
   *  Array#clear() -> Array
   *
   *  Clears the array (makes it empty) and returns the array reference.
   *
   *  ### Example
   *
   *      var guys = ['Sam', 'Justin', 'Andrew', 'Dan'];
   *      guys.clear();
   *      // -> []
   *      guys
   *      // -> []
  **/
  function clear() {
    this.length = 0;
    return this;
  }

  /**
   *  Array#first() -> ?
   *  Returns the array's first item.
  **/
  function first() {
    return this[0];
  }

  /**
   *  Array#last() -> ?
   *  Returns the array's last item.
  **/
  function last() {
    return this[this.length - 1];
  }

  /**
   *  Array#compact() -> Array
   *  Returns a copy of the array without any `null` or `undefined` values.
  **/
  function compact() {
    return this.select(function(value) {
      return value != null;
    });
  }

  /**
   *  Array#flatten() -> Array
   *  Returns a "flat" (one-dimensional) version of the array.
   *
   *  Nested arrays are recursively injected "inline." This can prove very
   *  useful when handling the results of a recursive collection algorithm,
   *  for instance.
  **/
  function flatten() {
    return this.inject([], function(array, value) {
      if (Object.isArray(value))
        return array.concat(value.flatten());
      array.push(value);
      return array;
    });
  }

  /**
   *  Array#without(value...) -> Array
   *  - value (?): A value to exclude.
   *
   *  Produces a new version of the array that does not contain any of the
   *  specified values.
  **/
  function without() {
    var values = slice.call(arguments, 0);
    return this.select(function(value) {
      return !values.include(value);
    });
  }

  /**
   *  Array#reverse([inline = false]) -> Array
   *  - inline (Boolean): Whether to modify the array in place. If `false`,
   *      clones the original array first.
   *
   *  Returns the reversed version of the array.
  **/
  function reverse(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  }

  /**
   *  Array#uniq([sorted = false]) -> Array
   *  - sorted (Boolean): Whether the array has already been sorted. If `true`,
   *      a less-costly algorithm will be used.
   *
   *  Produces a duplicate-free version of an array. If no duplicates are
   *  found, the original array is returned.
  **/
  function uniq(sorted) {
    return this.inject([], function(array, value, index) {
      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
        array.push(value);
      return array;
    });
  }

  /**
   *  Array#intersect(array) -> Array
   *  - array (Array): A collection of values.
   *
   *  Returns an array containing every item that is shared between the two
   *  given arrays.
  **/
  function intersect(array) {
    return this.uniq().findAll(function(item) {
      return array.detect(function(value) { return item === value });
    });
  }

  /** alias of: Array#clone
   *  Array#toArray() -> Array
  **/

  /**
   *  Array#clone() -> Array
   *
   *  Returns a duplicate of the array, leaving the original array intact.
  **/
  function clone() {
    return slice.call(this, 0);
  }

  /** related to: Enumerable#size
   *  Array#size() -> Number
   *  Returns the size of the array.
   *
   *  This is just a local optimization of the mixed-in [[Enumerable#size]]
   *  which avoids array cloning and uses the array's native length property.
  **/
  function size() {
    return this.length;
  }

  /** related to: Object.inspect
   *  Array#inspect() -> String
   *
   *  Returns the debug-oriented string representation of an array.
  **/
  function inspect() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }

  /** related to: Object.toJSON
   *  Array#toJSON() -> String
   *
   *  Returns a JSON string representation of the array.
  **/
  function toJSON() {
    var results = [];
    this.each(function(object) {
      var value = Object.toJSON(object);
      if (!Object.isUndefined(value)) results.push(value);
    });
    return '[' + results.join(', ') + ']';
  }

  /**
   *  Array#indexOf(item[, offset = 0]) -> Number
   *  - item (?): A value that may or may not be in the array.
   *  - offset (Number): The number of initial items to skip before beginning the
   *      search.
   *
   *  Returns the position of the first occurrence of `item` within the array — or
   *  `-1` if `item` doesn't exist in the array.
  **/
  function indexOf(item, i) {
    i || (i = 0);
    var length = this.length;
    if (i < 0) i = length + i;
    for (; i < length; i++)
      if (this[i] === item) return i;
    return -1;
  }

  /** related to: Array#indexOf
   *  Array#lastIndexOf(item[, offset]) -> Number
   *  - item (?): A value that may or may not be in the array.
   *  - offset (Number): The number of items at the end to skip before beginning
   *      the search.
   *
   *  Returns the position of the last occurrence of `item` within the array — or
   *  `-1` if `item` doesn't exist in the array.
  **/
  function lastIndexOf(item, i) {
    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
    var n = this.slice(0, i).reverse().indexOf(item);
    return (n < 0) ? n : i - n - 1;
  }

  // Replaces a built-in function. No PDoc needed.
  function concat() {
    var array = slice.call(this, 0), item;
    for (var i = 0, length = arguments.length; i < length; i++) {
      item = arguments[i];
      if (Object.isArray(item) && !('callee' in item)) {
        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
          array.push(item[j]);
      } else {
        array.push(item);
      }
    }
    return array;
  }

  Object.extend(arrayProto, Enumerable);

  if (!arrayProto._reverse)
    arrayProto._reverse = arrayProto.reverse;

  Object.extend(arrayProto, {
    _each:     _each,
    clear:     clear,
    first:     first,
    last:      last,
    compact:   compact,
    flatten:   flatten,
    without:   without,
    reverse:   reverse,
    uniq:      uniq,
    intersect: intersect,
    clone:     clone,
    toArray:   clone,
    size:      size,
    inspect:   inspect,
    toJSON:    toJSON
  });

  // fix for opera
  var CONCAT_ARGUMENTS_BUGGY = (function() {
    return [].concat(arguments)[0][0] !== 1;
  })(1,2)

  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;

  // use native browser JS 1.6 implementation if available
  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();
<|endoftext|>


<commit_before>/* eslint-disable global-require */
export const langs = [
  {
    value: 'en-US',
    native: 'English (US)',
    data: require('./en-US.json'),
  }, /* {
    value: 'bg-BG',
    native: 'български bǎlgarski',
    data: require('./bg-BG.json'),
  }, {
    value: 'cs-CZ',
    native: 'Čeština',
    data: require('./cs-CZ.json'),
  }, */ {
    value: 'de-DE',
    native: 'Deutsch',
    data: require('./de-DE.json'),
  }, {
    value: 'es-ES',
    native: 'Español',
    data: require('./es-ES.json'),
  }, /* {
    value: 'es-PE',
    native: 'Español (América Latina)',
    data: require('./es-PE.json'),
  }, {
    value: 'fi-FI',
    native: 'Suomi',
    data: require('./fi-FI.json'),
  }, */ {
    value: 'fr-FR',
    native: 'Français',
    data: require('./fr-FR.json'),
  }, {
    value: 'it-IT',
    native: 'Italiano',
    data: require('./it-IT.json'),
  }, {
    value: 'ja-JP',
    native: '日本語',
    data: require('./ja-JP.json'),
  }, /* {
    value: 'ko-KR',
    native: '한국어',
    data: require('./ko-KR.json'),
  }, */ {
    value: 'ms-MY',
    native: 'Bahasa Melayu',
    data: require('./ms-MY.json'),
  }, /* {
    value: 'nl-NL',
    native: 'Nederlands',
    data: require('./nl-NL.json'),
  }, */ {
    value: 'pl-PL',
    native: 'Polski',
    data: require('./pl-PL.json'),
  }, {
    value: 'pt-BR',
    native: 'Português Brasileiro',
    data: require('./pt-BR.json'),
  }, {
    value: 'ru-RU',
    native: 'Русский',
    data: require('./ru-RU.json'),
  }, /* {
    value: 'sv-SE',
    native: 'Svenska',
    data: require('./sv-SE.json'),
  }, {
    value: 'tr-TR',
    native: 'Türkçe',
    data: require('./tr-TR.json'),
  },  {
    value: 'uk-UA',
    native: 'Українська',
    data: require('./uk-UA.json'),
  }, {
    value: 'vi-VN',
    native: 'Tiếng Việt',
    data: require('./vi-VN.json'),
  }, */ {
    value: 'zh-CN',
    native: '简体字',
    data: require('./zh-CN.json'),
  }, /* {
    value: 'zh-TW',
    native: '繁體字',
    data: require('./zh-TW.json'),
  }, */
];
const savedLang = window.localStorage && window.localStorage.getItem('localization');
const langToUse = (langs.find(lang => lang.value === savedLang) || langs[0]).data;
export default langToUse;
<commit_msg>disable french<commit_after>/* eslint-disable global-require */
export const langs = [
  {
    value: 'en-US',
    native: 'English (US)',
    data: require('./en-US.json'),
  }, /* {
    value: 'bg-BG',
    native: 'български bǎlgarski',
    data: require('./bg-BG.json'),
  }, {
    value: 'cs-CZ',
    native: 'Čeština',
    data: require('./cs-CZ.json'),
  }, */ {
    value: 'de-DE',
    native: 'Deutsch',
    data: require('./de-DE.json'),
  }, {
    value: 'es-ES',
    native: 'Español',
    data: require('./es-ES.json'),
  }, /* {
    value: 'es-PE',
    native: 'Español (América Latina)',
    data: require('./es-PE.json'),
  }, {
    value: 'fi-FI',
    native: 'Suomi',
    data: require('./fi-FI.json'),
  },  {
    value: 'fr-FR',
    native: 'Français',
    data: require('./fr-FR.json'),
  }, */ {
    value: 'it-IT',
    native: 'Italiano',
    data: require('./it-IT.json'),
  }, {
    value: 'ja-JP',
    native: '日本語',
    data: require('./ja-JP.json'),
  }, /* {
    value: 'ko-KR',
    native: '한국어',
    data: require('./ko-KR.json'),
  }, */ {
    value: 'ms-MY',
    native: 'Bahasa Melayu',
    data: require('./ms-MY.json'),
  }, /* {
    value: 'nl-NL',
    native: 'Nederlands',
    data: require('./nl-NL.json'),
  }, */ {
    value: 'pl-PL',
    native: 'Polski',
    data: require('./pl-PL.json'),
  }, {
    value: 'pt-BR',
    native: 'Português Brasileiro',
    data: require('./pt-BR.json'),
  }, {
    value: 'ru-RU',
    native: 'Русский',
    data: require('./ru-RU.json'),
  }, /* {
    value: 'sv-SE',
    native: 'Svenska',
    data: require('./sv-SE.json'),
  }, {
    value: 'tr-TR',
    native: 'Türkçe',
    data: require('./tr-TR.json'),
  },  {
    value: 'uk-UA',
    native: 'Українська',
    data: require('./uk-UA.json'),
  }, {
    value: 'vi-VN',
    native: 'Tiếng Việt',
    data: require('./vi-VN.json'),
  }, */ {
    value: 'zh-CN',
    native: '简体字',
    data: require('./zh-CN.json'),
  }, /* {
    value: 'zh-TW',
    native: '繁體字',
    data: require('./zh-TW.json'),
  }, */
];
const savedLang = window.localStorage && window.localStorage.getItem('localization');
const langToUse = (langs.find(lang => lang.value === savedLang) || langs[0]).data;
export default langToUse;
<|endoftext|>