<commit_before>/*
 * Revolution custom js file
 * Author: Design_mylife
 *
 */

//full width slider

jQuery(document).ready(function () {

    revapi = jQuery('.tp-banner').revolution(
            {
                delay: 6000,
                startwidth: 1170,
                startheight: 600,
                hideThumbs: 10,
                fullWidth: "on",
                forceFullWidth: "on",
                navigationStyle: "preview4"
            });

});	//ready

jQuery(document).ready(function () {

    revapi = jQuery('.tp-banner-boxed').revolution(
            {
                delay: 6000,
                startwidth: 1170,
                startheight: 500,
                hideThumbs: 10,
                navigationStyle: "preview4"
            });

});

jQuery(document).ready(function () {

    revapi = jQuery('.tp-fullscreen-banner').revolution(
            {
                delay: 15000,
                startwidth: 1170,
                startheight: 500,
                hideThumbs: 10,
                fullWidth: "off",
                fullScreen: "on",
                fullScreenOffsetContainer: "",
                navigationStyle: "preview5"

            });

});	//ready

//ken burns effect

jQuery(document).ready(function () {

    revapi = jQuery('.ken-burns-banner').revolution(
            {
                dottedOverlay: "none",
                delay: 16000,
                startwidth: 1140,
                startheight: 700,
                hideThumbs: 200,
                thumbWidth: 100,
                thumbHeight: 50,
                thumbAmount: 5,
                navigationType: "bullet",
                navigationArrows: "solo",
                navigationStyle: "preview4",
                touchenabled: "on",
                onHoverStop: "on",
                swipe_velocity: 0.7,
                swipe_min_touches: 1,
                swipe_max_touches: 1,
                drag_block_vertical: false,
                parallax: "mouse",
                parallaxBgFreeze: "on",
                parallaxLevels: [7, 4, 3, 2, 5, 4, 3, 2, 1, 0],
                keyboardNavigation: "off",
                navigationHAlign: "center",
                navigationVAlign: "bottom",
                navigationHOffset: 0,
                navigationVOffset: 20,
                soloArrowLeftHalign: "left",
                soloArrowLeftValign: "center",
                soloArrowLeftHOffset: 20,
                soloArrowLeftVOffset: 0,
                soloArrowRightHalign: "right",
                soloArrowRightValign: "center",
                soloArrowRightHOffset: 20,
                soloArrowRightVOffset: 0,
                shadow: 0,
                fullWidth: "off",
                fullScreen: "on",
                spinner: "spinner4",
                stopLoop: "off",
                stopAfterLoops: -1,
                stopAtSlide: -1,
                shuffle: "off",
                autoHeight: "off",
                forceFullWidth: "off",
                hideThumbsOnMobile: "off",
                hideNavDelayOnMobile: 1500,
                hideBulletsOnMobile: "off",
                hideArrowsOnMobile: "off",
                hideThumbsUnderResolution: 0,
                hideSliderAtLimit: 0,
                hideCaptionAtLimit: 0,
                hideAllCaptionAtLilmit: 0,
                startWithSlide: 0
            });

});	//ready

//vertical slider
jQuery(document).ready(function () {
    jQuery('.tp-banner-vertical').show().revolution(
            {
                dottedOverlay: "none",
                delay: 9000,
                startwidth: 1170,
                startheight: 500,
                hideThumbs: 200,
                thumbWidth: 100,
                thumbHeight: 50,
                thumbAmount: 5,
                navigationType: "none",
                navigationArrows: "solo",
                navigationStyle: "preview1",
                touchenabled: "on",
                onHoverStop: "on",
                swipe_velocity: 0.7,
                swipe_min_touches: 1,
                swipe_max_touches: 1,
                drag_block_vertical: false,
                keyboardNavigation: "on",
                navigationHAlign: "center",
                navigationVAlign: "bottom",
                navigationHOffset: 0,
                navigationVOffset: 20,
                soloArrowLeftHalign: "left",
                soloArrowLeftValign: "center",
                soloArrowLeftHOffset: 20,
                soloArrowLeftVOffset: 0,
                soloArrowRightHalign: "right",
                soloArrowRightValign: "center",
                soloArrowRightHOffset: 20,
                soloArrowRightVOffset: 0,
                shadow: 0,
                fullWidth: "on",
                fullScreen: "off",
                spinner: "spinner0",
                stopLoop: "off",
                stopAfterLoops: -1,
                stopAtSlide: -1,
                shuffle: "off",
                autoHeight: "off",     forceFullWidth: "on",
                hideThumbsOnMobile: "off",
                hideNavDelayOnMobile: 1500,
                hideBulletsOnMobile: "off",
                hideArrowsOnMobile: "off",
                hideThumbsUnderResolution: 0,
                hideSliderAtLimit: 0,
                hideCaptionAtLimit: 0,
                hideAllCaptionAtLilmit: 0,
                startWithSlide: 0
            });

});	//ready<commit_msg>Drop exec bits<commit_after>/*
 * Revolution custom js file
 * Author: Design_mylife
 *
 */

//full width slider

jQuery(document).ready(function () {

    revapi = jQuery('.tp-banner').revolution(
            {
                delay: 6000,
                startwidth: 1170,
                startheight: 600,
                hideThumbs: 10,
                fullWidth: "on",
                forceFullWidth: "on",
                navigationStyle: "preview4"
            });

});	//ready

jQuery(document).ready(function () {

    revapi = jQuery('.tp-banner-boxed').revolution(
            {
                delay: 6000,
                startwidth: 1170,
                startheight: 500,
                hideThumbs: 10,
                navigationStyle: "preview4"
            });

});

jQuery(document).ready(function () {

    revapi = jQuery('.tp-fullscreen-banner').revolution(
            {
                delay: 15000,
                startwidth: 1170,
                startheight: 500,
                hideThumbs: 10,
                fullWidth: "off",
                fullScreen: "on",
                fullScreenOffsetContainer: "",
                navigationStyle: "preview5"

            });

});	//ready

//ken burns effect

jQuery(document).ready(function () {

    revapi = jQuery('.ken-burns-banner').revolution(
            {
                dottedOverlay: "none",
                delay: 16000,
                startwidth: 1140,
                startheight: 700,
                hideThumbs: 200,
                thumbWidth: 100,
                thumbHeight: 50,
                thumbAmount: 5,
                navigationType: "bullet",
                navigationArrows: "solo",
                navigationStyle: "preview4",
                touchenabled: "on",
                onHoverStop: "on",
                swipe_velocity: 0.7,
                swipe_min_touches: 1,
                swipe_max_touches: 1,
                drag_block_vertical: false,
                parallax: "mouse",
                parallaxBgFreeze: "on",
                parallaxLevels: [7, 4, 3, 2, 5, 4, 3, 2, 1, 0],
                keyboardNavigation: "off",
                navigationHAlign: "center",
                navigationVAlign: "bottom",
                navigationHOffset: 0,
                navigationVOffset: 20,
                soloArrowLeftHalign: "left",
                soloArrowLeftValign: "center",
                soloArrowLeftHOffset: 20,
                soloArrowLeftVOffset: 0,
                soloArrowRightHalign: "right",
                soloArrowRightValign: "center",
                soloArrowRightHOffset: 20,
                soloArrowRightVOffset: 0,
                shadow: 0,
                fullWidth: "off",
                fullScreen: "on",
                spinner: "spinner4",
                stopLoop: "off",
                stopAfterLoops: -1,
                stopAtSlide: -1,
                shuffle: "off",
                autoHeight: "off",
                forceFullWidth: "off",
                hideThumbsOnMobile: "off",
                hideNavDelayOnMobile: 1500,
                hideBulletsOnMobile: "off",
                hideArrowsOnMobile: "off",
                hideThumbsUnderResolution: 0,
                hideSliderAtLimit: 0,
                hideCaptionAtLimit: 0,
                hideAllCaptionAtLilmit: 0,
                startWithSlide: 0
            });

});	//ready

//vertical slider
jQuery(document).ready(function () {
    jQuery('.tp-banner-vertical').show().revolution(
            {
                dottedOverlay: "none",
                delay: 9000,
                startwidth: 1170,
                startheight: 500,
                hideThumbs: 200,
                thumbWidth: 100,
                thumbHeight: 50,
                thumbAmount: 5,
                navigationType: "none",
                navigationArrows: "solo",
                navigationStyle: "preview1",
                touchenabled: "on",
                onHoverStop: "on",
                swipe_velocity: 0.7,
                swipe_min_touches: 1,
                swipe_max_touches: 1,
                drag_block_vertical: false,
                keyboardNavigation: "on",
                navigationHAlign: "center",
                navigationVAlign: "bottom",
                navigationHOffset: 0,
                navigationVOffset: 20,
                soloArrowLeftHalign: "left",
                soloArrowLeftValign: "center",
                soloArrowLeftHOffset: 20,
                soloArrowLeftVOffset: 0,
                soloArrowRightHalign: "right",
                soloArrowRightValign: "center",
                soloArrowRightHOffset: 20,
                soloArrowRightVOffset: 0,
                shadow: 0,
                fullWidth: "on",
                fullScreen: "off",
                spinner: "spinner0",
                stopLoop: "off",
                stopAfterLoops: -1,
                stopAtSlide: -1,
                shuffle: "off",
                autoHeight: "off",     forceFullWidth: "on",
                hideThumbsOnMobile: "off",
                hideNavDelayOnMobile: 1500,
                hideBulletsOnMobile: "off",
                hideArrowsOnMobile: "off",
                hideThumbsUnderResolution: 0,
                hideSliderAtLimit: 0,
                hideCaptionAtLimit: 0,
                hideAllCaptionAtLilmit: 0,
                startWithSlide: 0
            });

});	//ready<|endoftext|>


<commit_before>'use strict';

/* globals $, window, document, ajaxify, FormData, define, utils, config, app */

define('composer/uploads', [
	'composer/preview',
	'composer/categoryList',
	'translator',
	'jquery-form',
], function (preview, categoryList, translator) {
	var uploads = {
		inProgress: {},
	};

	var uploadingText = '';

	uploads.initialize = function (post_uuid) {
		initializeDragAndDrop(post_uuid);
		initializePaste(post_uuid);

		addChangeHandlers(post_uuid);
		addTopicThumbHandlers(post_uuid);
		translator.translate('[[modules:composer.uploading, ' + 0 + '%]]', function (translated) {
			uploadingText = translated;
		});
	};

	function addChangeHandlers(post_uuid) {
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');

		postContainer.find('#files').on('change', function (e) {
			var files = (e.target || {}).files ||
				($(this).val() ? [{ name: $(this).val(), type: utils.fileMimeType($(this).val()) }] : null);
			if (files) {
				uploadContentFiles({ files: files, post_uuid: post_uuid, route: '/api/post/upload' });
			}
		});
	}

	function addTopicThumbHandlers(post_uuid) {
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');

		postContainer.on('click', '.topic-thumb-clear-btn', function (e) {
			postContainer.find('input#topic-thumb-url').val('').trigger('change');
			resetInputFile(postContainer.find('input#topic-thumb-file'));
			$(this).addClass('hide');
			e.preventDefault();
		});

		postContainer.on('paste change keypress', 'input#topic-thumb-url', function () {
			var urlEl = $(this);
			setTimeout(function () {
				var url = urlEl.val();
				if (url) {
					postContainer.find('.topic-thumb-clear-btn').removeClass('hide');
				} else {
					resetInputFile(postContainer.find('input#topic-thumb-file'));
					postContainer.find('.topic-thumb-clear-btn').addClass('hide');
				}
				postContainer.find('img.topic-thumb-preview').attr('src', url);
			}, 100);
		});
	}

	function resetInputFile($el) {
		$el.wrap('<form />').closest('form').get(0).reset();
		$el.unwrap();
	}

	function initializeDragAndDrop(post_uuid) {
		var draggingDocument = false;
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');
		var drop = postContainer.find('.imagedrop');

		function onDragEnter() {
			if (draggingDocument) {
				return;
			}

			drop.css('top', '0px');
			drop.css('height', postContainer.height() + 'px');
			drop.css('line-height', postContainer.height() + 'px');
			drop.show();

			drop.on('dragleave', function () {
				drop.hide();
				drop.off('dragleave');
			});
		}

		function onDragDrop(e) {
			e.preventDefault();
			var files = e.originalEvent.dataTransfer.files;
			var fd;

			if (files.length) {
				if (window.FormData) {
					fd = new FormData();
					for (var i = 0; i < files.length; ++i) {
						fd.append('files[]', files[i], files[i].name);
					}
				}

				uploadContentFiles({
					files: files,
					post_uuid: post_uuid,
					route: '/api/post/upload',
					formData: fd,
				});
			}

			drop.hide();
			return false;
		}

		function cancel(e) {
			e.preventDefault();
			return false;
		}

		$(document)
			.off('dragstart')
			.on('dragstart', function () {
				draggingDocument = true;
			})
			.off('dragend')
			.on('dragend', function () {
				draggingDocument = false;
			});

		postContainer.on('dragenter', onDragEnter);

		drop.on('dragover', cancel);
		drop.on('dragenter', cancel);
		drop.on('drop', onDragDrop);
	}

	function initializePaste(post_uuid) {
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');
		postContainer.on('paste', function (event) {
			var items = (event.clipboardData || event.originalEvent.clipboardData || {}).items;

			[].some.call(items, function (item) {
				var blob = item.getAsFile();

				if (!blob) {
					return false;
				}

				var blobName = utils.generateUUID() + '-' + blob.name;

				var fd = null;
				if (window.FormData) {
					fd = new FormData();
					fd.append('files[]', blob, blobName);
				}

				uploadContentFiles({
					files: [blob],
					fileNames: [blobName],
					post_uuid: post_uuid,
					route: '/api/post/upload',
					formData: fd,
				});

				return true;
			});
		});
	}

	function escapeRegExp(text) {
		return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
	}

	function insertText(str, index, insert) {
		return str.slice(0, index) + insert + str.slice(index);
	}

	function uploadContentFiles(params) {
		var files = [...params.files];
		var post_uuid = params.post_uuid;
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');
		var textarea = postContainer.find('textarea');
		var text = textarea.val();
		var uploadForm = postContainer.find('#fileForm');
		var doneUploading = false;
		uploadForm.attr('action', config.relative_path + params.route);

		var cid = categoryList.getSelectedCid();
		if (!cid && ajaxify.data.cid) {
			cid = ajaxify.data.cid;
		}
		var i = 0;
		var isImage = false;
		for (i = 0; i < files.length; ++i) {
			isImage = files[i].type.match(/image./);
			if ((isImage && !app.user.privileges['upload:post:image']) || (!isImage && !app.user.privileges['upload:post:file'])) {
				return app.alertError('[[error:no-privileges]]');
			}
		}

		var filenameMapping = [];

		for (i = 0; i < files.length; ++i) {
			// The filename map has datetime and iterator prepended so that they can be properly tracked even if the
			// filenames are identical.
			filenameMapping.push(i + '_' + Date.now() + '_' + (params.fileNames ? params.fileNames[i] : files[i].name));
			isImage = files[i].type.match(/image./);

			if (files[i].size > parseInt(config.maximumFileSize, 10) * 1024) {
				uploadForm[0].reset();
				return app.alertError('[[error:file-too-big, ' + config.maximumFileSize + ']]');
			}

			text = insertText(text, textarea.getCursorPosition(), (isImage ? '!' : '') + '[' + filenameMapping[i] + '](' + uploadingText + ') ');
		}
		if (uploadForm.length) {
			postContainer.find('[data-action="post"]').prop('disabled', true);
		}
		textarea.val(text);

		$(window).trigger('action:composer.uploadStart', {
			post_uuid: post_uuid,
			files: filenameMapping.map(function (filename, i) {
				return {
					filename: filename.replace(/^\d+_\d{13}_/, ''),
					isImage: /image./.test(files[i].type),
				};
			}),
			text: uploadingText,
		});

		uploadForm.off('submit').submit(function () {
			function updateTextArea(filename, text, trim) {
				var newFilename;
				if (trim) {
					newFilename = filename.replace(/^\d+_\d{13}_/, '');
				}
				var current = textarea.val();
				var re = new RegExp(escapeRegExp(filename) + ']\\([^)]+\\)', 'g');
				textarea.val(current.replace(re, (newFilename || filename) + '](' + text + ')'));

				$(window).trigger('action:composer.uploadUpdate', {
					post_uuid: post_uuid,
					filename: filename,
					text: text,
				});
			}

			uploads.inProgress[post_uuid] = uploads.inProgress[post_uuid] || [];
			uploads.inProgress[post_uuid].push(1);

			if (params.formData) {
				params.formData.append('cid', cid);
			}

			$(this).ajaxSubmit({
				headers: {
					'x-csrf-token': config.csrf_token,
				},
				resetForm: true,
				clearForm: true,
				formData: params.formData,
				data: { cid: cid },

				error: function (xhr) {
					postContainer.find('[data-action="post"]').prop('disabled', false);
					onUploadError(xhr, post_uuid);
				},

				uploadProgress: function (event, position, total, percent) {
					translator.translate('[[modules:composer.uploading, ' + percent + '%]]', function (translated) {
						if (doneUploading) {
							return;
						}
						for (var i = 0; i < files.length; ++i) {
							updateTextArea(filenameMapping[i], translated);
						}
					});
				},

				success: function (res) {
					const uploads = res.response.images;
					doneUploading = true;
					if (uploads && uploads.length) {
						for (var i = 0; i < uploads.length; ++i) {
							uploads[i].filename = filenameMapping[i].replace(/^\d+_\d{13}_/, '');
							uploads[i].isImage = /image./.test(files[i].type);
							updateTextArea(filenameMapping[i], uploads[i].url, true);
						}
					}
					preview.render(postContainer);
					textarea.focus();
					postContainer.find('[data-action="post"]').prop('disabled', false);
					$(window).trigger('action:composer.upload', {
						post_uuid: post_uuid,
						files: uploads,
					});
				},

				complete: function () {
					uploadForm[0].reset();
					uploads.inProgress[post_uuid].pop();
				},
			});

			return false;
		});

		uploadForm.submit();
	}

	function onUploadError(xhr, post_uuid) {
		var msg = (xhr.responseJSON && xhr.responseJSON.error) || '[[error:parse-error]]';
		if (xhr && xhr.status === 413) {
			msg = xhr.statusText || 'Request Entity Too Large';
		}
		app.alertError(msg);
		$(window).trigger('action:composer.uploadError', {
			post_uuid: post_uuid,
			message: msg,
		});
	}

	return uploads;
});

<commit_msg>fix: error messages on upload<commit_after>'use strict';

/* globals $, window, document, ajaxify, FormData, define, utils, config, app */

define('composer/uploads', [
	'composer/preview',
	'composer/categoryList',
	'translator',
	'jquery-form',
], function (preview, categoryList, translator) {
	var uploads = {
		inProgress: {},
	};

	var uploadingText = '';

	uploads.initialize = function (post_uuid) {
		initializeDragAndDrop(post_uuid);
		initializePaste(post_uuid);

		addChangeHandlers(post_uuid);
		addTopicThumbHandlers(post_uuid);
		translator.translate('[[modules:composer.uploading, ' + 0 + '%]]', function (translated) {
			uploadingText = translated;
		});
	};

	function addChangeHandlers(post_uuid) {
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');

		postContainer.find('#files').on('change', function (e) {
			var files = (e.target || {}).files ||
				($(this).val() ? [{ name: $(this).val(), type: utils.fileMimeType($(this).val()) }] : null);
			if (files) {
				uploadContentFiles({ files: files, post_uuid: post_uuid, route: '/api/post/upload' });
			}
		});
	}

	function addTopicThumbHandlers(post_uuid) {
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');

		postContainer.on('click', '.topic-thumb-clear-btn', function (e) {
			postContainer.find('input#topic-thumb-url').val('').trigger('change');
			resetInputFile(postContainer.find('input#topic-thumb-file'));
			$(this).addClass('hide');
			e.preventDefault();
		});

		postContainer.on('paste change keypress', 'input#topic-thumb-url', function () {
			var urlEl = $(this);
			setTimeout(function () {
				var url = urlEl.val();
				if (url) {
					postContainer.find('.topic-thumb-clear-btn').removeClass('hide');
				} else {
					resetInputFile(postContainer.find('input#topic-thumb-file'));
					postContainer.find('.topic-thumb-clear-btn').addClass('hide');
				}
				postContainer.find('img.topic-thumb-preview').attr('src', url);
			}, 100);
		});
	}

	function resetInputFile($el) {
		$el.wrap('<form />').closest('form').get(0).reset();
		$el.unwrap();
	}

	function initializeDragAndDrop(post_uuid) {
		var draggingDocument = false;
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');
		var drop = postContainer.find('.imagedrop');

		function onDragEnter() {
			if (draggingDocument) {
				return;
			}

			drop.css('top', '0px');
			drop.css('height', postContainer.height() + 'px');
			drop.css('line-height', postContainer.height() + 'px');
			drop.show();

			drop.on('dragleave', function () {
				drop.hide();
				drop.off('dragleave');
			});
		}

		function onDragDrop(e) {
			e.preventDefault();
			var files = e.originalEvent.dataTransfer.files;
			var fd;

			if (files.length) {
				if (window.FormData) {
					fd = new FormData();
					for (var i = 0; i < files.length; ++i) {
						fd.append('files[]', files[i], files[i].name);
					}
				}

				uploadContentFiles({
					files: files,
					post_uuid: post_uuid,
					route: '/api/post/upload',
					formData: fd,
				});
			}

			drop.hide();
			return false;
		}

		function cancel(e) {
			e.preventDefault();
			return false;
		}

		$(document)
			.off('dragstart')
			.on('dragstart', function () {
				draggingDocument = true;
			})
			.off('dragend')
			.on('dragend', function () {
				draggingDocument = false;
			});

		postContainer.on('dragenter', onDragEnter);

		drop.on('dragover', cancel);
		drop.on('dragenter', cancel);
		drop.on('drop', onDragDrop);
	}

	function initializePaste(post_uuid) {
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');
		postContainer.on('paste', function (event) {
			var items = (event.clipboardData || event.originalEvent.clipboardData || {}).items;

			[].some.call(items, function (item) {
				var blob = item.getAsFile();

				if (!blob) {
					return false;
				}

				var blobName = utils.generateUUID() + '-' + blob.name;

				var fd = null;
				if (window.FormData) {
					fd = new FormData();
					fd.append('files[]', blob, blobName);
				}

				uploadContentFiles({
					files: [blob],
					fileNames: [blobName],
					post_uuid: post_uuid,
					route: '/api/post/upload',
					formData: fd,
				});

				return true;
			});
		});
	}

	function escapeRegExp(text) {
		return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
	}

	function insertText(str, index, insert) {
		return str.slice(0, index) + insert + str.slice(index);
	}

	function uploadContentFiles(params) {
		var files = [...params.files];
		var post_uuid = params.post_uuid;
		var postContainer = $('.composer[data-uuid="' + post_uuid + '"]');
		var textarea = postContainer.find('textarea');
		var text = textarea.val();
		var uploadForm = postContainer.find('#fileForm');
		var doneUploading = false;
		uploadForm.attr('action', config.relative_path + params.route);

		var cid = categoryList.getSelectedCid();
		if (!cid && ajaxify.data.cid) {
			cid = ajaxify.data.cid;
		}
		var i = 0;
		var isImage = false;
		for (i = 0; i < files.length; ++i) {
			isImage = files[i].type.match(/image./);
			if ((isImage && !app.user.privileges['upload:post:image']) || (!isImage && !app.user.privileges['upload:post:file'])) {
				return app.alertError('[[error:no-privileges]]');
			}
		}

		var filenameMapping = [];

		for (i = 0; i < files.length; ++i) {
			// The filename map has datetime and iterator prepended so that they can be properly tracked even if the
			// filenames are identical.
			filenameMapping.push(i + '_' + Date.now() + '_' + (params.fileNames ? params.fileNames[i] : files[i].name));
			isImage = files[i].type.match(/image./);

			if (files[i].size > parseInt(config.maximumFileSize, 10) * 1024) {
				uploadForm[0].reset();
				return app.alertError('[[error:file-too-big, ' + config.maximumFileSize + ']]');
			}

			text = insertText(text, textarea.getCursorPosition(), (isImage ? '!' : '') + '[' + filenameMapping[i] + '](' + uploadingText + ') ');
		}
		if (uploadForm.length) {
			postContainer.find('[data-action="post"]').prop('disabled', true);
		}
		textarea.val(text);

		$(window).trigger('action:composer.uploadStart', {
			post_uuid: post_uuid,
			files: filenameMapping.map(function (filename, i) {
				return {
					filename: filename.replace(/^\d+_\d{13}_/, ''),
					isImage: /image./.test(files[i].type),
				};
			}),
			text: uploadingText,
		});

		uploadForm.off('submit').submit(function () {
			function updateTextArea(filename, text, trim) {
				var newFilename;
				if (trim) {
					newFilename = filename.replace(/^\d+_\d{13}_/, '');
				}
				var current = textarea.val();
				var re = new RegExp(escapeRegExp(filename) + ']\\([^)]+\\)', 'g');
				textarea.val(current.replace(re, (newFilename || filename) + '](' + text + ')'));

				$(window).trigger('action:composer.uploadUpdate', {
					post_uuid: post_uuid,
					filename: filename,
					text: text,
				});
			}

			uploads.inProgress[post_uuid] = uploads.inProgress[post_uuid] || [];
			uploads.inProgress[post_uuid].push(1);

			if (params.formData) {
				params.formData.append('cid', cid);
			}

			$(this).ajaxSubmit({
				headers: {
					'x-csrf-token': config.csrf_token,
				},
				resetForm: true,
				clearForm: true,
				formData: params.formData,
				data: { cid: cid },

				error: function (xhr) {
					postContainer.find('[data-action="post"]').prop('disabled', false);
					onUploadError(xhr, post_uuid);
				},

				uploadProgress: function (event, position, total, percent) {
					translator.translate('[[modules:composer.uploading, ' + percent + '%]]', function (translated) {
						if (doneUploading) {
							return;
						}
						for (var i = 0; i < files.length; ++i) {
							updateTextArea(filenameMapping[i], translated);
						}
					});
				},

				success: function (res) {
					const uploads = res.response.images;
					doneUploading = true;
					if (uploads && uploads.length) {
						for (var i = 0; i < uploads.length; ++i) {
							uploads[i].filename = filenameMapping[i].replace(/^\d+_\d{13}_/, '');
							uploads[i].isImage = /image./.test(files[i].type);
							updateTextArea(filenameMapping[i], uploads[i].url, true);
						}
					}
					preview.render(postContainer);
					textarea.focus();
					postContainer.find('[data-action="post"]').prop('disabled', false);
					$(window).trigger('action:composer.upload', {
						post_uuid: post_uuid,
						files: uploads,
					});
				},

				complete: function () {
					uploadForm[0].reset();
					uploads.inProgress[post_uuid].pop();
				},
			});

			return false;
		});

		uploadForm.submit();
	}

	function onUploadError(xhr, post_uuid) {
		var msg = (xhr.responseJSON &&
			(xhr.responseJSON.error || (xhr.responseJSON.status && xhr.responseJSON.status.message))) ||
			'[[error:parse-error]]';

		if (xhr && xhr.status === 413) {
			msg = xhr.statusText || 'Request Entity Too Large';
		}
		app.alertError(msg);
		$(window).trigger('action:composer.uploadError', {
			post_uuid: post_uuid,
			message: msg,
		});
	}

	return uploads;
});

<|endoftext|>


<commit_before>var Video = function() {

    this.player = null;

    //
    // Init
    //
    this.init();

};

Video.prototype.init = function() {

    var that = this;

    that.player = videojs('video-js-playlist', {
        aspectRatio:"905:520"
    });

    var playlist = [];
    $('.video-playlist li a').each(function(idx) {

        var elem = $(this);

        var srcs = elem.attr('data-src').split(',');
        var mimes = elem.attr('data-mime').split(',');
        var obj = {
            sources: [],
            poster: elem.attr('data-poster')
        };

        for(var i=0; i<srcs.length; i++) {
            obj.sources.push({
                src: srcs[i],
                type: mimes[i]
            });
        }

        playlist.push(obj);

        elem.click(function(e) {
            e.preventDefault();

            $('.video-playlist li').removeClass('playing');
            $(this).parent().addClass('playing');
            that.player.playlist.currentItem($(this).parent().index());
            that.player.play();

            return false;
        });

    });
    console.log(playlist);

    that.player.playlist(playlist);

};

Video.prototype.open = function(e) {

}

module.exports = Video;
<commit_msg>Fix a video.js bug<commit_after>var Video = function() {

    this.player = null;

    //
    // Init
    //
    if($('#video-js-playlist').length > 0) {
        this.init();
    }

};

Video.prototype.init = function() {

    var that = this;

    that.player = videojs('video-js-playlist', {
        aspectRatio:"905:520"
    });

    var playlist = [];
    $('.video-playlist li a').each(function(idx) {

        var elem = $(this);

        var srcs = elem.attr('data-src').split(',');
        var mimes = elem.attr('data-mime').split(',');
        var obj = {
            sources: [],
            poster: elem.attr('data-poster')
        };

        for(var i=0; i<srcs.length; i++) {
            obj.sources.push({
                src: srcs[i],
                type: mimes[i]
            });
        }

        playlist.push(obj);

        elem.click(function(e) {
            e.preventDefault();

            $('.video-playlist li').removeClass('playing');
            $(this).parent().addClass('playing');
            that.player.playlist.currentItem($(this).parent().index());
            that.player.play();

            return false;
        });

    });
    console.log(playlist);

    that.player.playlist(playlist);

};

Video.prototype.open = function(e) {

}

module.exports = Video;
<|endoftext|>


<commit_before>/**
 * Bottom menu constructor.
 * @constructor
 */

function bottom_menu(parent, options){

    this.on = false;
    this.parent = parent;

    this.dom_obj = {};
    this.main_container = {};

    this.cur_row_idx = 0;

    this.items = [];

    this.offset_x = 190;

    if (options){
        if (options.offset_x){
            this.offset_x = options.offset_x;
        }
    }
}

bottom_menu.prototype.show = function(){
    _debug('bottom_menu.show');

    this.dom_obj.moveY(576 - this.dom_obj.clientHeight - 36);
    this.on = true;
}

bottom_menu.prototype.hide = function(){
    _debug('bottom_menu.hide');

    this.dom_obj.moveY(576);
    this.on = false;
}

bottom_menu.prototype.init = function(map){
    _debug('bottom_menu.init');

    this.items = map;

    this.dom_obj = create_block_element('bottom_menu', this.parent.dom_obj);

    this.dom_obj.moveX(this.offset_x);

    create_block_element('bottom_menu_corners', this.dom_obj);

    this.main_container = document.createElement('ul');
    this.main_container.addClass('bottom_menu_container');

    var item;

    for (var i = 0; i < map.length; i++){
        item = document.createElement('li');
        item.innerHTML = map[i].label;

        this.items[i].dom_obj = item;

        this.main_container.appendChild(item);
    }

    this.dom_obj.appendChild(this.main_container);

    this.set_active_row();

    this.hide();
}

bottom_menu.prototype.shift_row = function(dir){
    _debug('bottom_menu.shift_row', dir);

    this.set_passive_row();

    if (dir > 0){
        if (this.cur_row_idx < this.items.length - 1){
            this.cur_row_idx++;
        }
    }else{
        if (this.cur_row_idx > 0){
            this.cur_row_idx--;
        }
    }

    this.set_active_row();
}

bottom_menu.prototype.set_active_row = function(){
    _debug('bottom_menu.set_active_row');

    this.items[this.cur_row_idx].dom_obj.setClass('bottom_menu_active_row');
}

bottom_menu.prototype.set_passive_row = function(){
    _debug('bottom_menu.set_passive_row');

    this.items[this.cur_row_idx].dom_obj.delClass();
}

bottom_menu.prototype.action = function(){
    _debug('bottom_menu.action');

    try{
        this.items[this.cur_row_idx].cmd();
    }catch(e){
        _debug(e);
    }
}

bottom_menu.prototype.bind = function(){

    this.shift_row.bind(key.UP, this, -1);
    this.shift_row.bind(key.DOWN, this, 1);

    this.hide.bind(key.EXIT, this);

    this.action.bind(key.OK, this);
}
<commit_msg>"Change action"<commit_after>/**
 * Bottom menu constructor.
 * @constructor
 */

function bottom_menu(parent, options){

    this.on = false;
    this.parent = parent;

    this.dom_obj = {};
    this.main_container = {};

    this.cur_row_idx = 0;

    this.items = [];

    this.offset_x = 190;

    if (options){
        if (options.offset_x){
            this.offset_x = options.offset_x;
        }
    }
}

bottom_menu.prototype.show = function(){
    _debug('bottom_menu.show');

    this.dom_obj.moveY(576 - this.dom_obj.clientHeight - 36);
    this.on = true;
}

bottom_menu.prototype.hide = function(){
    _debug('bottom_menu.hide');

    this.dom_obj.moveY(576);
    this.on = false;
}

bottom_menu.prototype.init = function(map){
    _debug('bottom_menu.init');

    this.items = map;

    this.dom_obj = create_block_element('bottom_menu', this.parent.dom_obj);

    this.dom_obj.moveX(this.offset_x);

    create_block_element('bottom_menu_corners', this.dom_obj);

    this.main_container = document.createElement('ul');
    this.main_container.addClass('bottom_menu_container');

    var item;

    for (var i = 0; i < map.length; i++){
        item = document.createElement('li');
        item.innerHTML = map[i].label;

        this.items[i].dom_obj = item;

        this.main_container.appendChild(item);
    }

    this.dom_obj.appendChild(this.main_container);

    this.set_active_row();

    this.hide();
}

bottom_menu.prototype.shift_row = function(dir){
    _debug('bottom_menu.shift_row', dir);

    this.set_passive_row();

    if (dir > 0){
        if (this.cur_row_idx < this.items.length - 1){
            this.cur_row_idx++;
        }
    }else{
        if (this.cur_row_idx > 0){
            this.cur_row_idx--;
        }
    }

    this.set_active_row();
}

bottom_menu.prototype.set_active_row = function(){
    _debug('bottom_menu.set_active_row');

    this.items[this.cur_row_idx].dom_obj.setClass('bottom_menu_active_row');
}

bottom_menu.prototype.set_passive_row = function(){
    _debug('bottom_menu.set_passive_row');

    this.items[this.cur_row_idx].dom_obj.delClass();
}

bottom_menu.prototype.action = function(){
    _debug('bottom_menu.action');

    _debug('this.items', this.items);
    _debug('this.items[this.cur_row_idx].cmd', this.items[this.cur_row_idx].cmd);

    try{
        this.items[this.cur_row_idx].cmd.call(this);

        this.parent.update_header_path([{"alias" : "sortby", "item" : this.items[this.cur_row_idx].label}]);

        this.parent.reset();
        this.parent.load_data();
    }catch(e){
        _debug(e);
    }
}

bottom_menu.prototype.bind = function(){

    this.shift_row.bind(key.UP, this, -1);
    this.shift_row.bind(key.DOWN, this, 1);

    this.hide.bind(key.EXIT, this);

    this.action.bind(key.OK, this);
}
<|endoftext|>


<commit_before>import postcss from 'postcss'
import plugin from '../src/lib/substituteClassApplyAtRules'
import generateUtilities from '../src/util/generateUtilities'
import defaultConfig from '../defaultConfig.stub.js'

const defaultUtilities = generateUtilities(defaultConfig, [])

function run(input, config = defaultConfig, utilities = defaultUtilities) {
  return postcss([plugin(config, utilities)]).process(input, { from: undefined })
}

test("it copies a class's declarations into itself", () => {
  const output = '.a { color: red; } .b { color: red; }'

  return run('.a { color: red; } .b { @apply .a; }').then(result => {
    expect(result.css).toEqual(output)
    expect(result.warnings().length).toBe(0)
  })
})

test('selectors with invalid characters do not need to be manually escaped', () => {
  const input = `
    .a\\:1\\/2 { color: red; }
    .b { @apply .a:1/2; }
  `

  const expected = `
    .a\\:1\\/2 { color: red; }
    .b { color: red; }
  `

  return run(input).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('it removes important from applied classes by default', () => {
  const input = `
    .a { color: red !important; }
    .b { @apply .a; }
  `

  const expected = `
    .a { color: red !important; }
    .b { color: red; }
  `

  return run(input).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('applied rules can be made !important', () => {
  const input = `
    .a { color: red; }
    .b { @apply .a !important; }
  `

  const expected = `
    .a { color: red; }
    .b { color: red !important; }
  `

  return run(input).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('cssnext custom property sets are preserved', () => {
  const input = `
    .a {
      color: red;
    }
    .b {
      @apply .a --custom-property-set;
    }
  `

  const expected = `
    .a {
      color: red;
    }
    .b {
      color: red;
      @apply --custom-property-set;
    }
  `

  return run(input).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('it fails if the class does not exist', () => {
  return run('.b { @apply .a; }').catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('applying classes that are defined in a media query is not supported', () => {
  const input = `
    @media (min-width: 300px) {
      .a { color: blue; }
    }

    .b {
      @apply .a;
    }
  `
  expect.assertions(1)
  return run(input).catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('applying classes that are ever used in a media query is not supported', () => {
  const input = `
    .a {
      color: red;
    }

    @media (min-width: 300px) {
      .a { color: blue; }
    }

    .b {
      @apply .a;
    }
  `
  expect.assertions(1)
  return run(input).catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('it does not match classes that include pseudo-selectors', () => {
  const input = `
    .a:hover {
      color: red;
    }

    .b {
      @apply .a;
    }
  `
  expect.assertions(1)
  return run(input).catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('it does not match classes that have multiple rules', () => {
  const input = `
    .a {
      color: red;
    }

    .b {
      @apply .a;
    }

    .a {
      color: blue;
    }
  `
  expect.assertions(1)
  return run(input).catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('you can apply utility classes that do not actually exist as long as they would exist if utilities were being generated', () => {
  const input = `
    .foo { @apply .mt-4; }
  `

  const expected = `
    .foo { margin-top: 1rem; }
  `

  const config = {
    ...defaultConfig,
    experiments: { shadowLookup: true },
  }

  return run(input, config).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('you can apply utility classes without using the given prefix', () => {
  const input = `
    .foo { @apply .mt-4; }
  `

  const expected = `
    .prefix-foo { margin-top: 1rem; }
  `

  const config = {
    ...defaultConfig,
    options: {
      ...defaultConfig.options,
      prefix: 'prefix',
    },
  }

  return run(input, config).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})
<commit_msg>Fix test for optional prefix (missing dash)<commit_after>import postcss from 'postcss'
import plugin from '../src/lib/substituteClassApplyAtRules'
import generateUtilities from '../src/util/generateUtilities'
import defaultConfig from '../defaultConfig.stub.js'

const defaultUtilities = generateUtilities(defaultConfig, [])

function run(input, config = defaultConfig, utilities = defaultUtilities) {
  return postcss([plugin(config, utilities)]).process(input, { from: undefined })
}

test("it copies a class's declarations into itself", () => {
  const output = '.a { color: red; } .b { color: red; }'

  return run('.a { color: red; } .b { @apply .a; }').then(result => {
    expect(result.css).toEqual(output)
    expect(result.warnings().length).toBe(0)
  })
})

test('selectors with invalid characters do not need to be manually escaped', () => {
  const input = `
    .a\\:1\\/2 { color: red; }
    .b { @apply .a:1/2; }
  `

  const expected = `
    .a\\:1\\/2 { color: red; }
    .b { color: red; }
  `

  return run(input).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('it removes important from applied classes by default', () => {
  const input = `
    .a { color: red !important; }
    .b { @apply .a; }
  `

  const expected = `
    .a { color: red !important; }
    .b { color: red; }
  `

  return run(input).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('applied rules can be made !important', () => {
  const input = `
    .a { color: red; }
    .b { @apply .a !important; }
  `

  const expected = `
    .a { color: red; }
    .b { color: red !important; }
  `

  return run(input).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('cssnext custom property sets are preserved', () => {
  const input = `
    .a {
      color: red;
    }
    .b {
      @apply .a --custom-property-set;
    }
  `

  const expected = `
    .a {
      color: red;
    }
    .b {
      color: red;
      @apply --custom-property-set;
    }
  `

  return run(input).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('it fails if the class does not exist', () => {
  return run('.b { @apply .a; }').catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('applying classes that are defined in a media query is not supported', () => {
  const input = `
    @media (min-width: 300px) {
      .a { color: blue; }
    }

    .b {
      @apply .a;
    }
  `
  expect.assertions(1)
  return run(input).catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('applying classes that are ever used in a media query is not supported', () => {
  const input = `
    .a {
      color: red;
    }

    @media (min-width: 300px) {
      .a { color: blue; }
    }

    .b {
      @apply .a;
    }
  `
  expect.assertions(1)
  return run(input).catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('it does not match classes that include pseudo-selectors', () => {
  const input = `
    .a:hover {
      color: red;
    }

    .b {
      @apply .a;
    }
  `
  expect.assertions(1)
  return run(input).catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('it does not match classes that have multiple rules', () => {
  const input = `
    .a {
      color: red;
    }

    .b {
      @apply .a;
    }

    .a {
      color: blue;
    }
  `
  expect.assertions(1)
  return run(input).catch(e => {
    expect(e).toMatchObject({ name: 'CssSyntaxError' })
  })
})

test('you can apply utility classes that do not actually exist as long as they would exist if utilities were being generated', () => {
  const input = `
    .foo { @apply .mt-4; }
  `

  const expected = `
    .foo { margin-top: 1rem; }
  `

  const config = {
    ...defaultConfig,
    experiments: { shadowLookup: true },
  }

  return run(input, config).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})

test('you can apply utility classes without using the given prefix', () => {
  const input = `
    .foo { @apply .mt-4; }
  `

  const expected = `
    .prefix-foo { margin-top: 1rem; }
  `

  const config = {
    ...defaultConfig,
    options: {
      ...defaultConfig.options,
      prefix: 'prefix-',
    },
  }

  return run(input, config).then(result => {
    expect(result.css).toEqual(expected)
    expect(result.warnings().length).toBe(0)
  })
})
<|endoftext|>


<commit_before>/**
 * This file is part of agora-gui-booth.
 * Copyright (C) 2015-2016  Agora Voting SL <agora@agoravoting.com>

 * agora-gui-booth is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License.

 * agora-gui-booth  is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.

 * You should have received a copy of the GNU Affero General Public License
 * along with agora-gui-booth.  If not, see <http://www.gnu.org/licenses/>.
**/

angular.module('avBooth')
  .directive('avBooth', function(
    $http,
    $location,
    $i18next,
    $window,
    $timeout,
    HmacService,
    ConfigService,
    InsideIframeService)
{

    // we use it as something similar to a controller here
    function link(scope, element, attrs) {
      // timeout is used with updateWidth so that we do not create too many
      // calls to it, at most one per 100ms
      var timeoutWidth;
      var w = angular.element($window);
      $("#theme").attr("href", "booth/themes/" + ConfigService.theme + "/app.min.css");
      //window.avThemes.change(ConfigService.theme);

      // when we are not inside an iframe and voter id is not set, this is a
      // demo booth
      scope.isDemo = !InsideIframeService() && !scope.voterId;

      function updateWidth() {
        $timeout.cancel(timeoutWidth);
        timeoutWidth = $timeout(function() {
          scope.windowWidth = w.width();
          console.log("scope.windowWidth = " + scope.windowWidth);
          scope.$apply();
        }, 100);
      }
      w.bind('resize', function () {
        updateWidth();
      });
      updateWidth();

      // possible values of the election state scope variable
      var stateEnum = {
        receivingElection: 'receivingElection',
        errorScreen: 'errorScreen',
        helpScreen: 'helpScreen',
        startScreen: 'startScreen',
        multiQuestion: 'multiQuestion',
        pairwiseBeta: 'pairwiseBeta',
        draftsElectionScreen: 'draftsElectionScreen',
        auditBallotScreen: 'auditBallotScreen',
        pcandidatesElectionScreen: 'pcandidatesElectionScreen',
        "2questionsConditionalScreen": '2questionsConditionalScreen',
        simultaneousQuestionsScreen: 'simultaneousQuestionsScreen',
        conditionalAccordionScreen: 'conditionalAccordionScreen',
        encryptingBallotScreen: 'encryptingBallotScreen',
        castOrCancelScreen: 'castOrCancelScreen',
        reviewScreen: 'reviewScreen',
        castingBallotScreen: 'castingBallotScreen',
        successScreen: 'successScreen'
      };

      // override state if in debug mode and it's provided via query param
      function setState(newState, newStateData) {
        console.log("setting state to " + newState);
        scope.state = newState;
        scope.stateData = newStateData;
        scope.stateChange++;
      }

      scope.mapQuestion = function(question) {
        if (question.layout === "conditional-accordion") {
          return {
            state: stateEnum.conditionalAccordionScreen,
            sorted: true,
            ordered: true
          };
        } else if  (question.layout === "pcandidates-election") {
          return {
            state: stateEnum.pcandidatesElectionScreen,
            sorted: true,
            ordered: true
          };
        } else if  (question.layout === "simultaneous-questions") {
          return {
            state: stateEnum.simultaneousQuestionsScreen,
            sorted: true,
            ordered: true
          };
        }

        var map = {
          "plurality-at-large": {
            state: stateEnum.multiQuestion,
            sorted: true,
            ordered: false
          },
          "borda-nauru": {
            state: stateEnum.multiQuestion,
            sorted: true,
            ordered: true
          },
          "borda": {
            state: stateEnum.multiQuestion,
            sorted: true,
            ordered: true
          },
          "pairwise-beta": {
            state: stateEnum.pairwiseBeta,
            sorted: true,
            ordered: true
          }
        };
        return map[question.tally_type];
      };

      // given a question number, looks at the question type and tells the
      // correct state to set, so that the associated directive correctly shows
      // the given question
      function goToQuestion(n, reviewMode) {
        // first check for special election-wide layouts
        var layout = scope.election.layout;
        if (layout === "2questions-conditional") {
          scope.setState(stateEnum["2questionsConditionalScreen"], {
            isLastQuestion: true,
            reviewMode: true,
            filter: ""
          });
          return;
        }

        // what should be the next question?
        var nextQuestion = processConditionalQuestions(n);

        var isLastQuestion = (scope.election.questions.length === nextQuestion);
        if (isLastQuestion) {
          scope.setState(stateEnum.encryptingBallotScreen, {});
          return;
        }

        var question = scope.election.questions[nextQuestion];
        var mapped = scope.mapQuestion(question);

        scope.setState(mapped.state, {
          question: scope.election.questions[nextQuestion],
          questionNum: nextQuestion,
          isLastQuestion: (scope.election.questions.length === nextQuestion + 1),
          reviewMode: reviewMode,
          filter: "",
          sorted: mapped.sorted,
          ordered: mapped.ordered,
          affixIsSet: false,
          pairNum: 0 // only used for pairwise comparison
        });
      }

      // Set the vote in a question as blank (no option selected)
      function blankVoteQuestion(question)
      {
        _.each(
          question.answers,
          function (element)
          {
            element.selected = -1;
          }
        );
      }

      // taking into account the choices in previous questions, check if
      // questions [n, max] are enabled or not, reset to blank vote disabled
      // questions and return the first enabled question between [n, max+1]
      function processConditionalQuestions(n)
      {
        // if there are no conditional question, then continue
        if (!scope.election.presentation.conditional_questions ||
          !angular.isArray(scope.election.presentation.conditional_questions))
        {
          return n;
        }

        // review all questions, disabling conditional questions as needed
        // and resetting their answers
        _.each(
          scope.election.questions,
          function (question, index)
          {
            var conditional_questions = _.filter(
              scope.election.presentation.conditional_questions,
              function (cond_question)
              {
                return cond_question.question_id === index;
              }
            );

            // if it's not a conditional question, then we are finished
            if (conditional_questions.length === 0) {
              question.disabled = false;
              return;
            }

            var cond_question = conditional_questions[0];
            var conditions = _.filter(
              cond_question.when_any,
              // check if the options is selected
              function (condition)
              {
                return (scope.election.questions[condition.question_id].answers[condition.answer_id].selected > -1);
              }
            );

            question.disabled = (conditions.length === 0);
            if (question.disabled) {
              blankVoteQuestion(question);
            }
          }
        );

        // return the next enabled question index including or after n
        var nextEnabledQuestion = scope.election.questions.length + 1;
        for (var i = n; i < scope.election.questions.length; i++)
        {
          if (!scope.election.questions[i].disabled) {
            return i;
          }
        }

        return scope.election.questions.length + 1;
      }

      // changes state to the next one, calculating it and setting some scope
      // vars
      function next() {
        var questionStates = [
          stateEnum.multiQuestion,
          stateEnum.pcandidatesElectionScreen,
          stateEnum.simultaneousQuestionsScreen,
        ];
        if (scope.state === stateEnum.startScreen)
        {
          goToQuestion(0, false);

        } else if (scope.state === stateEnum.reviewScreen)
        {
          if (!scope.stateData.auditClicked) {
            // in a demo, we don't send the ballot, we just show as if we had sent it
            if (scope.isDemo) {
              scope.setState(stateEnum.successScreen, {
                ballotHash: scope.stateData.ballotHash
              });
            // if we are not in a demo, send the ballot
            } else {
              scope.setState(stateEnum.castingBallotScreen, {
                encryptedBallot: scope.stateData.encryptedBallot,
                auditableBallot: scope.stateData.auditableBallot
              });
            }
          } else {
            scope.setState(stateEnum.auditBallotScreen, {
              encryptedBallot: scope.stateData.encryptedBallot,
              auditableBallot: scope.stateData.auditableBallot,
              ballotHash: scope.stateData.auditableBallot.ballot_hash
            });
          }

        } else if (scope.state === stateEnum.auditBallotScreen)
        {
          goToQuestion(0, false);

        } else if (scope.state === stateEnum.encryptingBallotScreen)
        {
          scope.setState(stateEnum.reviewScreen, {
            encryptedBallot: scope.stateData.encryptedBallot,
            auditableBallot: scope.stateData.auditableBallot,
            ballotHash: scope.stateData.auditableBallot.ballot_hash,
            auditClicked: false
          });

        } else if (scope.state === stateEnum.castingBallotScreen)
        {
          scope.setState(stateEnum.successScreen, {
            ballotHash: scope.stateData.ballotHash
          });

        } else if (scope.stateData.isLastQuestion || scope.stateData.reviewMode)
        {
          // process again conditional questions
          processConditionalQuestions(0);
          scope.setState(stateEnum.encryptingBallotScreen, {});

        } else if (_.contains(questionStates, scope.state) &&
                   !scope.stateData.isLastQuestion)
        {
          goToQuestion(scope.stateData.questionNum + 1, false);
        }
      }

      // shows the error string
      function showError(error) {
        if (scope.state === stateEnum.errorScreen) {
          console.log("already in an error state, new error appeared: " + error);
          return;
        }
        scope.setState(stateEnum.errorScreen, {error: error});
      }

      function launchHelp() {
        scope.setState(stateEnum.helpScreen, {
          oldState: {
            name: scope.state,
            data: angular.copy(scope.stateData)
          }});
      }

      function backFromHelp() {
        if (scope.state !== stateEnum.helpScreen) {
          console.log("error, calling to backFromHelp in another state");
          return;
        }

        if (angular.isDefined(scope.stateData.oldState.data.questionNum)) {
          var n = scope.stateData.oldState.data.questionNum;
          scope.stateData.oldState.data.question = scope.election.questions[n];
        }

        scope.setState(
          scope.stateData.oldState.name,
          scope.stateData.oldState.data);
      }

      // init scope vars
      angular.extend(scope, {
        election: null,
        setState: setState,
        stateEnum: stateEnum,
        stateChange: 0,
        showError: showError,
        launchHelp: launchHelp,
        backFromHelp: backFromHelp,
        goToQuestion: goToQuestion,
        next: next,

        // stateData stores information used by the directive being shown.
        // Its content depends on the current state.
        stateData: {},

        // contains the clear text of the ballot. It's a list with an element
        // per question.
        // The format of each item in the array depends on the voting method for
        // the related question. This is used by the directives to store the
        // clear text of the ballot.
        ballotClearText: [],

        // convert config to JSON
        config: angular.fromJson(scope.configStr)
      });

      // execute pre-check first
      if (attrs.preCheck) {
        var ret = scope.preCheck();
        if (ret !== null) {
          showError(ret);
          return;
        }
      }

      setState(stateEnum.receivingElection, {});

      function retrieveElectionConfig() {
        try {
          $http.get(scope.baseUrl + "election/" + scope.electionId)
            // on success
            .success(function(value) {
              if (!scope.isDemo && value.payload.state !== "started") {
                showError($i18next("avBooth.errorElectionIsNotOpen"));
                return;
              }

              scope.election = angular.fromJson(value.payload.configuration);

              // index questions
              _.each(scope.election.questions, function(q, num) { q.num = num; });

              scope.pubkeys = angular.fromJson(value.payload.pks);
              // initialize ballotClearText as a list of lists
              scope.ballotClearText = _.map(
                scope.election.questions, function () { return []; });
              scope.setState(stateEnum.startScreen, {});
            })
            // on error, like parse error or 404
            .error(function (error) {
              showError($i18next("avBooth.errorLoadingElection"));
            });
        } catch (error) {
          showError($i18next("avBooth.errorLoadingElection"));
        }
      }
      function avPostAuthorization(e, errorHandler) {
        var action = "avPostAuthorization:";
        if (e.data.substr(0, action.length) !== action) {
          return;
        }

        var khmacStr = e.data.substr(action.length, e.data.length);
        var khmac = HmacService.checkKhmac(khmacStr);
        if (!khmac) {
          scope.authorizationReceiverErrorHandler();
          showError($i18next("avBooth.errorLoadingElection"));
          return;
        }
        scope.authorizationHeader = khmacStr;
        var splitMessage = khmac.message.split(":");

        if (splitMessage.length < 4) {
          scope.authorizationReceiverErrorHandler();
          return;
        }
        scope.voterId = splitMessage[0];
        scope.authorizationReceiver();
        scope.authorizationReceiver = null;
      }
      scope.setAuthorizationReceiver = function (callback, errorCallback) {
        scope.authorizationReceiver = callback;
        scope.authorizationReceiverErrorHandler = errorCallback;
      };

      $window.addEventListener('message', avPostAuthorization, false);
      retrieveElectionConfig();
    }

    return {
      restrict: 'AE',
      scope: {
        baseUrl: '@',
        voterId: '@',
        electionId: '@',
        authorizationHeader: '@',
        configStr: '@config',

        // optional function to be called before anything, that will return null
        // if there's no error, or the error to be shown if there was some
        preCheck: '&',
      },
      link: link,
      templateUrl: 'avBooth/booth-directive/booth-directive.html'
    };
  });
<commit_msg>fixing usage of index of answers<commit_after>/**
 * This file is part of agora-gui-booth.
 * Copyright (C) 2015-2016  Agora Voting SL <agora@agoravoting.com>

 * agora-gui-booth is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License.

 * agora-gui-booth  is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.

 * You should have received a copy of the GNU Affero General Public License
 * along with agora-gui-booth.  If not, see <http://www.gnu.org/licenses/>.
**/

angular.module('avBooth')
  .directive('avBooth', function(
    $http,
    $location,
    $i18next,
    $window,
    $timeout,
    HmacService,
    ConfigService,
    InsideIframeService)
{

    // we use it as something similar to a controller here
    function link(scope, element, attrs) {
      // timeout is used with updateWidth so that we do not create too many
      // calls to it, at most one per 100ms
      var timeoutWidth;
      var w = angular.element($window);
      $("#theme").attr("href", "booth/themes/" + ConfigService.theme + "/app.min.css");
      //window.avThemes.change(ConfigService.theme);

      // when we are not inside an iframe and voter id is not set, this is a
      // demo booth
      scope.isDemo = !InsideIframeService() && !scope.voterId;

      function updateWidth() {
        $timeout.cancel(timeoutWidth);
        timeoutWidth = $timeout(function() {
          scope.windowWidth = w.width();
          console.log("scope.windowWidth = " + scope.windowWidth);
          scope.$apply();
        }, 100);
      }
      w.bind('resize', function () {
        updateWidth();
      });
      updateWidth();

      // possible values of the election state scope variable
      var stateEnum = {
        receivingElection: 'receivingElection',
        errorScreen: 'errorScreen',
        helpScreen: 'helpScreen',
        startScreen: 'startScreen',
        multiQuestion: 'multiQuestion',
        pairwiseBeta: 'pairwiseBeta',
        draftsElectionScreen: 'draftsElectionScreen',
        auditBallotScreen: 'auditBallotScreen',
        pcandidatesElectionScreen: 'pcandidatesElectionScreen',
        "2questionsConditionalScreen": '2questionsConditionalScreen',
        simultaneousQuestionsScreen: 'simultaneousQuestionsScreen',
        conditionalAccordionScreen: 'conditionalAccordionScreen',
        encryptingBallotScreen: 'encryptingBallotScreen',
        castOrCancelScreen: 'castOrCancelScreen',
        reviewScreen: 'reviewScreen',
        castingBallotScreen: 'castingBallotScreen',
        successScreen: 'successScreen'
      };

      // override state if in debug mode and it's provided via query param
      function setState(newState, newStateData) {
        console.log("setting state to " + newState);
        scope.state = newState;
        scope.stateData = newStateData;
        scope.stateChange++;
      }

      scope.mapQuestion = function(question) {
        if (question.layout === "conditional-accordion") {
          return {
            state: stateEnum.conditionalAccordionScreen,
            sorted: true,
            ordered: true
          };
        } else if  (question.layout === "pcandidates-election") {
          return {
            state: stateEnum.pcandidatesElectionScreen,
            sorted: true,
            ordered: true
          };
        } else if  (question.layout === "simultaneous-questions") {
          return {
            state: stateEnum.simultaneousQuestionsScreen,
            sorted: true,
            ordered: true
          };
        }

        var map = {
          "plurality-at-large": {
            state: stateEnum.multiQuestion,
            sorted: true,
            ordered: false
          },
          "borda-nauru": {
            state: stateEnum.multiQuestion,
            sorted: true,
            ordered: true
          },
          "borda": {
            state: stateEnum.multiQuestion,
            sorted: true,
            ordered: true
          },
          "pairwise-beta": {
            state: stateEnum.pairwiseBeta,
            sorted: true,
            ordered: true
          }
        };
        return map[question.tally_type];
      };

      // given a question number, looks at the question type and tells the
      // correct state to set, so that the associated directive correctly shows
      // the given question
      function goToQuestion(n, reviewMode) {
        // first check for special election-wide layouts
        var layout = scope.election.layout;
        if (layout === "2questions-conditional") {
          scope.setState(stateEnum["2questionsConditionalScreen"], {
            isLastQuestion: true,
            reviewMode: true,
            filter: ""
          });
          return;
        }

        // what should be the next question?
        var nextQuestion = processConditionalQuestions(n);

        var isLastQuestion = (scope.election.questions.length === nextQuestion);
        if (isLastQuestion) {
          scope.setState(stateEnum.encryptingBallotScreen, {});
          return;
        }

        var question = scope.election.questions[nextQuestion];
        var mapped = scope.mapQuestion(question);

        scope.setState(mapped.state, {
          question: scope.election.questions[nextQuestion],
          questionNum: nextQuestion,
          isLastQuestion: (scope.election.questions.length === nextQuestion + 1),
          reviewMode: reviewMode,
          filter: "",
          sorted: mapped.sorted,
          ordered: mapped.ordered,
          affixIsSet: false,
          pairNum: 0 // only used for pairwise comparison
        });
      }

      // Set the vote in a question as blank (no option selected)
      function blankVoteQuestion(question)
      {
        _.each(
          question.answers,
          function (element)
          {
            element.selected = -1;
          }
        );
      }

      // taking into account the choices in previous questions, check if
      // questions [n, max] are enabled or not, reset to blank vote disabled
      // questions and return the first enabled question between [n, max+1]
      function processConditionalQuestions(n)
      {
        // if there are no conditional question, then continue
        if (!scope.election.presentation.conditional_questions ||
          !angular.isArray(scope.election.presentation.conditional_questions))
        {
          return n;
        }

        // review all questions, disabling conditional questions as needed
        // and resetting their answers
        _.each(
          scope.election.questions,
          function (question, index)
          {
            var conditional_questions = _.filter(
              scope.election.presentation.conditional_questions,
              function (cond_question)
              {
                return cond_question.question_id === index;
              }
            );

            // if it's not a conditional question, then we are finished
            if (conditional_questions.length === 0) {
              question.disabled = false;
              return;
            }

            var cond_question = conditional_questions[0];
            var conditions = _.filter(
              cond_question.when_any,
              // check if the options is selected
              function (condition)
              {
                return _.find(
                  scope.election.questions[condition.question_id].answers,
                  function (answer)
                  {
                    return (answer.id === condition.answer_id &&
                      answer.selected > -1);
                  }
                ) !== undefined;
              }
            );

            question.disabled = (conditions.length === 0);
            if (question.disabled) {
              blankVoteQuestion(question);
            }
          }
        );

        // return the next enabled question index including or after n
        var nextEnabledQuestion = scope.election.questions.length + 1;
        for (var i = n; i < scope.election.questions.length; i++)
        {
          if (!scope.election.questions[i].disabled) {
            return i;
          }
        }

        return scope.election.questions.length + 1;
      }

      // changes state to the next one, calculating it and setting some scope
      // vars
      function next() {
        var questionStates = [
          stateEnum.multiQuestion,
          stateEnum.pcandidatesElectionScreen,
          stateEnum.simultaneousQuestionsScreen,
        ];
        if (scope.state === stateEnum.startScreen)
        {
          goToQuestion(0, false);

        } else if (scope.state === stateEnum.reviewScreen)
        {
          if (!scope.stateData.auditClicked) {
            // in a demo, we don't send the ballot, we just show as if we had sent it
            if (scope.isDemo) {
              scope.setState(stateEnum.successScreen, {
                ballotHash: scope.stateData.ballotHash
              });
            // if we are not in a demo, send the ballot
            } else {
              scope.setState(stateEnum.castingBallotScreen, {
                encryptedBallot: scope.stateData.encryptedBallot,
                auditableBallot: scope.stateData.auditableBallot
              });
            }
          } else {
            scope.setState(stateEnum.auditBallotScreen, {
              encryptedBallot: scope.stateData.encryptedBallot,
              auditableBallot: scope.stateData.auditableBallot,
              ballotHash: scope.stateData.auditableBallot.ballot_hash
            });
          }

        } else if (scope.state === stateEnum.auditBallotScreen)
        {
          goToQuestion(0, false);

        } else if (scope.state === stateEnum.encryptingBallotScreen)
        {
          scope.setState(stateEnum.reviewScreen, {
            encryptedBallot: scope.stateData.encryptedBallot,
            auditableBallot: scope.stateData.auditableBallot,
            ballotHash: scope.stateData.auditableBallot.ballot_hash,
            auditClicked: false
          });

        } else if (scope.state === stateEnum.castingBallotScreen)
        {
          scope.setState(stateEnum.successScreen, {
            ballotHash: scope.stateData.ballotHash
          });

        } else if (scope.stateData.isLastQuestion || scope.stateData.reviewMode)
        {
          // process again conditional questions
          processConditionalQuestions(0);
          scope.setState(stateEnum.encryptingBallotScreen, {});

        } else if (_.contains(questionStates, scope.state) &&
                   !scope.stateData.isLastQuestion)
        {
          goToQuestion(scope.stateData.questionNum + 1, false);
        }
      }

      // shows the error string
      function showError(error) {
        if (scope.state === stateEnum.errorScreen) {
          console.log("already in an error state, new error appeared: " + error);
          return;
        }
        scope.setState(stateEnum.errorScreen, {error: error});
      }

      function launchHelp() {
        scope.setState(stateEnum.helpScreen, {
          oldState: {
            name: scope.state,
            data: angular.copy(scope.stateData)
          }});
      }

      function backFromHelp() {
        if (scope.state !== stateEnum.helpScreen) {
          console.log("error, calling to backFromHelp in another state");
          return;
        }

        if (angular.isDefined(scope.stateData.oldState.data.questionNum)) {
          var n = scope.stateData.oldState.data.questionNum;
          scope.stateData.oldState.data.question = scope.election.questions[n];
        }

        scope.setState(
          scope.stateData.oldState.name,
          scope.stateData.oldState.data);
      }

      // init scope vars
      angular.extend(scope, {
        election: null,
        setState: setState,
        stateEnum: stateEnum,
        stateChange: 0,
        showError: showError,
        launchHelp: launchHelp,
        backFromHelp: backFromHelp,
        goToQuestion: goToQuestion,
        next: next,

        // stateData stores information used by the directive being shown.
        // Its content depends on the current state.
        stateData: {},

        // contains the clear text of the ballot. It's a list with an element
        // per question.
        // The format of each item in the array depends on the voting method for
        // the related question. This is used by the directives to store the
        // clear text of the ballot.
        ballotClearText: [],

        // convert config to JSON
        config: angular.fromJson(scope.configStr)
      });

      // execute pre-check first
      if (attrs.preCheck) {
        var ret = scope.preCheck();
        if (ret !== null) {
          showError(ret);
          return;
        }
      }

      setState(stateEnum.receivingElection, {});

      function retrieveElectionConfig() {
        try {
          $http.get(scope.baseUrl + "election/" + scope.electionId)
            // on success
            .success(function(value) {
              if (!scope.isDemo && value.payload.state !== "started") {
                showError($i18next("avBooth.errorElectionIsNotOpen"));
                return;
              }

              scope.election = angular.fromJson(value.payload.configuration);

              // index questions
              _.each(scope.election.questions, function(q, num) { q.num = num; });

              scope.pubkeys = angular.fromJson(value.payload.pks);
              // initialize ballotClearText as a list of lists
              scope.ballotClearText = _.map(
                scope.election.questions, function () { return []; });
              scope.setState(stateEnum.startScreen, {});
            })
            // on error, like parse error or 404
            .error(function (error) {
              showError($i18next("avBooth.errorLoadingElection"));
            });
        } catch (error) {
          showError($i18next("avBooth.errorLoadingElection"));
        }
      }
      function avPostAuthorization(e, errorHandler) {
        var action = "avPostAuthorization:";
        if (e.data.substr(0, action.length) !== action) {
          return;
        }

        var khmacStr = e.data.substr(action.length, e.data.length);
        var khmac = HmacService.checkKhmac(khmacStr);
        if (!khmac) {
          scope.authorizationReceiverErrorHandler();
          showError($i18next("avBooth.errorLoadingElection"));
          return;
        }
        scope.authorizationHeader = khmacStr;
        var splitMessage = khmac.message.split(":");

        if (splitMessage.length < 4) {
          scope.authorizationReceiverErrorHandler();
          return;
        }
        scope.voterId = splitMessage[0];
        scope.authorizationReceiver();
        scope.authorizationReceiver = null;
      }
      scope.setAuthorizationReceiver = function (callback, errorCallback) {
        scope.authorizationReceiver = callback;
        scope.authorizationReceiverErrorHandler = errorCallback;
      };

      $window.addEventListener('message', avPostAuthorization, false);
      retrieveElectionConfig();
    }

    return {
      restrict: 'AE',
      scope: {
        baseUrl: '@',
        voterId: '@',
        electionId: '@',
        authorizationHeader: '@',
        configStr: '@config',

        // optional function to be called before anything, that will return null
        // if there's no error, or the error to be shown if there was some
        preCheck: '&',
      },
      link: link,
      templateUrl: 'avBooth/booth-directive/booth-directive.html'
    };
  });
<|endoftext|>


<commit_before>const easingOutQuint = (x, t, b, c, d) => c * ((t = t / d - 1) * t * t * t * t + 1) + b;

const scroll = (node, key, target) => {
  const startTime = Date.now();
  const offset    = node[key];
  const gap       = target - offset;
  const duration  = 1000;
  let interrupt   = false;

  const step = () => {
    const elapsed    = Date.now() - startTime;
    const percentage = elapsed / duration;

    if (percentage > 1 || interrupt) {
      return;
    }

    node[key] = easingOutQuint(0, elapsed, offset, gap, duration);
    requestAnimationFrame(step);
  };

  step();

  return () => {
    interrupt = true;
  };
};

export const scrollRight = (node, position) => scroll(node, 'scrollLeft', position);
export const scrollTop = (node) => scroll(node, 'scrollTop', 0);
<commit_msg>[Glitch] Use ScrollToOptions for smooth scrolling if supported<commit_after>const easingOutQuint = (x, t, b, c, d) => c * ((t = t / d - 1) * t * t * t * t + 1) + b;

const scroll = (node, key, target) => {
  const startTime = Date.now();
  const offset    = node[key];
  const gap       = target - offset;
  const duration  = 1000;
  let interrupt   = false;

  const step = () => {
    const elapsed    = Date.now() - startTime;
    const percentage = elapsed / duration;

    if (percentage > 1 || interrupt) {
      return;
    }

    node[key] = easingOutQuint(0, elapsed, offset, gap, duration);
    requestAnimationFrame(step);
  };

  step();

  return () => {
    interrupt = true;
  };
};

const isScrollBehaviorSupported = 'scrollBehavior' in document.documentElement.style;

export const scrollRight = (node, position) => isScrollBehaviorSupported ? node.scrollTo({ left: position, behavior: 'smooth' }) : scroll(node, 'scrollLeft', position);
export const scrollTop = (node) => isScrollBehaviorSupported ? node.scrollTo({ top: 0, behavior: 'smooth' }) : scroll(node, 'scrollTop', 0);
<|endoftext|>


<commit_before>(function ($) {
  var seconds, element, interval,
      _options = {},
      row = 0,
      col = 0;
  $.defaults = {
    rows: 4,
    cols: 7,
    time: 1000,
    gridSize: 60,
    stopAtEnd: true,
    displayTime: true,
    displaySeconds: 35,
    onStart: function (o){},
    onStop: function (){}
  },

  $.tick = function () {
    if (row > _options.rows ) {
      row = 0;
      col += 1;
    }
    if (col > _options.cols || seconds === 0) {
      if (_options.stopAtEnd) {
        $.stop();
      }
        col = 0;
        seconds = _options.displaySeconds;
    }
    verticalPosition = col * _options.gridSize * -1;
    horizontalPosition = row * _options.gridSize * -1;
    position = horizontalPosition + "px " + verticalPosition + "px";
    $(element).css("background-position", position);
    if (_options.displayTime) {
      $(element).text(--seconds);
    }
    ++row;
  };

  $.start = function () {
    _options.onStart();
    interval = setInterval(function(){ $.tick(_options) }, _options.time);
  };

  $.stop = function () {
    _options.onStop();
    clearInterval(interval);
  }

  $.fn.countdown_timer = function (options) {
    element = this;
    $.extend (_options, $.defaults, options);
    seconds = _options.displaySeconds;
    if ( _options.displayTime) {
      $(element).html(seconds);
    }
    return $;
  };
})(jQuery);<commit_msg>code cleanup<commit_after>(function ($) {
  var seconds, element, interval,
      _options = {},
      row = 0,
      col = 0;
  $.defaults = {
    rows: 4,
    cols: 7,
    time: 1000,
    gridSize: 60,
    stopAtEnd: true,
    displayTime: true,
    displaySeconds: 35,
    onStart: function () {},
    onStop:  function () {}
  },

  $.tick = function () {
    if (row > _options.rows ) {
      row = 0;
      col += 1;
    }
    if (col > _options.cols || seconds === 0) {
      if (_options.stopAtEnd) {
        $.stop();
      }
      col = 0;
      seconds = _options.displaySeconds;
    }
    verticalPosition = col * _options.gridSize * -1;
    horizontalPosition = row * _options.gridSize * -1;
    position = horizontalPosition + "px " + verticalPosition + "px";
    $(element).css("background-position", position);
    if (_options.displayTime) {
      $(element).text(--seconds);
    }
    ++row;
  };

  $.start = function () {
    _options.onStart();
    interval = setInterval(function(){ $.tick(_options) }, _options.time);
  };

  $.stop = function () {
    _options.onStop();
    clearInterval(interval);
  }

  $.fn.countdown_timer = function (options) {
    element = this;
    $.extend (_options, $.defaults, options);
    seconds = _options.displaySeconds;
    if ( _options.displayTime) {
      $(element).html(seconds);
    }
    return $;
  };
})(jQuery);<|endoftext|>


<commit_before>export function createSimpleFunctional (c, el = 'div') {
  return {
    functional: true,

    render: (h, { data, children }) => {
      data.staticClass = data.staticClass ? `${c} ${data.staticClass}` : c

      return h(el, data, children)
    }
  }
}

export function createSimpleTransition (name) {
  return {
    functional: true,

    render (createElement, context) {
      let origin = (context.data.attrs || {}).origin || 'top center 0'

      let data = Object.assign({},
        (context.data || {}),
        {
          props: { name },
          on: {
            beforeEnter (el) {
              el.style.transformOrigin = origin
            }
          }
        }
      )

      return createElement('transition', data, context.children)
    }
  }
}

export function directiveConfig (binding, defaults = {}) {
  return Object.assign(
    defaults,
    binding.modifiers,
    { value: binding.arg },
    binding.value || {}
  )
}

export function closestParentTag (tag) {
  let parent = this.$parent

  while(parent) {
    if (!parent.$options._componentTag) {
      return null
    }

    if (parent.$options._componentTag === tag) {
      return parent
    }

    parent = parent.$parent
  }

  return null
}

export function addOnceEventListener (el, event, cb) {
  var once = () => {
    cb()
    el.removeEventListener(event, once, false)
  }

  el.addEventListener(event, once, false)
}

export function browserTransform (el, value) {
  [
    'transform',
    'webkitTransform'
  ].forEach(i => {
    el.style[i] = value
  })
}<commit_msg>swapped out object.assign for a custom function to support older safari browsers<commit_after>export function createSimpleFunctional (c, el = 'div') {
  return {
    functional: true,

    render: (h, { data, children }) => {
      data.staticClass = data.staticClass ? `${c} ${data.staticClass}` : c

      return h(el, data, children)
    }
  }
}

export function createSimpleTransition (name) {
  return {
    functional: true,

    render (createElement, context) {
      let origin = (context.data.attrs || {}).origin || 'top center 0'
      let data = context.data || {}

      data.props = { name }
      data.on = {
        beforeEnter (el) {
          el.style.transformOrigin = origin
        }
      }

      return createElement('transition', data, context.children)
    }
  }
}

export function directiveConfig (binding, defaults = {}) {
  return mergeObject(
    defaults,
    binding.modifiers,
    { value: binding.arg },
    binding.value || {}
  )
}

export function closestParentTag (tag) {
  let parent = this.$parent

  while(parent) {
    if (!parent.$options._componentTag) {
      return null
    }

    if (parent.$options._componentTag === tag) {
      return parent
    }

    parent = parent.$parent
  }

  return null
}

export function addOnceEventListener (el, event, cb) {
  var once = () => {
    cb()
    el.removeEventListener(event, once, false)
  }

  el.addEventListener(event, once, false)
}

export function browserTransform (el, value) {
  [
    'transform',
    'webkitTransform'
  ].forEach(i => {
    el.style[i] = value
  })
}

export function mergeObject(target) {
  for (let i = 1, length = arguments.length; i < length; i++) {
    let source = arguments[i];
    for (let key in source) {
      if (source.hasOwnProperty(key)) {
        target[key] = source[key];
      }
    }
  }

  return target;
}<|endoftext|>


<commit_before>/*!
 * Joshfire Framework 0.9.1
 * http://framework.joshfire.com/
 *
 * Copyright 2011, Joshfire
 * Dual licensed under the GPL Version 2 and a Commercial license.
 * http://framework.joshfire.com/license
 *
 * Date: Wed Jul 20 20:23:43 2011
 */

Joshfire.define(['joshfire/input', 'joshfire/class', 'joshfire/vendor/jquery'], function(Input, Class, $) {

  /**
  * @class Input interface for keyboards
  * @name adapters_browser_inputs_mouse
  * @augments input
  */
  return Class(Input,
      /**
      * @lends adapters_browser_inputs_mouse.prototype
      */
      {

        /**
        * @function
        */
        setup: function(callback) {
          var self = this;

          self.app.subscribe('afterInsert', function() {

            $('.joshover', self.app.baseHtmlEl).live('mousedown', function(event) {

              //        console.log('click', this, event);

              var uiElement = $(this).attr('data-josh-ui-path');
              if (uiElement) {
                self.app.ui.element(uiElement).publish('input', ['enter', $(this).attr('data-josh-grid-id')]);
                return false;
              }

              /* else {
              var menuPath = $(this).attr('data-path');
              console.log("click", menuPath);
              if (menuPath) {
              self.app.tree.moveTo("focus",menuPath);
              }

              setTimeout(function() {

              //If we didn't auto-child
              console.log("autochild?", self.app.tree.getState("focus"), menuPath);

              if (self.app.tree.getState("focus") == menuPath || !menuPath) {
              self.app.publish("input", ["enter"]);
              //,menuPath || event.currentTarget.id]);
              }
              }, 100);
              }*/

            });

            $('.joshover', self.app.baseHtmlEl).live('mouseenter', function(event) {

              var uiElement = $(this).attr('data-josh-ui-path');
              if (uiElement) {
                var uiElement = self.app.ui.element(uiElement);
                if (uiElement && !uiElement.options.noMouseAutoFocus)
                  uiElement.publish('input', ['hover', $(this).attr('data-josh-grid-id')]);
              }
              /* else {

              var menuPath = $(this).attr('data-path') || event.currentTarget.id;
              self.app.publish("input", ["hover", menuPath]);

              }*/

              return false;
            });

            $('.joshover', self.app.baseHtmlEl).live('mouseleave', function(event) {

              var uiElement = $(this).attr('data-josh-ui-path');
              if (uiElement) {
                var uiElement = self.app.ui.element(uiElement);
                if (uiElement && !uiElement.options.noMouseAutoFocus)
                  uiElement.publish('input', ['leave', $(this).attr('data-josh-grid-id')]);
              }
              /* else {

              var menuPath = $(this).attr('data-path') || event.currentTarget.id;
              self.app.publish("input", ["hover", menuPath]);

              }*/

              return false;
            });

          });

          callback(null);
        }

      });

});
<commit_msg>Updated the framework<commit_after>/*!
 * Joshfire Framework 0.9.1
 * http://framework.joshfire.com/
 *
 * Copyright 2011, Joshfire
 * Dual licensed under the GPL Version 2 and a Commercial license.
 * http://framework.joshfire.com/license
 *
 * Date: Wed Jul 20 20:23:43 2011
 */

Joshfire.define(['joshfire/input', 'joshfire/class', 'joshfire/vendor/jquery'], function(Input, Class, $) {

  /**
  * @class Input interface for keyboards
  * @name adapters_browser_inputs_mouse
  * @augments input
  */
  return Class(Input,
      /**
      * @lends adapters_browser_inputs_mouse.prototype
      */
      {

        /**
        * @function
        */
        setup: function(callback) {
          var self = this;

          self.app.subscribe('afterInsert', function() {

            $('.joshover', self.app.baseHtmlEl).live('mousedown', function(event) {
              var uiElement = $(this).attr('data-josh-ui-path');
              if (uiElement) {
                if (event.button == 2) {
                  //right click
                  self.app.ui.element(uiElement).publish('input', ['rightclick', $(this).attr('data-josh-grid-id')]);

                }
                else{
                  self.app.ui.element(uiElement).publish('input', ['enter', $(this).attr('data-josh-grid-id')]);
                  return true;
                }

              }

            });

            $('.joshover', self.app.baseHtmlEl).live('mouseenter', function(event) {

              var uiElement = $(this).attr('data-josh-ui-path');
              if (uiElement) {
                var uiElement = self.app.ui.element(uiElement);
                if (uiElement && !uiElement.options.noMouseAutoFocus)
                  uiElement.publish('input', ['hover', $(this).attr('data-josh-grid-id')]);
              }
              /* else {

              var menuPath = $(this).attr('data-path') || event.currentTarget.id;
              self.app.publish("input", ["hover", menuPath]);

              }*/

              return false;
            });

            $('.joshover', self.app.baseHtmlEl).live('mouseleave', function(event) {

              var uiElement = $(this).attr('data-josh-ui-path');
              if (uiElement) {
                var uiElement = self.app.ui.element(uiElement);
                if (uiElement && !uiElement.options.noMouseAutoFocus)
                  uiElement.publish('input', ['leave', $(this).attr('data-josh-grid-id')]);
              }
              /* else {

              var menuPath = $(this).attr('data-path') || event.currentTarget.id;
              self.app.publish("input", ["hover", menuPath]);

              }*/

              return false;
            });

          });

          callback(null);
        }

      });

});
<|endoftext|>


<commit_before>// fetch the data we want from the different timing API:s

var timings = function() {
  var t = window.performance.timing;

  return {
    timings: {
      domainLookupTime: (t.domainLookupEnd - t.domainLookupStart),
      redirectionTime: (t.fetchStart - t.navigationStart),
      serverConnectionTime: (t.connectEnd - t.requestStart),
      serverResponseTime: (t.responseEnd - t.requestStart),
      pageDownloadTime: (t.responseEnd - t.responseStart),
      domInteractiveTime: (t.domInteractive - t.navigationStart),
      domContentLoadedTime: (t.domContentLoadedEventStart - t.navigationStart),
      pageLoadTime: (t.loadEventStart - t.navigationStart),
      frontEndTime: (t.loadEventStart - t.responseEnd),
      backEndTime: (t.responseStart - t.navigationStart)
    }
  };
};
module.exports = timings;<commit_msg>added copyright<commit_after>/**
 * Browsertime (http://www.browsertime.com)
 * Copyright (c) 2014, Peter Hedenskog, Tobias Lidskog
 * and other contributors
 * Released under the Apache 2.0 License
 */
var timings = function() {
  var t = window.performance.timing;

  return {
    timings: {
      domainLookupTime: (t.domainLookupEnd - t.domainLookupStart),
      redirectionTime: (t.fetchStart - t.navigationStart),
      serverConnectionTime: (t.connectEnd - t.requestStart),
      serverResponseTime: (t.responseEnd - t.requestStart),
      pageDownloadTime: (t.responseEnd - t.responseStart),
      domInteractiveTime: (t.domInteractive - t.navigationStart),
      domContentLoadedTime: (t.domContentLoadedEventStart - t.navigationStart),
      pageLoadTime: (t.loadEventStart - t.navigationStart),
      frontEndTime: (t.loadEventStart - t.responseEnd),
      backEndTime: (t.responseStart - t.navigationStart)
    }
  };
};
module.exports = timings;<|endoftext|>