<commit_before>
"use strict";

function t(id) {
	var s = T[id];
	if (!s) return id;
	if (!s.replace) return s;
	for (var i = 1; i < arguments.length; i++) {
		s = s.replace(new RegExp('\\\$' + i.toString(10), 'g'), arguments[i]);
	}
	return s;
}

jQuery(function ($) {
	var $c = $('#canvas'),
		$toggleUI = $('.toggleUI'),
		$loading = $('#loading'),
		$error = $('#error'),
		$loadingText = $('#loading > p'),
		$errorText = $('#error > p'),
		wordfreq = WordFreq({worker: '../wordfreq.worker.js'}),
		theme = [
			{
				fontFamily: '"Trebuchet MS", "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
				wordColor: 'random-dark',
				backgroundColor: '#eee'  //opaque white
			},
			{
				// http://ethantw.net/projects/lab/css-reset/
				fontFamily: 'Baskerville, "Times New Roman", "華康儷金黑 Std", "華康儷宋 Std",  DFLiKingHeiStd-W8, DFLiSongStd-W5, "Hiragino Mincho Pro", "LiSong Pro Light", "新細明體", serif',
				wordColor: 'random-light',
				backgroundColor: '#000'
			},
			{
				// http://ethantw.net/projects/lab/css-reset/
				fontFamily: 'Baskerville, "Times New Roman", "華康儷金黑 Std", "華康儷宋 Std",  DFLiKingHeiStd-W8, DFLiSongStd-W5, "Hiragino Mincho Pro", "LiSong Pro Light", "新細明體", serif',
				wordColor: '#fff',
				backgroundColor: '#000'
			},
			{
				fontFamily: '"Myriad Pro", "Lucida Grande", Helvetica, "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
				wordColor: 'rgba(255,255,255,0.8)',
				backgroundColor: '#353130'
			},
			{
				fontFamily: '"Trebuchet MS", "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
				wordColor: 'rgba(0,0,0,0.7)',
				backgroundColor: 'rgba(255, 255, 255, 1)'  //opaque white
			}
		],
		list, weightFactor, gridSize, themeid = 0;

	function resetCanvasSize() {
		var width = document.body.offsetWidth,
		height = document.body.offsetHeight;

		$c.attr(
			{
				height: height,
				width: width
			}
		).css({
			width: width.toString(10) + 'px',
			height: height.toString(10) + 'px',
			top: '50%',
			left: '50%',
			marginLeft: '-' + (width/2).toString(10) + 'px',
			marginTop: '-' + (height/2).toString(10) + 'px'
		});
	}

	if (
		!$.wordCloudSupported
		|| !WordFreq.supported
		|| !$.getContent.feedSupported
		|| !Array.prototype.forEach
		|| !Array.prototype.pop
		|| !Array.prototype.push
		|| !('onhashchange' in window)
	) {
		$('#not_support').show();
		return;
	}

	if (!$.getContent.fileSupported) {
		$('input[name="source"][value="file"]').parent('label').hide();
	}

	var changeUIState = {
		start: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			$('#start').show();
			resetCanvasSize();
			$c.show().wordCloud({
				wordColor: theme[themeid].wordColor,
				backgroundColor: theme[themeid].backgroundColor,
				fontFamily: theme[themeid].fontFamily,
				rotateRatio: 0,
				wait: 50,
				wordList: [
					[t('startList_1'), t('startList_1C')],
					[t('startList_2'), t('startList_2C')],
					[t('startList_3'), t('startList_3C')],
					[t('startList_4'), t('startList_4C')]
				]//,
				//abortThreshold: 200,
				//abort: changeUIState.too_slow
			});
			return false;
		},
		source: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			resetCanvasSize();
			changeSource.apply($('input[name=source]:checked')[0]);
			$('#source_panel').show();
			return false;
		},
		ready: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			resetCanvasSize();
			$('#title').show();
			$c.show();
			$('#ready').show();
			return false;
		},
		draw: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			resetCanvasSize();
			$('#title').show();
			$('#controls').show();
			$c.show();
			setTimeout(
				function () {
					$c.wordCloud({
						wordColor: theme[themeid].wordColor,
						backgroundColor: theme[themeid].backgroundColor,
						fontFamily: theme[themeid].fontFamily,
						gridSize: gridSize,
						weightFactor: weightFactor, //$c[0].offsetHeight*$c[0].offsetWidth/vol*0.5,
						wordList: list//,
						//abortThreshold: 1000,
						//abort: changeUIState.too_slow
					});
				},
				0
			);
			return false;
		},
		loading: function (text) {
			$toggleUI.hide();
			$loadingText.text(text);
			$loading.fadeIn(100);
			$('#title').show();
			return false;
		},
		error: function (text) {
			$toggleUI.hide();
			$loading.fadeOut(100);
			$errorText.text(text);
			$error.fadeIn(100);
			return false;
		}//,
		/*too_slow: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			$('#too_slow').show();
			return false;
		}*/
	};

	// handleHash

	function handleHash() {
		if (window.location.hash) {
			if (window._gaq) _gaq.push(['_trackEvent', 'Word Cloud', 'hashchange: ' + window.location.hash]);
			$c.wordCloud(); // stop current wordCloud;
			switch (window.location.hash.substr(1, 4)) {
				case 'feed':
				updateTitle('feed', window.location.hash.substr(6));
				changeUIState.loading(t('downloading'));
				$.getContent(
					window.location.hash.substr(6),
					{
						type: 'feed',
						beforeComplete: processingFeed,
						complete: handleText
					}
				);
				return;
				break;
				case 'html':
				updateTitle('html', window.location.hash.substr(6));
				changeUIState.loading(t('downloading'));
				$.getContent(
					window.location.hash.substr(6),
					{
						type: 'html',
						beforeComplete: processingHTML,
						complete: handleText
					}
				);
				return;
				break;
				case 'file':
				var f = $('#file')[0];
				if (!f.files || !f.files.length) {
					// not really getting files, show panel
					if ($.getContent.fileSupported) $('input[value=file]').attr('checked', true);
					window.location.hash = '#';
					//changeUIState.source();
				} else {
					updateTitle('file', f.files[0].name);
					changeUIState.loading(t('reading'));
					$.getContent(
						f.files,
						{
							type: 'file.text',
							beforeComplete: readingFile,
							complete: handleText,
							encoding: $('#encoding').val()
						}
					);
				}
				break;
				//default:
				//do nothing
				//break;
			}
		} else {
			changeUIState.source();
		}
	}

	window.onhashchange = handleHash;
	if (window.location.hash) handleHash(); // only load when hash exists
	else changeUIState.start(); // show start otherwise

	// UI flow buttons

	$('.start').bind(
		'click',
		function () {
			window.location.hash = '#';
			changeUIState.source();
		}
	);

	$('.ready').bind(
		'click',
		changeUIState.draw
	);

	// Help/about panel

	$('.help').bind(
		'click',
		function () {
			$('#help_panel, #help_panel .entry').show();
			return false;
		}
	);

	$('#help_panel button').bind(
		'click',
		function () {
			$('#help_panel').hide();
		}
	);

	// interaction within source panel

	var $s = $('input[name=source]');

	function changeSource() {
		var type = this.value.substr(0,4);
		$('.entry').hide();
		$(this).parent().addClass('checked').siblings().removeClass('checked');
		$('#' + type + '_entry').show();
		$('.feed_type_name').text($(this).parent('label').text());
	};

	$s.bind(
		'click',
		changeSource
	);

	$('#source_panel_form').bind(
		'submit',
		function () {
			switch ($('input[name=source]:checked').val()) {
				case 'demo':
					window.location.hash = '#' + $('input[name=demo]:checked').val();
				break;
				case 'blog:blogger':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://' + $('#username').val() + '.blogspot.com/feeds/posts/default';
				break;
				case 'blog:pixnet':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://' + $('#username').val() + '.pixnet.net/blog/feed/rss';
//						function (str) {
	//						return str.replace(/\(.+?\.\.\.\)/g, '');
	//					},
				break;
				case 'blog:wretch':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://www.wretch.cc/blog/' + $('#username').val() + '&rss20=1';
				break;
				case 'blog:plurk':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://www.plurk.com/' + $('#username').val() + '.xml';
				break;
				case 'blog:twitter':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://twitter.com/statuses/user_timeline/' + $('#username').val() + '.rss';
				break;
				case 'feed':
					if (!$('#rss').val()) return false;
					window.location.hash = '#feed:' + $('#rss').val();
				break;
				case 'file':
					if (!$('#file')[0].files.length) return false;
					window.location.hash = '#file';
				break;
				case 'wiki':
					if (!$('#wikipedia_entry').val()) return false;
					window.location.hash = '#html:' + 'http://zh.wikipedia.org/zh-tw/' + encodeURIComponent($('#wikipedia_entry').val());
				break;
				case 'html':
					if (!$('#html_url').val()) return false;
					window.location.hash = '#html:' + $('#html_url').val();
				break;
			}
			return false;
		}
	);

	// helper function

	function processURL(url) {
		if (url.indexOf('%') !== -1) {
			return encodeURIComponent(decodeURI(url));
		} else {
			return encodeURIComponent(url);
		}
	}

	function updateTitle(type, title) {
		$('#title')
		.empty()
		.append('')
		.append($('').text(t('title', title)));
	}

	function processingFeed(title) {
		if (title) updateTitle('feed', title);
		changeUIState.loading(t('processing'));
	};

	function processingHTML(title) {
		if (title) updateTitle('html', data.responseData.feed.title);
		changeUIState.loading(t('processing'));
	};

	function readingFile() {
		changeUIState.loading(t('reading'));
	};

	// handleText

	function handleText (text) {
		changeUIState.loading(t('analyzing'));
		if (!text) {
			changeUIState.error(t('errorReading'));
			return;
		}
		wordfreq.empty();
		wordfreq.processText(
			text,
			function () {
				changeUIState.ready();

				list = wordfreq.getSortedList();

				if (list.length < 5) {
					changeUIState.error(t('errorWordCount'));
					return;
				}

				weightFactor = $c[0].offsetHeight * $c[0].offsetWidth / list[0][1] / 3500;
				gridSize = 8;

				var wordLength = list.length.toString(10),
				maxCount = list[0][1].toString(10);

				$c.wordCloud({
					wordColor: theme[themeid].wordColor,
					backgroundColor: theme[themeid].backgroundColor,
					fontFamily: theme[themeid].fontFamily,
					rotateRatio: 0,
					wordList: [
						[t('readyList_1', wordLength, maxCount), t('readyList_1C')],
						[t('readyList_2', wordLength, maxCount), t('readyList_2C')],
						[t('readyList_3', wordLength, maxCount), t('readyList_3C')],
						[t('readyList_4', wordLength, maxCount), t('readyList_4C')]
					]//,
					//abortThreshold: 200,
					//abort: changeUIState.too_slow
				});
			}
		);
	};

	// panel functions

	$('.smaller').bind(
		'click',
		function () {
			weightFactor -= 0.1;
			changeUIState.draw();
			return false;
		}
	);

	$('.larger').bind(
		'click',
		function () {
			weightFactor += 0.1;
			changeUIState.draw();
			return false;
		}
	);

	$('.changetheme').bind(
		'click',
		function () {
			themeid++;
			if (themeid >= theme.length) themeid = 0;
			$(document.body).css('background-color', theme[themeid].backgroundColor);
			changeUIState.draw();
			return false;
		}
	);

	$('.thiner').bind(
		'click',
		function () {
			gridSize --;
			changeUIState.draw();
			return false;
		}
	);

	$('.thicker').bind(
		'click',
		function () {
			gridSize ++;
			changeUIState.draw();
			return false;
		}
	);

	$('.save').bind(
		'click',
		function () {
			window.open($c[0].toDataURL());
			return false;
		}
	);
});<commit_msg>Fix Mobile Safari  issue<commit_after>
"use strict";

function t(id) {
	var s = T[id];
	if (!s) return id;
	if (!s.replace) return s;
	for (var i = 1; i < arguments.length; i++) {
		s = s.replace(new RegExp('\\\$' + i.toString(10), 'g'), arguments[i]);
	}
	return s;
}

jQuery(function ($) {
	var $c = $('#canvas'),
		$toggleUI = $('.toggleUI'),
		$loading = $('#loading'),
		$error = $('#error'),
		$loadingText = $('#loading > p'),
		$errorText = $('#error > p'),
		wordfreq = WordFreq({worker: '../wordfreq.worker.js'}),
		theme = [
			{
				fontFamily: '"Trebuchet MS", "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
				wordColor: 'random-dark',
				backgroundColor: '#eee'  //opaque white
			},
			{
				// http://ethantw.net/projects/lab/css-reset/
				fontFamily: 'Baskerville, "Times New Roman", "華康儷金黑 Std", "華康儷宋 Std",  DFLiKingHeiStd-W8, DFLiSongStd-W5, "Hiragino Mincho Pro", "LiSong Pro Light", "新細明體", serif',
				wordColor: 'random-light',
				backgroundColor: '#000'
			},
			{
				// http://ethantw.net/projects/lab/css-reset/
				fontFamily: 'Baskerville, "Times New Roman", "華康儷金黑 Std", "華康儷宋 Std",  DFLiKingHeiStd-W8, DFLiSongStd-W5, "Hiragino Mincho Pro", "LiSong Pro Light", "新細明體", serif',
				wordColor: '#fff',
				backgroundColor: '#000'
			},
			{
				fontFamily: '"Myriad Pro", "Lucida Grande", Helvetica, "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
				wordColor: 'rgba(255,255,255,0.8)',
				backgroundColor: '#353130'
			},
			{
				fontFamily: '"Trebuchet MS", "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
				wordColor: 'rgba(0,0,0,0.7)',
				backgroundColor: 'rgba(255, 255, 255, 1)'  //opaque white
			}
		],
		list, weightFactor, gridSize, themeid = 0;

	function resetCanvasSize() {
		var width = document.body.offsetWidth,
		height = document.body.offsetHeight;

		$c.attr(
			{
				height: height,
				width: width
			}
		).css({
			width: width.toString(10) + 'px',
			height: height.toString(10) + 'px',
			top: '50%',
			left: '50%',
			marginLeft: '-' + (width/2).toString(10) + 'px',
			marginTop: '-' + (height/2).toString(10) + 'px'
		});
	}

	if (
		!$.wordCloudSupported
		|| !WordFreq.supported
		|| !$.getContent.feedSupported
		|| !Array.prototype.forEach
		|| !Array.prototype.pop
		|| !Array.prototype.push
		|| !('onhashchange' in window)
	) {
		$('#not_support').show();
		return;
	}

	if (!$.getContent.fileSupported) {
		$('input[name="source"][value="file"]').parent('label').hide();
	}

	var changeUIState = {
		start: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			$('#start').show();
			resetCanvasSize();
			$c.show().wordCloud({
				wordColor: theme[themeid].wordColor,
				backgroundColor: theme[themeid].backgroundColor,
				fontFamily: theme[themeid].fontFamily,
				rotateRatio: 0,
				wait: 50,
				wordList: [
					[t('startList_1'), t('startList_1C')],
					[t('startList_2'), t('startList_2C')],
					[t('startList_3'), t('startList_3C')],
					[t('startList_4'), t('startList_4C')]
				]//,
				//abortThreshold: 200,
				//abort: changeUIState.too_slow
			});
			return false;
		},
		source: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			resetCanvasSize();
			changeSource.apply($('input[name=source]:checked')[0]);
			$('#source_panel').show();
			return false;
		},
		ready: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			resetCanvasSize();
			$('#title').show();
			$c.show();
			$('#ready').show();
			return false;
		},
		draw: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			resetCanvasSize();
			$('#title').show();
			$('#controls').show();
			$c.show();
			setTimeout(
				function () {
					$c.wordCloud({
						wordColor: theme[themeid].wordColor,
						backgroundColor: theme[themeid].backgroundColor,
						fontFamily: theme[themeid].fontFamily,
						gridSize: gridSize,
						weightFactor: weightFactor, //$c[0].offsetHeight*$c[0].offsetWidth/vol*0.5,
						wordList: list//,
						//abortThreshold: 1000,
						//abort: changeUIState.too_slow
					});
				},
				0
			);
			return false;
		},
		loading: function (text) {
			$toggleUI.hide();
			$loadingText.text(text);
			$loading.fadeIn(100);
			$('#title').show();
			return false;
		},
		error: function (text) {
			$toggleUI.hide();
			$loading.fadeOut(100);
			$errorText.text(text);
			$error.fadeIn(100);
			return false;
		}//,
		/*too_slow: function () {
			$toggleUI.hide();
			$loading.fadeOut(100);
			$('#too_slow').show();
			return false;
		}*/
	};

	// handleHash

	function handleHash() {
		if (window.location.hash) {
			if (window._gaq) _gaq.push(['_trackEvent', 'Word Cloud', 'hashchange: ' + window.location.hash]);
			$c.wordCloud(); // stop current wordCloud;
			switch (window.location.hash.substr(1, 4)) {
				case 'feed':
				updateTitle('feed', window.location.hash.substr(6));
				changeUIState.loading(t('downloading'));
				$.getContent(
					window.location.hash.substr(6),
					{
						type: 'feed',
						beforeComplete: processingFeed,
						complete: handleText
					}
				);
				return;
				break;
				case 'html':
				updateTitle('html', window.location.hash.substr(6));
				changeUIState.loading(t('downloading'));
				$.getContent(
					window.location.hash.substr(6),
					{
						type: 'html',
						beforeComplete: processingHTML,
						complete: handleText
					}
				);
				return;
				break;
				case 'file':
				var f = $('#file')[0];
				if (!f.files || !f.files.length) {
					// not really getting files, show panel
					if ($.getContent.fileSupported) $('input[value=file]').attr('checked', true);
					window.location.hash = '#';
					//changeUIState.source();
				} else {
					updateTitle('file', f.files[0].name);
					changeUIState.loading(t('reading'));
					$.getContent(
						f.files,
						{
							type: 'file.text',
							beforeComplete: readingFile,
							complete: handleText,
							encoding: $('#encoding').val()
						}
					);
				}
				break;
				//default:
				//do nothing
				//break;
			}
		} else {
			changeUIState.source();
		}
	}

	window.onhashchange = handleHash;
	if (window.location.hash) handleHash(); // only load when hash exists
	else changeUIState.start(); // show start otherwise

	// UI flow buttons

	$('.start').bind(
		'click',
		function () {
			window.location.hash = '#';
			changeUIState.source();
		}
	);

	$('.ready').bind(
		'click',
		changeUIState.draw
	);

	// Help/about panel

	$('.help').bind(
		'click',
		function () {
			$('#help_panel, #help_panel .entry').show();
			return false;
		}
	);

	$('#help_panel button').bind(
		'click',
		function () {
			$('#help_panel').hide();
		}
	);

	// interaction within source panel

	var $s = $('input[name=source]');

	function changeSource() {
		var type = this.value.substr(0,4);
		$('.entry').hide();
		$(this).parent().addClass('checked').siblings().removeClass('checked');
		$('#' + type + '_entry').show();
		$('.feed_type_name').text($(this).parent('label').text());
	};

	$s.bind(
		'click',
		changeSource
	);

	// Do this manually for Mobile Safari as a workaround
	$s.parent('label').bind(
		'click',
		function () {
			var $input = $(this).find('input');
			$input.attr('checked', true);
			changeSource.apply($input[0]);
			return false;
		}
	);

	$('#source_panel_form').bind(
		'submit',
		function () {
			switch ($('input[name=source]:checked').val()) {
				case 'demo':
					window.location.hash = '#' + $('input[name=demo]:checked').val();
				break;
				case 'blog:blogger':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://' + $('#username').val() + '.blogspot.com/feeds/posts/default';
				break;
				case 'blog:pixnet':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://' + $('#username').val() + '.pixnet.net/blog/feed/rss';
//						function (str) {
	//						return str.replace(/\(.+?\.\.\.\)/g, '');
	//					},
				break;
				case 'blog:wretch':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://www.wretch.cc/blog/' + $('#username').val() + '&rss20=1';
				break;
				case 'blog:plurk':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://www.plurk.com/' + $('#username').val() + '.xml';
				break;
				case 'blog:twitter':
					if (!$('#username').val()) return false;
					window.location.hash = '#feed:' + 'http://twitter.com/statuses/user_timeline/' + $('#username').val() + '.rss';
				break;
				case 'feed':
					if (!$('#rss').val()) return false;
					window.location.hash = '#feed:' + $('#rss').val();
				break;
				case 'file':
					if (!$('#file')[0].files.length) return false;
					window.location.hash = '#file';
				break;
				case 'wiki':
					if (!$('#wikipedia_entry').val()) return false;
					window.location.hash = '#html:' + 'http://zh.wikipedia.org/zh-tw/' + encodeURIComponent($('#wikipedia_entry').val());
				break;
				case 'html':
					if (!$('#html_url').val()) return false;
					window.location.hash = '#html:' + $('#html_url').val();
				break;
			}
			return false;
		}
	);

	// helper function

	function processURL(url) {
		if (url.indexOf('%') !== -1) {
			return encodeURIComponent(decodeURI(url));
		} else {
			return encodeURIComponent(url);
		}
	}

	function updateTitle(type, title) {
		$('#title')
		.empty()
		.append('')
		.append($('').text(t('title', title)));
	}

	function processingFeed(title) {
		if (title) updateTitle('feed', title);
		changeUIState.loading(t('processing'));
	};

	function processingHTML(title) {
		if (title) updateTitle('html', data.responseData.feed.title);
		changeUIState.loading(t('processing'));
	};

	function readingFile() {
		changeUIState.loading(t('reading'));
	};

	// handleText

	function handleText (text) {
		changeUIState.loading(t('analyzing'));
		if (!text) {
			changeUIState.error(t('errorReading'));
			return;
		}
		wordfreq.empty();
		wordfreq.processText(
			text,
			function () {
				changeUIState.ready();

				list = wordfreq.getSortedList();

				if (list.length < 5) {
					changeUIState.error(t('errorWordCount'));
					return;
				}

				weightFactor = $c[0].offsetHeight * $c[0].offsetWidth / list[0][1] / 3500;
				gridSize = 8;

				var wordLength = list.length.toString(10),
				maxCount = list[0][1].toString(10);

				$c.wordCloud({
					wordColor: theme[themeid].wordColor,
					backgroundColor: theme[themeid].backgroundColor,
					fontFamily: theme[themeid].fontFamily,
					rotateRatio: 0,
					wordList: [
						[t('readyList_1', wordLength, maxCount), t('readyList_1C')],
						[t('readyList_2', wordLength, maxCount), t('readyList_2C')],
						[t('readyList_3', wordLength, maxCount), t('readyList_3C')],
						[t('readyList_4', wordLength, maxCount), t('readyList_4C')]
					]//,
					//abortThreshold: 200,
					//abort: changeUIState.too_slow
				});
			}
		);
	};

	// panel functions

	$('.smaller').bind(
		'click',
		function () {
			weightFactor -= 0.1;
			changeUIState.draw();
			return false;
		}
	);

	$('.larger').bind(
		'click',
		function () {
			weightFactor += 0.1;
			changeUIState.draw();
			return false;
		}
	);

	$('.changetheme').bind(
		'click',
		function () {
			themeid++;
			if (themeid >= theme.length) themeid = 0;
			$(document.body).css('background-color', theme[themeid].backgroundColor);
			changeUIState.draw();
			return false;
		}
	);

	$('.thiner').bind(
		'click',
		function () {
			gridSize --;
			changeUIState.draw();
			return false;
		}
	);

	$('.thicker').bind(
		'click',
		function () {
			gridSize ++;
			changeUIState.draw();
			return false;
		}
	);

	$('.save').bind(
		'click',
		function () {
			window.open($c[0].toDataURL());
			return false;
		}
	);
});<|endoftext|>


<commit_before>(function(){

    var request = require("request");
    var xml2js = require('xml2js');
    var builder = new xml2js.Builder();

    var RSS = require('rss');
    var moment = require("moment");
    var async = require("async");
    var cheerio = require('cheerio');

    module.exports.reddit = function(req, res) {
        var url = "http://www.reddit.com/.rss";

        request.get(url, function(err, httpResponse, body) {
            xml2js.parseString(body, function (err, rss) {

                rss.feed.entry.forEach(function(element) {
                    var content = element.content[0]["_"];
                    var link = content.substring(0, content.lastIndexOf("\">[link]"));
                    link = link.substring(link.lastIndexOf("href") + "href= ".length);
                    element.link[0]["$"].href = link;
                }, this);

                res.type("application/atom+xml").send(builder.buildObject(rss));
            });
        });
    }

    module.exports.vldocs = function(req, res) {

        var urltemplate = "http://www.microsoftvolumelicensing.com/DocumentSearch.aspx?Mode=3&DocumentTypeId={doctype}&Language={lang}";

        var documents = {
            SLA: 37,
            OST: 46,
            PT: 53
        };

        var languages = {
            English: 1,
            French: 9
        };

        var all = [];
        for (var d in documents) {
            for (var l in languages) {
                all.push([ d, l ]);
            }
        }

        var feed = new RSS({
            title:       'Volume licensing',
            description: 'VL documents',
            site_url :   'https://www.microsoft.com/en-us/licensing/product-licensing/products.aspx',
            ttl: 24*60 // 1 day
        });

        async.map(all, function(item, cb) {

            var url = urltemplate.replace("{doctype}", documents[item[0]]);
            url = url.replace("{lang}", languages[item[1]]);

            request.get(url, function(err, httpResponse, body) {
                if (err) return cb(err, null);

                $ = cheerio.load(body);
                var doc = $("#dgDocuments_ctl03_lnkTitle");
                var name = doc.text();
                var month = name.substring(name.lastIndexOf("(") + 1);
                month = month.substring(0, month.indexOf(")"));
                console.log(month);

                cb(null, {
                    id: name,
                    month: month,
                    title: name + ".docx",
                    url: "http://www.microsoftvolumelicensing.com/" + doc.attr("href")
                });
            });

        }, function(err, results) {

            results.forEach(function(doc) {
                if (doc != null) {
                    feed.item({
                        title: doc.id,
                        description: "See here",
                        url: "https://www.microsoft.com/en-us/licensing/product-licensing/products.aspx",
                        guid: doc.id,
                        date: moment().date(1).toDate(),
                        enclosure: {
                            url: doc.url,
                            type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                        }
                    });
                }
            }, this);

            res.type("application/atom+xml").send(feed.xml());
        });
    }

}());
<commit_msg>fix rss for vldocs<commit_after>(function(){

    var request = require("request");
    var xml2js = require('xml2js');
    var builder = new xml2js.Builder();

    var RSS = require('rss');
    var moment = require("moment");
    var async = require("async");
    var cheerio = require('cheerio');

    module.exports.reddit = function(req, res) {
        var url = "http://www.reddit.com/.rss";

        request.get(url, function(err, httpResponse, body) {
            xml2js.parseString(body, function (err, rss) {

                rss.feed.entry.forEach(function(element) {
                    var content = element.content[0]["_"];
                    var link = content.substring(0, content.lastIndexOf("\">[link]"));
                    link = link.substring(link.lastIndexOf("href") + "href= ".length);
                    element.link[0]["$"].href = link;
                }, this);

                res.type("application/atom+xml").send(builder.buildObject(rss));
            });
        });
    }

    module.exports.vldocs = function(req, res) {

        var urltemplate = "http://www.microsoftvolumelicensing.com/DocumentSearch.aspx?Mode=3&DocumentTypeId={doctype}&Language={lang}";

        var documents = {
            SLA: 37,
            OST: 46,
            PT: 53
        };

        var languages = {
            English: 1,
            French: 9
        };

        var all = [];
        for (var d in documents) {
            for (var l in languages) {
                all.push([ d, l ]);
            }
        }

        var feed = new RSS({
            title:       'Volume licensing',
            description: 'VL documents',
            site_url :   'https://www.microsoft.com/en-us/licensing/product-licensing/products.aspx',
            ttl: 24*60 // 1 day
        });

        async.map(all, function(item, cb) {

            var url = urltemplate.replace("{doctype}", documents[item[0]]);
            url = url.replace("{lang}", languages[item[1]]);

            request.get(url, function(err, httpResponse, body) {
                if (err) return cb(err, null);

                $ = cheerio.load(body);
                var doc = $("#dgDocuments_ctl03_lnkTitle");
                var name = doc.text();
                var month = name.substring(name.lastIndexOf("(") + 1);
                month = month.substring(0, month.indexOf(")"));
                console.log(month);

                cb(null, {
                    id: name,
                    month: month,
                    title: name + ".docx",
                    url: "http://www.microsoftvolumelicensing.com/" + doc.attr("href")
                });
            });

        }, function(err, results) {

            results.forEach(function(doc) {
                if (doc != null) {
                    feed.item({
                        title: doc.id,
                        description: "See here",
                        url: doc.url,
                        guid: doc.id,
                        date: moment().date(1).toDate(),
                        enclosure: {
                            url: doc.url,
                            type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                        }
                    });
                }
            }, this);

            res.type("application/atom+xml").send(feed.xml());
        });
    }

}());
<|endoftext|>


<commit_before>import Raven from 'raven-js';
import log from 'loglevel';

export default class Log {
  static trace(message) {
    log.trace(message);
  }

  static debug(message) {
    Raven.captureMessage(message, { level: 'info' });
    log.debug(message);
  }

  static info(message) {
    Raven.captureMessage(message, { level: 'info' });
    log.info(message);
  }

  static warn(message) {
    Raven.captureMessage(message, { level: 'warning' });
    log.info(message);
  }

  static error(message) {
    Raven.captureMessage(message, { level: 'error' });
    log.info(message);
  }
}
<commit_msg>OTI-304 Improved a bit our logger<commit_after>import Raven from 'raven-js';
import log from 'loglevel';

export default class Log {
  static trace(message) {
    log.trace(message);
  }

  static debug(message) {
    Raven.captureBreadcrumb({ message, level: 'debug' });
    log.debug(message);
  }

  static info(message) {
    Raven.captureBreadcrumb({ message, level: 'info' });
    log.info(message);
  }

  static warn(message) {
    Raven.captureBreadcrumb({ message, level: 'warn' });
    log.warn(message);
  }

  static error(message) {
    if (message instanceof Error) {
      Raven.captureException(message, { level: 'error' });
    } else {
      Raven.captureMessage(message, { level: 'error' });
    }
    log.error(message);
  }
}
<|endoftext|>


<commit_before>function PhotoViewModel(data) {
  var self = this;

  self.data = data;

  self.aspectRatio = function () {
    var width = self.data.width;
    var height = self.data.height;
    var gcd = _.gcd(width, height);

    return (width / gcd) + ':' + (height / gcd);
  };

  self.fileName = function () {
    return self.data.path.split('/').reverse()[0];
  };

  self.formattedFocalLength = function () {
    var fl = self.data.exif.FocalLength;
    var fl35 = self.data.exif.FocalLengthIn35mmFormat;

    if (!fl) {
      return;
    }

    fl = fl.replace('.0', '');

    if (!fl35) {
      return fl;
    }

    fl35 = fl35.replace('.0', '');

    if (fl === fl35) {
      return fl;
    }

    return fl + ' (' + fl35 + ')';
  };

  self.formattedSize =  function () {
    return _.formatSize(self.data.size);
  };

  self.formattedTakenAt = function () {
    return moment(self.data.takenAt).format('ddd, D MMM YYYY HH:mm:ss z');
  };

  self.relativeTakenAt = function () {
    return moment(self.data.takenAt).fromNow();
  };

  self.shortName = function () {
    return _.trunc(self.fileName(), 20);
  };
}

function SetViewModel(data) {
  var self = this;

  self.data = data;

  self.photosCountTitle = function () {
    return _.pluralize(self.data.photosCount, 'photo');
  };

  self.shortName = function () {
    return _.trunc(self.data.name, 20);
  };
}

function ThymeViewModel() {
  var self = this;

  self.photo = _.tap(ko.observable(), function (observable) {
    observable.subscribe(function (photo) {
      if (photo) {
        location.hash = photo.data.setId + '/' + photo.data.id;
      }
    });
  });

  self.photos = ko.observableArray([]);

  self.set = _.tap(ko.observable(), function (observable) {
    observable.subscribe(function (set) {
      location.hash = set.data.id;
    });
  });

  self.sets = ko.observableArray([]);

  Sammy(function () {
    this.get('#:setId/:photoId', function () {
      if (self.photo()) { return; } // clicked photo

      var data = {
        id: this.params.photoId,
        set_id: this.params.setId
      };

      $.getJSON('/photo', data, function (photoData) {
        self.photo(new PhotoViewModel(photoData));
      });
    });

    this.get('#:setId', function () {
      self.photo(null);

      if (self.photos().length > 0) { // back pressed
        return;
      }

      $.getJSON('/photos', { set_id: this.params.setId }, function (photosData) {
        _.forEach(photosData, function (photoData) {
          self.photos.push(new PhotoViewModel(photoData));
        });
      });
    });

    this.get('', function () {
      self.photos([]);

      if (self.sets().length > 0) { // back pressed
        return;
      }

      $.getJSON('/sets', function (setsData) {
        _.forEach(setsData, function (setData) {
          self.sets.push(new SetViewModel(setData));
        });
      });
    });
  }).run();
};

// lodash extensions
_.mixin({
  formatSize: function (bytes) {
    var n = bytes;

    if (n < 1024) {
      return _.pluralize(n, 'byte');
    }

    n /= 1024; // kB

    if (n < 1024) {
      return _.round(n, 2) + ' kB';
    }

    n /= 1024; // MB

    return _.round(n, 2) + ' MB';
  },
  gcd: function (a, b) {
    return b ? _.gcd(b, a % b) : Math.abs(a);
  },
  pluralize: function (n, singular, plural) {
    plural = plural || singular + 's';
    return n + ' ' + (n === 1 ? singular : plural);
  },
  round: function (n, scale) {
    return Math.round(n * Math.pow(10, scale)) / Math.pow(10, scale);
  }
});

ko.applyBindings(new ThymeViewModel());
<commit_msg>Show closest aspect ratio if not standard<commit_after>function PhotoViewModel(data) {
  var self = this;

  self.stdAspectRatios = [[4, 3], [3, 2], [16, 9], [5, 3], [5, 4], [1, 1]];

  self.data = data;

  self.aspectRatio = function () {
    var aspectRatio = self.calculateAspectRatio(self.data.width, self.data.height);
    var exactMatch = _.find(self.stdAspectRatios, function (ar) {
      return ar[0] == aspectRatio[0] && ar[1] == aspectRatio[1];
    });

    if (exactMatch) { return aspectRatio.join(':'); }

    var closestMatch = _.sortBy(self.stdAspectRatios, function (ar) {
      return Math.abs((ar[0] / ar[1]) - (aspectRatio[0] / aspectRatio[1]));
    })[0];

    return '~' + closestMatch.join(':');
  };

  self.calculateAspectRatio = function (width, height) {
    var gcd = _.gcd(width, height);
    return [width / gcd, height / gcd];
  };

  self.fileName = function () {
    return self.data.path.split('/').reverse()[0];
  };

  self.formattedFocalLength = function () {
    var fl = self.data.exif.FocalLength;
    var fl35 = self.data.exif.FocalLengthIn35mmFormat;

    if (!fl) {
      return;
    }

    fl = fl.replace('.0', '');

    if (!fl35) {
      return fl;
    }

    fl35 = fl35.replace('.0', '');

    if (fl === fl35) {
      return fl;
    }

    return fl + ' (' + fl35 + ')';
  };

  self.formattedSize =  function () {
    return _.formatSize(self.data.size);
  };

  self.formattedTakenAt = function () {
    return moment(self.data.takenAt).format('ddd, D MMM YYYY HH:mm:ss z');
  };

  self.relativeTakenAt = function () {
    return moment(self.data.takenAt).fromNow();
  };

  self.shortName = function () {
    return _.trunc(self.fileName(), 20);
  };
}

function SetViewModel(data) {
  var self = this;

  self.data = data;

  self.photosCountTitle = function () {
    return _.pluralize(self.data.photosCount, 'photo');
  };

  self.shortName = function () {
    return _.trunc(self.data.name, 20);
  };
}

function ThymeViewModel() {
  var self = this;

  self.photo = _.tap(ko.observable(), function (observable) {
    observable.subscribe(function (photo) {
      if (photo) {
        location.hash = photo.data.setId + '/' + photo.data.id;
      }
    });
  });

  self.photos = ko.observableArray([]);

  self.set = _.tap(ko.observable(), function (observable) {
    observable.subscribe(function (set) {
      location.hash = set.data.id;
    });
  });

  self.sets = ko.observableArray([]);

  Sammy(function () {
    this.get('#:setId/:photoId', function () {
      if (self.photo()) { return; } // clicked photo

      var data = {
        id: this.params.photoId,
        set_id: this.params.setId
      };

      $.getJSON('/photo', data, function (photoData) {
        self.photo(new PhotoViewModel(photoData));
      });
    });

    this.get('#:setId', function () {
      self.photo(null);

      if (self.photos().length > 0) { // back pressed
        return;
      }

      $.getJSON('/photos', { set_id: this.params.setId }, function (photosData) {
        _.forEach(photosData, function (photoData) {
          self.photos.push(new PhotoViewModel(photoData));
        });
      });
    });

    this.get('', function () {
      self.photos([]);

      if (self.sets().length > 0) { // back pressed
        return;
      }

      $.getJSON('/sets', function (setsData) {
        _.forEach(setsData, function (setData) {
          self.sets.push(new SetViewModel(setData));
        });
      });
    });
  }).run();
};

// lodash extensions
_.mixin({
  formatSize: function (bytes) {
    var n = bytes;

    if (n < 1024) {
      return _.pluralize(n, 'byte');
    }

    n /= 1024; // kB

    if (n < 1024) {
      return _.round(n, 2) + ' kB';
    }

    n /= 1024; // MB

    return _.round(n, 2) + ' MB';
  },
  gcd: function (a, b) {
    return b ? _.gcd(b, a % b) : Math.abs(a);
  },
  pluralize: function (n, singular, plural) {
    plural = plural || singular + 's';
    return n + ' ' + (n === 1 ? singular : plural);
  },
  round: function (n, scale) {
    return Math.round(n * Math.pow(10, scale)) / Math.pow(10, scale);
  }
});

ko.applyBindings(new ThymeViewModel());
<|endoftext|>


<commit_before>var child_process = require('child_process');
var fs = require('fs');
var path = require('path');
var rimraf = require('rimraf');
var temp = require('temp');
var url = require('url');

function convertHarEntriesToRequests (harObject) {
  var requests = [];
  var excludedRequests = [];

  harObject.log.entries.forEach(function (entry, index) {
    var parsedUrl = url.parse(entry.request.url);
    if (parsedUrl.protocol != 'http:') {
      excludedRequests.push({entryIndex: index, reason: 'Unsupported', message: 'Protocol not supported: ' + parsedUrl.protocol});
    } else if (entry.request.httpVersion != 'HTTP/1.0' && entry.request.httpVersion != 'HTTP/1.1') {
      excludedRequests.push({entryIndex: index, reason: 'Unsupported', message: 'HTTP version not supported: ' + entry.request.httpVersion});
    } else if (entry.request.method != 'GET') {
      excludedRequests.push({entryIndex: index, reason: 'Unsupported', message: 'Method not supported: ' + entry.request.method});
    } else {
      var warnings = [];
      var payload = entry.request.method + ' ' + parsedUrl.path + ' ' + entry.request.httpVersion + '\r\n';
      entry.request.headers.forEach(function (header) {
        if (header.name.toLowerCase() == 'connection') {
          warnings.push('Connection request header not supported.');
        } else {
          payload += header.name + ': ' + header.value + '\r\n';
        }
      });
      payload += '\r\n';
      requests.push({entryIndex: index, payload: payload, warnings: warnings});
    }
  });

  return {
    requests: requests,
    excludedRequests: excludedRequests
  };
}

function countdownCallback(count, onZeroCallback) {
  return function () {
    count--;
    if (count == 0) onZeroCallback();
  };
}

function writeInputFiles (dirPath, requests, vclText, callback) {

    fs.writeFile(path.join(dirPath, 'default.vcl'), vclText, function (err) {
      if (err) return callback(err);

      var success = countdownCallback(requests.length, callback);
      requests.forEach(function (r) {

        var filename = 'request_' + ('000' + r.entryIndex).slice(-3);
        fs.writeFile(path.join(dirPath, filename), r.payload, function (err) {
          if (err) return callback(err);
          success();
        });

      });

    });

}

function runContainer (dirPath, callback) {

  var dockerTimeoutMillseconds = 30 * 1000;
  var dockerImageName = 'varnish4';
  var dockerArgs = ['run', '--rm', '--volume=' + dirPath + ':/fiddle', dockerImageName];
  child_process.execFile('/usr/bin/docker', dockerArgs, {timeout: dockerTimeoutMillseconds}, function(err, stdout, stderr) {
    if (err) return callback(err);

    sails.log.debug('Docker stdout: ' + stdout);
    sails.log.error('Docker stderr: ' + stderr);

    callback(null);
  });

}

function readOutputFiles(dirPath, callback) {

  fs.readFile(path.join(dirPath, 'run.log'), function (err, runlog) {
    if (err) return callback(err);

    fs.readFile(path.join(dirPath, 'varnishlog'), function (err, varnishlog) {

      callback(null, {runlog: runlog, varnishlog: varnishlog});

    });

  });

}

module.exports = {

  replayHarWithVcl: function (harObject, vclText, callback) {
    allRequests = convertHarEntriesToRequests(harObject); // TODO move this function implementation to another service

    temp.mkdir('fiddle', function (err, dirPath) {
      sails.log.debug()

      if (err) return callback(err);

      if (allRequests.requests.length == 0) return callback('HAR does not contain any supported entry requests');

      writeInputFiles(dirPath, allRequests.requests, vclText, function (err) {

        if (err) return callback(err);

        runContainer(dirPath, function (err) {

          if (err) return callback(err);

          readOutputFiles(dirPath, function (err, output) {

            if (err) return callback(err);

            rimraf(dirPath, function () {}); // TODO clean up old failed temp dirs after investigation

            callback(null, output);

          });

        });

      });

    });

  }

};<commit_msg>Be explicit about encoding on read to get a string instead of a Buffer.<commit_after>var child_process = require('child_process');
var fs = require('fs');
var path = require('path');
var rimraf = require('rimraf');
var temp = require('temp');
var url = require('url');

function convertHarEntriesToRequests (harObject) {
  var requests = [];
  var excludedRequests = [];

  harObject.log.entries.forEach(function (entry, index) {
    var parsedUrl = url.parse(entry.request.url);
    if (parsedUrl.protocol != 'http:') {
      excludedRequests.push({entryIndex: index, reason: 'Unsupported', message: 'Protocol not supported: ' + parsedUrl.protocol});
    } else if (entry.request.httpVersion != 'HTTP/1.0' && entry.request.httpVersion != 'HTTP/1.1') {
      excludedRequests.push({entryIndex: index, reason: 'Unsupported', message: 'HTTP version not supported: ' + entry.request.httpVersion});
    } else if (entry.request.method != 'GET') {
      excludedRequests.push({entryIndex: index, reason: 'Unsupported', message: 'Method not supported: ' + entry.request.method});
    } else {
      var warnings = [];
      var payload = entry.request.method + ' ' + parsedUrl.path + ' ' + entry.request.httpVersion + '\r\n';
      entry.request.headers.forEach(function (header) {
        if (header.name.toLowerCase() == 'connection') {
          warnings.push('Connection request header not supported.');
        } else {
          payload += header.name + ': ' + header.value + '\r\n';
        }
      });
      payload += '\r\n';
      requests.push({entryIndex: index, payload: payload, warnings: warnings});
    }
  });

  return {
    requests: requests,
    excludedRequests: excludedRequests
  };
}

function countdownCallback(count, onZeroCallback) {
  return function () {
    count--;
    if (count == 0) onZeroCallback();
  };
}

function writeInputFiles (dirPath, requests, vclText, callback) {

    fs.writeFile(path.join(dirPath, 'default.vcl'), vclText, function (err) {
      if (err) return callback(err);

      var success = countdownCallback(requests.length, callback);
      requests.forEach(function (r) {

        var filename = 'request_' + ('000' + r.entryIndex).slice(-3);
        fs.writeFile(path.join(dirPath, filename), r.payload, function (err) {
          if (err) return callback(err);
          success();
        });

      });

    });

}

function runContainer (dirPath, callback) {

  var dockerTimeoutMillseconds = 30 * 1000;
  var dockerImageName = 'varnish4';
  var dockerArgs = ['run', '--rm', '--volume=' + dirPath + ':/fiddle', dockerImageName];
  child_process.execFile('/usr/bin/docker', dockerArgs, {timeout: dockerTimeoutMillseconds}, function(err, stdout, stderr) {
    if (err) return callback(err);

    sails.log.debug('Docker stdout: ' + stdout);
    sails.log.error('Docker stderr: ' + stderr);

    callback(null);
  });

}

function readOutputFiles(dirPath, callback) {

  fs.readFile(path.join(dirPath, 'run.log'), { encoding: "utf8" }, function (err, runlog) {
    if (err) return callback(err);

    fs.readFile(path.join(dirPath, 'varnishlog'), { encoding: "utf8" }, function (err, varnishlog) {

      callback(null, {runlog: runlog, varnishlog: varnishlog});

    });

  });

}

module.exports = {

  replayHarWithVcl: function (harObject, vclText, callback) {
    allRequests = convertHarEntriesToRequests(harObject); // TODO move this function implementation to another service

    temp.mkdir('fiddle', function (err, dirPath) {
      sails.log.debug()

      if (err) return callback(err);

      if (allRequests.requests.length == 0) return callback('HAR does not contain any supported entry requests');

      writeInputFiles(dirPath, allRequests.requests, vclText, function (err) {

        if (err) return callback(err);

        runContainer(dirPath, function (err) {

          if (err) return callback(err);

          readOutputFiles(dirPath, function (err, output) {

            if (err) return callback(err);

            rimraf(dirPath, function () {}); // TODO clean up old failed temp dirs after investigation

            callback(null, output);

          });

        });

      });

    });

  }

};<|endoftext|>


<commit_before>// ==UserScript==
// @name        GitHub Download ZIP
// @version     0.1.3
// @description A userscript adds download links so that downloaded filenames include the SHA
// @license     MIT
// @author      Rob Garrison
// @namespace   https://github.com/Mottie
// @include     https://github.com/*
// @run-at      document-idle
// @grant       none
// @require     https://greasyfork.org/scripts/28721-mutations/code/mutations.js?version=666427
// @icon        https://github.githubassets.com/pinned-octocat.svg
// @updateURL   https://raw.githubusercontent.com/Mottie/Github-userscripts/master/github-download-zip.user.js
// @downloadURL https://raw.githubusercontent.com/Mottie/Github-userscripts/master/github-download-zip.user.js
// ==/UserScript==
(() => {
	"use strict";

	const zipIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="16" height="16" class="octicon" style="vertical-align:text-top;margin-left:4px">
		<path d="M28.7 7.2a28.4 28.4 0 0 0-5.9-5.9C21.2.1 20.4 0 20 0H4.5A2.5 2.5 0 0 0 2 2.5v27C2 30.9 3.1 32 4.5 32h23c1.4 0 2.5-1.1 2.5-2.5V10c0-.4-.1-1.2-1.3-2.8zm-4.2-1.7c1 1 1.8 1.8 2.3 2.5H22V3.2c.7.5 1.6 1.3 2.5 2.3zm3.5 24c0 .3-.2.5-.5.5h-23a.5.5 0 0 1-.5-.5v-27c0-.3.2-.5.5-.5H20v7c0 .6.4 1 1 1h7v19.5z"/>
		<path d="M8 2h4v2H8V2zM12 4h4v2h-4V4zM8 6h4v2H8V6zM12 8h4v2h-4V8zM8 10h4v2H8v-2zM12 12h4v2h-4v-2zM8 14h4v2H8v-2zM12 16h4v2h-4v-2zM8 26.5c0 .8.7 1.5 1.5 1.5h5c.8 0 1.5-.7 1.5-1.5v-5c0-.8-.7-1.5-1.5-1.5H12v-2H8v8.5zm6-2.5v2h-4v-2h4z"/>
	</svg>`;
	const span = document.createElement("span");
	span.innerHTML = zipIcon;

	const link = document.createElement("a");
	link.className = "btn btn-outline BtnGroup-item tooltipped tooltipped-s ghdz-btn";
	link.setAttribute("aria-label", "Download ZIP");
	link.innerHTML = zipIcon;

	function buildURL(part) {
		const [, user, repo] = window.location.pathname.split("/");
		return `https://api.github.com/repos/${user}/${repo}/zipball/${part}`;
	}

	function updateLinks() {
		// Branch dropdown on main repo page
		const branch = $("summary[data-hotkey='w']");
		// Download link in "Clone or Download" dropdown
		const downloadLink = $("a[data-ga-click*='download zip']");
		// Repo commits page
		const commits = $(".commits-listing");

		if (downloadLink && branch) {
			downloadLink.href = buildURL(branch.title.trim());
			downloadLink.appendChild(span.cloneNode(true));
		}
		// Branch doesn't matter when you're using the SHA (first 7 values)
		if (commits) {
			[...document.querySelectorAll(".commit-group .commit .commit-links-group")].forEach(group => {
				if (!$(".ghdz-btn", group)) {
					const sha = $(".sha", group).textContent.trim();
					const a = link.cloneNode(true);
					a.href = buildURL(sha);
					group.appendChild(a);
				}
			});
		}
	}

	function $(selector, el) {
		return (el || document).querySelector(selector);
	}

	// DOM targets - to detect GitHub dynamic ajax page loading
	document.addEventListener("ghmo:container", updateLinks);
	updateLinks();

})();
<commit_msg>Download-zip: Add release links dropdown. Closes #62<commit_after>// ==UserScript==
// @name        GitHub Download ZIP
// @version     0.2.0
// @description A userscript adds download links so that downloaded filenames include the SHA
// @license     MIT
// @author      Rob Garrison
// @namespace   https://github.com/Mottie
// @include     https://github.com/*
// @run-at      document-idle
// @grant       GM_addStyle
// @grant       GM.addStyle
// @grant       GM_xmlhttpRequest
// @grant       GM.xmlHttpRequest
// @connect     api.github.com
// @connect     assets-cdn.github.com
// @require     https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?updated=20180103
// @require     https://greasyfork.org/scripts/28721-mutations/code/mutations.js?version=666427
// @icon        https://github.githubassets.com/pinned-octocat.svg
// @updateURL   https://raw.githubusercontent.com/Mottie/Github-userscripts/master/github-download-zip.user.js
// @downloadURL https://raw.githubusercontent.com/Mottie/Github-userscripts/master/github-download-zip.user.js
// ==/UserScript==
(() => {
	"use strict";

	GM.addStyle(`
		.ghdz-releases { width:100% !important; padding:10px; }
		.ghdz-releases summary { text-align:left; padding-left:16px; }
		.ghdz-files { width:100%; border:0; box-shadow:none; margin-bottom:0; }
		.ghdz-file { text-align:left; }
	`);

	const zipIcon = `
		<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="16" height="16" class="octicon" style="vertical-align:text-top;margin-left:4px">
			<path d="M28.7 7.2a28.4 28.4 0 0 0-5.9-5.9C21.2.1 20.4 0 20 0H4.5A2.5 2.5 0 0 0 2 2.5v27C2 30.9 3.1 32 4.5 32h23c1.4 0 2.5-1.1 2.5-2.5V10c0-.4-.1-1.2-1.3-2.8zm-4.2-1.7c1 1 1.8 1.8 2.3 2.5H22V3.2c.7.5 1.6 1.3 2.5 2.3zm3.5 24c0 .3-.2.5-.5.5h-23a.5.5 0 0 1-.5-.5v-27c0-.3.2-.5.5-.5H20v7c0 .6.4 1 1 1h7v19.5z"/>
			<path d="M8 2h4v2H8V2zM12 4h4v2h-4V4zM8 6h4v2H8V6zM12 8h4v2h-4V8zM8 10h4v2H8v-2zM12 12h4v2h-4v-2zM8 14h4v2H8v-2zM12 16h4v2h-4v-2zM8 26.5c0 .8.7 1.5 1.5 1.5h5c.8 0 1.5-.7 1.5-1.5v-5c0-.8-.7-1.5-1.5-1.5H12v-2H8v8.5zm6-2.5v2h-4v-2h4z"/>
		</svg>`;
	const span = document.createElement("span");
	span.innerHTML = zipIcon;

	const link = document.createElement("a");
	link.className = "btn btn-outline BtnGroup-item tooltipped tooltipped-s ghdz-btn";
	link.setAttribute("aria-label", "Download ZIP");
	link.innerHTML = zipIcon;

	const div = document.createElement("details");
	div.className = "select-menu get-repo-btn ghdz-releases";
	div.innerHTML = `

			Latest Release Files

		`;

	function buildURL(part) {
		const [, user, repo] = window.location.pathname.split("/");
		return `https://api.github.com/repos/${user}/${repo}/zipball/${part}`;
	}

	function buildReleases(assets, container) {
		let html = "";
		if (Array.isArray(assets)) {
			assets.forEach(release => {
				const url = release.browser_download_url;
				html += `

						${url.split("/").slice(-1)}
					`;
			});
		} else {
			html = assets;
		}
		$(".ghdz-files", container).innerHTML = html;
	}

	function getReleases(container) {
		if ($(".ghdz-file", container)) {
			// Already loaded
			return;
		}
		const [, user, repo] = window.location.pathname.split("/");
		GM.xmlHttpRequest({
			method : "GET",
			url : `https://api.github.com/repos/${user}/${repo}/releases`,
			onload : response => {
				if (response.status !== 200) {
					buildReleases(response.message, container);
					return console.error(response);
				}
				let json = false;
				try {
					json = JSON.parse(response.responseText);
				} catch (err) {
					return console.error(response);
				}
				if (json && json[0] && json[0].assets) {
					buildReleases(json[0].assets, container);
				}
			}
		});
	}

	function addBindings() {
		document.addEventListener("click", function(event) {
			const target = event.target.closest("details");
			if (target.classList.contains("ghdz-releases")) {
				getReleases(target);
			}
		});
	}

	function updateLinks() {
		// Branch dropdown on main repo page
		const branch = $("summary[data-hotkey='w']");
		// Download link in "Clone or Download" dropdown
		const downloadLink = $("a[data-ga-click*='download zip']");
		// Repo commits page
		const commits = $(".commits-listing");

		if (downloadLink && branch && !$(".ghdz-releases", downloadLink.parentNode)) {
			downloadLink.href = buildURL(branch.title.trim());
			downloadLink.appendChild(span.cloneNode(true));
			downloadLink.after(div.cloneNode(true));
		}
		// Branch doesn't matter when you're using the SHA (first 7 values)
		if (commits) {
			[...document.querySelectorAll(".commit-group .commit .commit-links-group")].forEach(group => {
				if (!$(".ghdz-btn", group)) {
					const sha = $(".sha", group).textContent.trim();
					const a = link.cloneNode(true);
					a.href = buildURL(sha);
					group.appendChild(a);
				}
			});
		}
	}

	function $(selector, el) {
		return (el || document).querySelector(selector);
	}

	// DOM targets - to detect GitHub dynamic ajax page loading
	document.addEventListener("pjax:end", updateLinks);
	updateLinks();
	addBindings();

})();
<|endoftext|>


<commit_before>var properties = require('./src/js/game/properties.js')

module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-browserify')
  grunt.loadNpmTasks('grunt-cache-bust')
  grunt.loadNpmTasks('grunt-contrib-clean')
  grunt.loadNpmTasks('grunt-contrib-compress')
  grunt.loadNpmTasks('grunt-contrib-connect')
  grunt.loadNpmTasks('grunt-contrib-copy')
  grunt.loadNpmTasks('grunt-contrib-jade')
  grunt.loadNpmTasks('grunt-contrib-jshint')
  grunt.loadNpmTasks('grunt-contrib-stylus')
  grunt.loadNpmTasks('grunt-contrib-uglify')
  grunt.loadNpmTasks('grunt-contrib-watch')
  grunt.loadNpmTasks('grunt-open')
  grunt.loadNpmTasks('grunt-pngmin')

  var productionBuild = !!(grunt.cli.tasks.length && grunt.cli.tasks[0] === 'build')

  grunt.initConfig(
    { pkg: grunt.file.readJSON('package.json')

    , project:
      { src: 'src/js'
      , js: '<%= project.src %>/game/{,*/}*.js'
      , dest: 'build/js'
      , bundle: 'build/js/app.min.js'
      , port: properties.port
      , banner:
        '/*!\n' +
        ' * <%= pkg.title %>\n' +
        ' * <%= pkg.description %>\n' +
        ' * <%= pkg.url %>\n' +
        ' * @author <%= pkg.author %>\n' +
        ' * @version <%= pkg.version %>\n' +
        ' * Copyright <%= pkg.author %>. <%= pkg.license %> licensed.\n' +
        ' * Made using Phaser Blank <https://github.com/lukewilde/phaser-blank/>\n' +
        ' */\n'
      }

    , connect:
      { dev:
        { options:
          { port: '<%= project.port %>'
          , base: './build'
          }
        }
      }

    , jshint:
      { files:
        [ 'gruntfile.js'
        , '<%= project.js %>'
        ]
      , options:
        { jshintrc: '.jshintrc'
        }
      }

    , watch:
      { options:
        { livereload: !productionBuild
        }
      , js:
        { files: '<%= project.dest %>/**/*.js'
        }
      , jade:
        { files: 'src/templates/*.jade'
        , tasks: ['jade']
        }
      , stylus:
        { files: 'src/style/*.styl'
        , tasks: ['stylus']
        }
      , images:
        { files: 'src/images/**/*'
        , tasks: ['copy:images']
        }
      }

    , browserify:
      { app:
        { src: ['<%= project.src %>/game/app.js']
        , dest: '<%= project.bundle %>'
        , options:
          { transform: ['browserify-shim']
          , watch: true
          , bundleOptions:
            { debug: !productionBuild
            }
          }
        }
      }

    , open:
      { server:
        { path: 'http://localhost:<%= project.port %>'
        }
      }

    , cacheBust:
      { options:
        { encoding: 'utf8'
        , algorithm: 'md5'
        , length: 8
        }
      , assets:
        { files:
          [ { src:
              [ 'build/index.html'
              , '<%= project.bundle %>'
              ]
            }
          ]
        }
      }

    , jade:
      { compile:
        { options:
          { data:
            { properties: properties
            , productionBuild: productionBuild
            }
          }
        , files:
          { 'build/index.html': ['src/templates/index.jade']
          }
        }
      }

    , stylus:
      { compile:
        { files:
          { 'build/style/game.css': ['src/style/*.styl'] }
        , options:
          { sourcemaps: !productionBuild
          }
        }
      }

    , clean: ['./build/']

    , pngmin:
      { options:
        { ext: '.png'
        , force: true
        }
      , compile:
        { files:
            [ { src: 'src/images/*.png'
              , dest: 'src/images/'
              }
            ]
          }
        }

    , copy:
      { images:
        { files:
          [ { expand: true, cwd: 'src/images/', src: ['**'], dest: 'build/images/' }
          ]
        }
      }

    , uglify:
      { options:
        { banner: '<%= project.banner %>'
        }
      , dist:
        { files:
          { '<%= project.bundle %>': '<%= project.bundle %>'
          }
        }
      }

    , compress:
      { options:
        { archive: 'build/build.zip'
        }
      , main:
        { files: [ { expand: true, cwd: 'build/', src: ['**/*'], dest: 'build/' } ]
        }
      }
    }
  )

  grunt.registerTask('default',
    [ 'clean'
    , 'browserify'
    , 'jade'
    , 'stylus'
    , 'copy:images'
    , 'cacheBust'
    , 'connect'
    , 'open'
    , 'watch'
    ]
  )

  grunt.registerTask('build',
    [ 'jshint'
    , 'clean'
    , 'browserify'
    , 'jade'
    , 'stylus'
    , 'uglify'
    , 'copy:images'
    , 'cacheBust'
    , 'connect'
    , 'open'
    , 'watch'
    ]
  )

  grunt.registerTask('optimise', ['pngmin'])
}
<commit_msg>Adjusting image compression task.<commit_after>var properties = require('./src/js/game/properties.js')

module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-browserify')
  grunt.loadNpmTasks('grunt-cache-bust')
  grunt.loadNpmTasks('grunt-contrib-clean')
  grunt.loadNpmTasks('grunt-contrib-compress')
  grunt.loadNpmTasks('grunt-contrib-connect')
  grunt.loadNpmTasks('grunt-contrib-copy')
  grunt.loadNpmTasks('grunt-contrib-jade')
  grunt.loadNpmTasks('grunt-contrib-jshint')
  grunt.loadNpmTasks('grunt-contrib-stylus')
  grunt.loadNpmTasks('grunt-contrib-uglify')
  grunt.loadNpmTasks('grunt-contrib-watch')
  grunt.loadNpmTasks('grunt-open')
  grunt.loadNpmTasks('grunt-pngmin')

  var productionBuild = !!(grunt.cli.tasks.length && grunt.cli.tasks[0] === 'build')

  grunt.initConfig(
    { pkg: grunt.file.readJSON('package.json')

    , project:
      { src: 'src/js'
      , js: '<%= project.src %>/game/{,*/}*.js'
      , dest: 'build/js'
      , bundle: 'build/js/app.min.js'
      , port: properties.port
      , banner:
        '/*!\n' +
        ' * <%= pkg.title %>\n' +
        ' * <%= pkg.description %>\n' +
        ' * <%= pkg.url %>\n' +
        ' * @author <%= pkg.author %>\n' +
        ' * @version <%= pkg.version %>\n' +
        ' * Copyright <%= pkg.author %>. <%= pkg.license %> licensed.\n' +
        ' * Made using Phaser Blank <https://github.com/lukewilde/phaser-blank/>\n' +
        ' */\n'
      }

    , connect:
      { dev:
        { options:
          { port: '<%= project.port %>'
          , base: './build'
          }
        }
      }

    , jshint:
      { files:
        [ 'gruntfile.js'
        , '<%= project.js %>'
        ]
      , options:
        { jshintrc: '.jshintrc'
        }
      }

    , watch:
      { options:
        { livereload: !productionBuild
        }
      , js:
        { files: '<%= project.dest %>/**/*.js'
        }
      , jade:
        { files: 'src/templates/*.jade'
        , tasks: ['jade']
        }
      , stylus:
        { files: 'src/style/*.styl'
        , tasks: ['stylus']
        }
      , images:
        { files: 'src/images/**/*'
        , tasks: ['copy:images']
        }
      }

    , browserify:
      { app:
        { src: ['<%= project.src %>/game/app.js']
        , dest: '<%= project.bundle %>'
        , options:
          { transform: ['browserify-shim']
          , watch: true
          , bundleOptions:
            { debug: !productionBuild
            }
          }
        }
      }

    , open:
      { server:
        { path: 'http://localhost:<%= project.port %>'
        }
      }

    , cacheBust:
      { options:
        { encoding: 'utf8'
        , algorithm: 'md5'
        , length: 8
        }
      , assets:
        { files:
          [ { src:
              [ 'build/index.html'
              , '<%= project.bundle %>'
              ]
            }
          ]
        }
      }

    , jade:
      { compile:
        { options:
          { data:
            { properties: properties
            , productionBuild: productionBuild
            }
          }
        , files:
          { 'build/index.html': ['src/templates/index.jade']
          }
        }
      }

    , stylus:
      { compile:
        { files:
          { 'build/style/game.css': ['src/style/*.styl'] }
        , options:
          { sourcemaps: !productionBuild
          }
        }
      }

    , clean: ['./build/']

    , pngmin:
      { options:
        { ext: '.png'
        , force: true
        }
      , compile:
        { files:
            [ { src: 'build/images/*.png'
              , dest: 'build/images/'
              }
            ]
          }
        }

    , copy:
      { images:
        { files:
          [ { expand: true, cwd: 'src/images/', src: ['**'], dest: 'build/images/' }
          ]
        }
      }

    , uglify:
      { options:
        { banner: '<%= project.banner %>'
        }
      , dist:
        { files:
          { '<%= project.bundle %>': '<%= project.bundle %>'
          }
        }
      }

    , compress:
      { options:
        { archive: 'build/build.zip'
        }
      , main:
        { files: [ { expand: true, cwd: 'build/', src: ['**/*'], dest: 'build/' } ]
        }
      }
    }
  )

  grunt.registerTask('default',
    [ 'clean'
    , 'browserify'
    , 'jade'
    , 'stylus'
    , 'copy:images'
    , 'cacheBust'
    , 'connect'
    , 'open'
    , 'watch'
    ]
  )

  grunt.registerTask('build',
    [ 'jshint'
    , 'clean'
    , 'browserify'
    , 'jade'
    , 'stylus'
    , 'uglify'
    , 'copy:images'
    , 'cacheBust'
    , 'connect'
    , 'open'
    , 'watch'
    ]
  )

  grunt.registerTask('optimise', ['pngmin'])
}
<|endoftext|>


<commit_before>import AppDispatcher from '../dispatcher/AppDispatcher';
import ProvideConstants from '../constants/ProvideConstants';

import BaseStore from './BaseStore';
import Toastr from 'toastr';
import Auth0 from 'auth0-js';
import Auth0Lock from 'auth0-lock'
import { isTokenExpired } from './jwtHelper'
import _ from 'lodash';

class LayoutStore extends BaseStore {

    constructor() {
        super();
        this.subscribe(() => this._registerToActions.bind(this))

        this._error = null;
        this._isLoggin = false;
        this._isAdmin = false;
        this._profile = {};

        // Configure Auth0 workaround to hash value when it's connected
        this.auth0 = new Auth0({
          clientID: process.env.AUTH_CLIENT_ID,
          domain: process.env.AUTH_AUDIENCE,
          responseType: 'token'
        });
        const options = {
            closable: false,
            language: 'en',
            auth: {
               responseType: "token",
           },
           languageDictionary: {
               title: "Qover",
           }
            };
        this.lock = new Auth0Lock(process.env.AUTH_CLIENT_ID, process.env.AUTH_AUDIENCE, options);

        // Add callback for lock `authenticated` event
        // this.lock.on('authenticated', this._doAuthentication.bind(this));
        // this.lock.on('hash_parsed', this._doAuthentication.bind(this) );

        // binds login functions to keep this context
        this.login = this.login.bind(this);
    }

  login() {
    // Call the show method to display the widget.
    this.lock.show();
  }

    _doAuthentication(authResult) {
        if (!_.isNil(authResult)) {
            this.setAccessToken(authResult.accessToken)
            this.setToken(authResult.idToken );
            this.lock.getUserInfo(authResult.accessToken, (error, userDetail) => {
                if (error) {
                    // callback(error);
                } else {
                    this.setUser(userDetail);
                    // in order to emit the profile
                    this.emitChange();
                }
            });
        }
    }

  _registerToActions(action) {
      this._error = null;

        switch(action.type){
            // Respond to RECEIVE_DATA action
            case ProvideConstants.DATA_ERROR:
                // If action was responded to, emit change event
                if ( !_.isNil(action.error.response) ) {
                    this._error = action.error.data;
                } else if ( !_.isNil(action.error.data) ) {
                    this._error = action.error.data;
                } else {
                    this._error = action.error.message;
                }

                Toastr.error(this._error);

                this.emitChange();
                break;
            case ProvideConstants.LOGIN_USER:
                this.setUser(action.profile);

                this.emitChange();
                break;
            case ProvideConstants.LOGOUT_USER:
                this.removeUser();

                this.emitChange();
                break;

            default:
                break;
        }

  }

    get stateLog() {
        return {
            lock: this.login()
        }
    }

    get stateLayout() {
        return {
            profile: this.getProfile,
            token: this.getToken,
            loggedIn: this.loggedIn,
            lock: this.getLock,
        };
    }

    get getProfile() {
        if ( localStorage.getItem('_profile') ) {
            return JSON.parse(localStorage.getItem('_profile') );
        } else {
            return this._profile;
        }
    }

    get loggedIn() {
        // Checks if there is a saved token and it's still valid
      const token = this.getToken;
      const isTokenExp= isTokenExpired(token);

      if (isTokenExp) {
          this.removeUser();
      }
      return !!token && !isTokenExp;
    }

    setToken(idToken) {
        if (!_.isNil(idToken)) {
            // Saves user token to local storage
            localStorage.setItem('id_token', idToken);
        }
    }

    setAccessToken(accessToken) {
        if (!_.isNil(accessToken)) {
            // Saves user token to local storage
            localStorage.setItem('accessToken', accessToken);
        }
    }

    get getToken() {
      // Retrieves the user token from local storage
      return localStorage.getItem('id_token');
    }

    setUser(profile) {
        localStorage.setItem('_profile', JSON.stringify(profile));
    }

    removeUser() {
        localStorage.removeItem('accessToken');
        localStorage.removeItem('id_token');
        localStorage.removeItem('_profile');
    }

    get getLock() {
        return this.lock ;
    }

    parseHash(hash) {
        if (/access_token|id_token|error/.test(hash)) {
            const authResult = this.auth0.parseHash(hash);
            // uses auth0 parseHash method to extract data from url hash
            //   const authResult = this.auth0.parseHash(hash);
            this._doAuthentication(authResult);
            return true;
        } else {
            return false;
        }
    }

}
export default new LayoutStore();
<commit_msg>Update LayoutStore.js<commit_after>import AppDispatcher from '../dispatcher/AppDispatcher';
import ProvideConstants from '../constants/ProvideConstants';

import BaseStore from './BaseStore';
import Toastr from 'toastr';
import Auth0 from 'auth0-js';
import Auth0Lock from 'auth0-lock'
import { isTokenExpired } from './jwtHelper'
import _ from 'lodash';

class LayoutStore extends BaseStore {

    constructor() {
        super();
        this.subscribe(() => this._registerToActions.bind(this))

        this._error = null;
        this._isLoggin = false;
        this._isAdmin = false;
        this._profile = {};

        // Configure Auth0 workaround to hash value when it's connected
        this.auth0 = new Auth0({
          clientID: process.env.AUTH_CLIENT_ID,
          domain: process.env.AUTH_AUDIENCE,
          responseType: 'token'
        });
        const options = {
            closable: false,
            language: 'en',
            auth: {
               responseType: "token",
           },
           languageDictionary: {
               title: "Qover",
           }
            };
        this.lock = new Auth0Lock(process.env.AUTH_CLIENT_ID, process.env.AUTH_AUDIENCE, options);

        // Add callback for lock `authenticated` event
        // this.lock.on('authenticated', this._doAuthentication.bind(this));
        // this.lock.on('hash_parsed', this._doAuthentication.bind(this) );

        // binds login functions to keep this context
        this.login = this.login.bind(this);
    }

  login() {
    // Call the show method to display the widget.
    this.lock.show();
  }

    _doAuthentication(authResult) {
        if (!_.isNil(authResult)) {
            this.setAccessToken(authResult.accessToken)
            this.setToken(authResult.idToken );
            this.lock.getUserInfo(authResult.accessToken, (error, userDetail) => {
                if (error) {
                    // callback(error);
                } else {
                    this.setUser(userDetail);
                    // in order to emit the profile
                    this.emitChange();
                }
            });
        }
    }

  _registerToActions(action) {
      this._error = null;

        switch(action.type){
            // Respond to RECEIVE_DATA action
            case ProvideConstants.DATA_ERROR:
                // If action was responded to, emit change event
                if ( !_.isNil(action.error.response) ) {
                    this._error = action.error.data;
                } else if ( !_.isNil(action.error.data) ) {
                    this._error = action.error.data;
                } else {
                    this._error = action.error.message;
                }

                Toastr.error(this._error);

                this.emitChange();
                break;
            case ProvideConstants.LOGOUT_USER:
                this.removeUser();

                this.emitChange();
                break;

            default:
                break;
        }

  }

    get stateLog() {
        return {
            lock: this.login()
        }
    }

    get stateLayout() {
        return {
            profile: this.getProfile,
            token: this.getToken,
            loggedIn: this.loggedIn,
            lock: this.getLock,
        };
    }

    get getProfile() {
        if ( localStorage.getItem('_profile') ) {
            return JSON.parse(localStorage.getItem('_profile') );
        } else {
            return this._profile;
        }
    }

    get loggedIn() {
        // Checks if there is a saved token and it's still valid
      const token = this.getToken;
      const isTokenExp= isTokenExpired(token);

      if (isTokenExp) {
          this.removeUser();
      }
      return !!token && !isTokenExp;
    }

    setToken(idToken) {
        if (!_.isNil(idToken)) {
            // Saves user token to local storage
            localStorage.setItem('id_token', idToken);
        }
    }

    setAccessToken(accessToken) {
        if (!_.isNil(accessToken)) {
            // Saves user token to local storage
            localStorage.setItem('accessToken', accessToken);
        }
    }

    get getToken() {
      // Retrieves the user token from local storage
      return localStorage.getItem('id_token');
    }

    setUser(profile) {
        localStorage.setItem('_profile', JSON.stringify(profile));
    }

    removeUser() {
        localStorage.removeItem('accessToken');
        localStorage.removeItem('id_token');
        localStorage.removeItem('_profile');
    }

    get getLock() {
        return this.lock ;
    }

    parseHash(hash) {
        if (/access_token|id_token|error/.test(hash)) {
            const authResult = this.auth0.parseHash(hash);
            // uses auth0 parseHash method to extract data from url hash
            //   const authResult = this.auth0.parseHash(hash);
            this._doAuthentication(authResult);
            return true;
        } else {
            return false;
        }
    }

}
export default new LayoutStore();
<|endoftext|>