<commit_before>/*global addEvent, Calendar, cancelEventPropagation, findPosX, findPosY, getStyle, get_format, gettext, interpolate, ngettext, quickElement, removeEvent*/
// Inserts shortcut buttons after all of the following:
//     <input type="text" class="vDateField">
//     <input type="text" class="vTimeField">
(function() {
    'use strict';
    var DateTimeShortcuts = {
        calendars: [],
        calendarInputs: [],
        clockInputs: [],
        dismissClockFunc: [],
        dismissCalendarFunc: [],
        calendarDivName1: 'calendarbox', // name of calendar
 that gets toggled
        calendarDivName2: 'calendarin',  // name of
 that contains calendar
        calendarLinkName: 'calendarlink',// name of the link that is used to toggle
        clockDivName: 'clockbox',        // name of clock
 that gets toggled
        clockLinkName: 'clocklink',      // name of the link that is used to toggle
        shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts
        timezoneWarningClass: 'timezonewarning', // class of the warning for timezone mismatch
        timezoneOffset: 0,
        init: function() {
            var body = document.getElementsByTagName('body')[0];
            var serverOffset = body.getAttribute('data-admin-utc-offset');
            if (serverOffset) {
                var localOffset = new Date().getTimezoneOffset() * -60;
                DateTimeShortcuts.timezoneOffset = localOffset - serverOffset;
            }

            var inputs = document.getElementsByTagName('input');
            for (var i = 0; i < inputs.length; i++) {
                var inp = inputs[i];
                if (inp.getAttribute('type') === 'text' && inp.className.match(/vTimeField/)) {
                    DateTimeShortcuts.addClock(inp);
                    DateTimeShortcuts.addTimezoneWarning(inp);
                }
                else if (inp.getAttribute('type') === 'text' && inp.className.match(/vDateField/)) {
                    DateTimeShortcuts.addCalendar(inp);
                    DateTimeShortcuts.addTimezoneWarning(inp);
                }
            }
        },
        // Return the current time while accounting for the server timezone.
        now: function() {
            var body = document.getElementsByTagName('body')[0];
            var serverOffset = body.getAttribute('data-admin-utc-offset');
            if (serverOffset) {
                var localNow = new Date();
                var localOffset = localNow.getTimezoneOffset() * -60;
                localNow.setTime(localNow.getTime() + 1000 * (serverOffset - localOffset));
                return localNow;
            } else {
                return new Date();
            }
        },
        // Add a warning when the time zone in the browser and backend do not match.
        addTimezoneWarning: function(inp) {
            var $ = django.jQuery;
            var warningClass = DateTimeShortcuts.timezoneWarningClass;
            var timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600;

            // Only warn if there is a time zone mismatch.
            if (!timezoneOffset) {
                return;
            }

            // Check if warning is already there.
            if ($(inp).siblings('.' + warningClass).length) {
                return;
            }

            var message;
            if (timezoneOffset > 0) {
                message = ngettext(
                    'Note: You are %s hour ahead of server time.',
                    'Note: You are %s hours ahead of server time.',
                    timezoneOffset
                );
            }
            else {
                timezoneOffset *= -1;
                message = ngettext(
                    'Note: You are %s hour behind server time.',
                    'Note: You are %s hours behind server time.',
                    timezoneOffset
                );
            }
            message = interpolate(message, [timezoneOffset]);

            var $warning = $('');
            $warning.attr('class', warningClass);
            $warning.text(message);

            $(inp).parent()
                .append($('
'))
                .append($warning);
        },
        // Add clock widget to a given field
        addClock: function(inp) {
            var num = DateTimeShortcuts.clockInputs.length;
            DateTimeShortcuts.clockInputs[num] = inp;
            DateTimeShortcuts.dismissClockFunc[num] = function() { DateTimeShortcuts.dismissClock(num); return true; };

            // Shortcut links (clock icon and "Now" link)
            var shortcuts_span = document.createElement('span');
            shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
            inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
            var now_link = document.createElement('a');
            now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", -1);");
            now_link.appendChild(document.createTextNode(gettext('Now')));
            var clock_link = document.createElement('a');
            clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
            clock_link.id = DateTimeShortcuts.clockLinkName + num;
            quickElement(
                'span', clock_link, '',
                'class', 'clock-icon',
                'title', gettext('Choose a Time')
            );
            shortcuts_span.appendChild(document.createTextNode('\u00A0'));
            shortcuts_span.appendChild(now_link);
            shortcuts_span.appendChild(document.createTextNode('\u00A0|\u00A0'));
            shortcuts_span.appendChild(clock_link);

            // Create clock link div
            //
            // Markup looks like:
            //

            //
Choose a time

            //

            //
Now

            //
Midnight

            //
6 a.m.

            //
Noon

            //
6 p.m.

            //

            //
Cancel

            //

            var clock_box = document.createElement('div');
            clock_box.style.display = 'none';
            clock_box.style.position = 'absolute';
            clock_box.className = 'clockbox module';
            clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
            document.body.appendChild(clock_box);
            addEvent(clock_box, 'click', cancelEventPropagation);

            quickElement('h2', clock_box, gettext('Choose a time'));
            var time_list = quickElement('ul', clock_box);
            time_list.className = 'timelist';
            quickElement("a", quickElement("li", time_list), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", -1);");
            quickElement("a", quickElement("li", time_list), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 0);");
            quickElement("a", quickElement("li", time_list), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 6);");
            quickElement("a", quickElement("li", time_list), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 12);");
            quickElement("a", quickElement("li", time_list), gettext("6 p.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 18);");

            var cancel_p = quickElement('p', clock_box);
            cancel_p.className = 'calendar-cancel';
            quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
            django.jQuery(document).bind('keyup', function(event) {
                if (event.which === 27) {
                    // ESC key closes popup
                    DateTimeShortcuts.dismissClock(num);
                    event.preventDefault();
                }
            });
        },
        openClock: function(num) {
            var clock_box = document.getElementById(DateTimeShortcuts.clockDivName + num);
            var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName + num);

            // Recalculate the clockbox position
            // is it left-to-right or right-to-left layout ?
            if (getStyle(document.body, 'direction') !== 'rtl') {
                clock_box.style.left = findPosX(clock_link) + 17 + 'px';
            }
            else {
                // since style's width is in em, it'd be tough to calculate
                // px value of it. let's use an estimated px for now
                // TODO: IE returns wrong value for findPosX when in rtl mode
                //       (it returns as it was left aligned), needs to be fixed.
                clock_box.style.left = findPosX(clock_link) - 110 + 'px';
            }
            clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px';

            // Show the clock box
            clock_box.style.display = 'block';
            addEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]);
        },
        dismissClock: function(num) {
            document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
            removeEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]);
        },
        handleClockQuicklink: function(num, val) {
            var d;
            if (val === -1) {
                d = DateTimeShortcuts.now();
            }
            else {
                d = new Date(1970, 1, 1, val, 0, 0, 0);
            }
            DateTimeShortcuts.clockInputs[num].value = d.strftime(get_format('TIME_INPUT_FORMATS')[0]);
            DateTimeShortcuts.clockInputs[num].focus();
            DateTimeShortcuts.dismissClock(num);
        },
        // Add calendar widget to a given field.
        addCalendar: function(inp) {
            var num = DateTimeShortcuts.calendars.length;

            DateTimeShortcuts.calendarInputs[num] = inp;
            DateTimeShortcuts.dismissCalendarFunc[num] = function() { DateTimeShortcuts.dismissCalendar(num); return true; };

            // Shortcut links (calendar icon and "Today" link)
            var shortcuts_span = document.createElement('span');
            shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
            inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
            var today_link = document.createElement('a');
            today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
            today_link.appendChild(document.createTextNode(gettext('Today')));
            var cal_link = document.createElement('a');
            cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
            cal_link.id = DateTimeShortcuts.calendarLinkName + num;
            quickElement(
                'span', cal_link, '',
                'class', 'date-icon',
                'title', gettext('Choose a Date')
            );
            shortcuts_span.appendChild(document.createTextNode('\u00A0'));
            shortcuts_span.appendChild(today_link);
            shortcuts_span.appendChild(document.createTextNode('\u00A0|\u00A0'));
            shortcuts_span.appendChild(cal_link);

            // Create calendarbox div.
            //
            // Markup looks like:
            //
            //

            //

            //           ‹
            //           › February 2003
            //

            //

            //
            //

            //

            //          Yesterday | Today | Tomorrow
            //

            //
Cancel

            //

            var cal_box = document.createElement('div');
            cal_box.style.display = 'none';
            cal_box.style.position = 'absolute';
            cal_box.className = 'calendarbox module';
            cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
            document.body.appendChild(cal_box);
            addEvent(cal_box, 'click', cancelEventPropagation);

            // next-prev links
            var cal_nav = quickElement('div', cal_box);
            var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev(' + num + ');');
            cal_nav_prev.className = 'calendarnav-previous';
            var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext(' + num + ');');
            cal_nav_next.className = 'calendarnav-next';

            // main box
            var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
            cal_main.className = 'calendar';
            DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
            DateTimeShortcuts.calendars[num].drawCurrent();

            // calendar shortcuts
            var shortcuts = quickElement('div', cal_box);
            shortcuts.className = 'calendar-shortcuts';
            quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
            shortcuts.appendChild(document.createTextNode('\u00A0|\u00A0'));
            quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
            shortcuts.appendChild(document.createTextNode('\u00A0|\u00A0'));
            quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');

            // cancel bar
            var cancel_p = quickElement('p', cal_box);
            cancel_p.className = 'calendar-cancel';
            quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
            django.jQuery(document).bind('keyup', function(event) {
                if (event.which === 27) {
                    // ESC key closes popup
                    DateTimeShortcuts.dismissCalendar(num);
                    event.preventDefault();
                }
            });
        },
        openCalendar: function(num) {
            var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1 + num);
            var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName + num);
            var inp = DateTimeShortcuts.calendarInputs[num];

            // Determine if the current value in the input has a valid date.
            // If so, draw the calendar with that date's year and month.
            if (inp.value) {
                var format = get_format('DATE_INPUT_FORMATS')[0];
                var selected = inp.value.strptime(format);
                var year = selected.getUTCFullYear();
                var month = selected.getUTCMonth() + 1;
                var re = /\d{4}/;
                if (re.test(year.toString()) && month >= 1 && month <= 12) {
                    DateTimeShortcuts.calendars[num].drawDate(month, year, selected);
                }
            }

            // Recalculate the clockbox position
            // is it left-to-right or right-to-left layout ?
            if (getStyle(document.body, 'direction') !== 'rtl') {
                cal_box.style.left = findPosX(cal_link) + 17 + 'px';
            }
            else {
                // since style's width is in em, it'd be tough to calculate
                // px value of it. let's use an estimated px for now
                // TODO: IE returns wrong value for findPosX when in rtl mode
                //       (it returns as it was left aligned), needs to be fixed.
                cal_box.style.left = findPosX(cal_link) - 180 + 'px';
            }
            cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px';

            cal_box.style.display = 'block';
            addEvent(document, 'click', DateTimeShortcuts.dismissCalendarFunc[num]);
        },
        dismissCalendar: function(num) {
            document.getElementById(DateTimeShortcuts.calendarDivName1 + num).style.display = 'none';
            removeEvent(document, 'click', DateTimeShortcuts.dismissCalendarFunc[num]);
        },
        drawPrev: function(num) {
            DateTimeShortcuts.calendars[num].drawPreviousMonth();
        },
        drawNext: function(num) {
            DateTimeShortcuts.calendars[num].drawNextMonth();
        },
        handleCalendarCallback: function(num) {
            var format = get_format('DATE_INPUT_FORMATS')[0];
            // the format needs to be escaped a little
            format = format.replace('\\', '\\\\');
            format = format.replace('\r', '\\r');
            format = format.replace('\n', '\\n');
            format = format.replace('\t', '\\t');
            format = format.replace("'", "\\'");
            return ["function(y, m, d) { DateTimeShortcuts.calendarInputs[",
                   num,
                   "].value = new Date(y, m-1, d).strftime('",
                   format,
                   "');DateTimeShortcuts.calendarInputs[",
                   num,
                   "].focus();document.getElementById(DateTimeShortcuts.calendarDivName1+",
                   num,
                   ").style.display='none';}"].join('');
        },
        handleCalendarQuickLink: function(num, offset) {
            var d = DateTimeShortcuts.now();
            d.setDate(d.getDate() + offset);
            DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]);
            DateTimeShortcuts.calendarInputs[num].focus();
            DateTimeShortcuts.dismissCalendar(num);
        }
    };

    addEvent(window, 'load', DateTimeShortcuts.init);
    window.DateTimeShortcuts = DateTimeShortcuts;
})();
<commit_msg>Update public/admin/js/admin/DateTimeShortcuts.js<commit_after><|endoftext|>


<commit_before>import browserify from 'browserify';
import watchify from 'watchify';
import browserSync from 'browser-sync';
import uglify from 'gulp-uglify';
import streamify from 'gulp-streamify';
import source from 'vinyl-source-stream';
import path from 'path';
import notify from 'gulp-notify';
import util from 'gulp-util';
import collapse from 'bundle-collapser/plugin';
import sourcemaps from 'gulp-sourcemaps';
import buffer from 'vinyl-buffer';

/**
 * Gulp task to run browserify over config.entryJs
 * @param  {object} config Global configuration
 * @return {function}        Function task
 */
export default function browserifyTask(userConfig) {
    const gulp = this.gulp;
    const config = userConfig || this.config;
    let onBundleError;
    if (config.notify.onError) {
        onBundleError = notify.onError('Browserify Error: <%= error.message %>');
    } else {
        onBundleError = (err) => {
            util.log(util.colors.red('Error'), err.message);
        };
    }

    /**
     * Function to run the Browserify Bundler over pipes
     * @param  {object} bundler Bundler object
     * @return {object} stream  Gulp stream
     */
    function browserifyBundle(bundler) {
        if (config.isProduction) {
            bundler.plugin(collapse);
        }

        let stream = bundler.bundle()
            .on('error', onBundleError)
            .pipe(source('index.js'));

        if (config.isProduction) {
            stream = stream.pipe(streamify(uglify()));
        } else {
            // source map external
            stream = stream.pipe(buffer())
                .pipe(sourcemaps.init({
                    loadMaps: true
                }))
                .pipe(sourcemaps.write('./', {
                    sourceRoot: '/'
                }));
        }

        stream = stream.pipe(gulp.dest(config.destPath));

        if (config.watch) {
            stream.pipe(browserSync.stream({once: true}));
        }

        if (config.notify.onUpdated) {
            return stream.pipe(notify('Browserify Bundle - Updated'));
        }

        return stream;
    }

    return () => {
        let bundler = browserify({
            entries: path.join(config.sourcePath, config.entryJs),
            debug: !(config.isProduction),
            transforms: config.browserify.transforms
        });

        config.browserify.plugins.forEach((elem) => {
            bundler = bundler.plugin(elem.module, elem.opts);
        });

        if (config.watch) {
            bundler = watchify(bundler);

            bundler.on('update', () => {
                browserifyBundle(bundler);
            });
        }

        return browserifyBundle(bundler);
    };
}
<commit_msg>fix add transforms by config<commit_after>import browserify from 'browserify';
import watchify from 'watchify';
import browserSync from 'browser-sync';
import uglify from 'gulp-uglify';
import streamify from 'gulp-streamify';
import source from 'vinyl-source-stream';
import path from 'path';
import notify from 'gulp-notify';
import util from 'gulp-util';
import collapse from 'bundle-collapser/plugin';
import sourcemaps from 'gulp-sourcemaps';
import buffer from 'vinyl-buffer';

/**
 * Gulp task to run browserify over config.entryJs
 * @param  {object} config Global configuration
 * @return {function}        Function task
 */
export default function browserifyTask(userConfig) {
    const gulp = this.gulp;
    const config = userConfig || this.config;
    let onBundleError;
    if (config.notify.onError) {
        onBundleError = notify.onError('Browserify Error: <%= error.message %>');
    } else {
        onBundleError = (err) => {
            util.log(util.colors.red('Error'), err.message);
        };
    }

    /**
     * Function to run the Browserify Bundler over pipes
     * @param  {object} bundler Bundler object
     * @return {object} stream  Gulp stream
     */
    function browserifyBundle(bundler) {
        if (config.isProduction) {
            bundler.plugin(collapse);
        }

        let stream = bundler.bundle()
            .on('error', onBundleError)
            .pipe(source('index.js'));

        if (config.isProduction) {
            stream = stream.pipe(streamify(uglify()));
        } else {
            // source map external
            stream = stream.pipe(buffer())
                .pipe(sourcemaps.init({
                    loadMaps: true
                }))
                .pipe(sourcemaps.write('./', {
                    sourceRoot: '/'
                }));
        }

        stream = stream.pipe(gulp.dest(config.destPath));

        if (config.watch) {
            stream.pipe(browserSync.stream({once: true}));
        }

        if (config.notify.onUpdated) {
            return stream.pipe(notify('Browserify Bundle - Updated'));
        }

        return stream;
    }

    return () => {
        let bundler = browserify({
            entries: path.join(config.sourcePath, config.entryJs),
            debug: !(config.isProduction),
            transforms: config.browserify.transforms
        });

        config.browserify.transforms.forEach((elem) => {
            bundler = bundler.transform(elem);
        });

        config.browserify.plugins.forEach((elem) => {
            bundler = bundler.plugin(elem.module, elem.opts);
        });

        if (config.watch) {
            bundler = watchify(bundler);

            bundler.on('update', () => {
                browserifyBundle(bundler);
            });
        }

        return browserifyBundle(bundler);
    };
}
<|endoftext|>


<commit_before>(function(angular) {
	var module = angular.module('net.enzey.autocomplete', ['ngSanitize']);

	var controllerName = 'nzCtrl';
	var defaultTemplateUrl = 'AutoComplete/hintTemplate.html';
	module.run(function($templateCache) {
		var defaultTemplate = '

';
		$templateCache.put(defaultTemplateUrl, defaultTemplate);
	});

	module.directive('nzReturnModelCtrl', function($parse) {
		return {
			restrict: 'A',
			require: '?ngModel',
			compile: function($element, $attrs) {
				var myName = this.name;
				var myDataName = 'data' + myName[0].toUpperCase() + myName.slice(1);

				return {
					pre: function (scope, element, attr, modelCtrl) {
						if (attr.$attr[myName]) {
							$parse(attr[myName]).assign(scope, modelCtrl);
						} else if (attr.$attr[myDataName]) {
							$parse(attr[myDataName]).assign(scope, modelCtrl);
						} else {
							throw 'location to return the model controller is required.';
						}
					}
				};
			}
		};
	});

	module.directive('nzAutoCompleteHintText', function($parse) {
		return {
			restrict: 'AE',
			link: {
				post: function(scope, element, attrs) {
					var inputText = scope[controllerName].$viewValue;
					var hintText = scope.displayPath === null ? 'hint' : 'hint.' + scope.displayPath;
					var highlightRegExp =  new RegExp('(' + inputText +  ')', 'gi');
					var text = $parse(hintText)(scope);
					if (text) {
						var markedText = text.replace(highlightRegExp, '$1');

						element[0].innerHTML = markedText;
					}
				}
			}
		};
	});

	module.directive('nzAutoCompleteInclude', function($compile, $http, $templateCache) {
		return {
			restrict: 'AE',
			link: function (scope, element, attr) {
				$http.get(attr.nzAutoCompleteInclude, {cache: $templateCache})
				.success(function(html) {
					element.replaceWith($compile(html)(scope));
				});
			}
		};
	});

	var positionAndAddScrollBar = function(hintList, inputElem) {
		hintList.css('display', 'block');
		var scroller = hintList.find('div')[0];
		if (scroller.scrollHeight > scroller.clientHeight) {
			angular.element(scroller).css('overflow-y', 'scroll');
		} else {
			angular.element(scroller).css('overflow-y', '');
		}
		hintList.css('display', '');
	};

	module.directive('nzAutoComplete', function($parse, $timeout) {
		return {
			scope: {},
			restrict: 'AE',
			template: function(element, attr) {
				element.addClass('autoComplete');

				var inputElem = element[0].querySelector('input');
				if (inputElem) {
					inputElem = angular.element(inputElem);
				} else {
					inputElem = angular.element('<input type="text"></input>');
				}
				inputElem.removeAttr('ng-model');
				inputElem.removeAttr('data-ng-model');
				var hintInputElem = inputElem.clone();

				inputElem.addClass('textEntry');
				inputElem.attr('nz-return-model-ctrl', controllerName);
				hintInputElem.addClass('hintBox');
				hintInputElem.attr('tabindex', '-1');
				hintInputElem.removeAttr('placeholder');

				var wrapper = angular.element('

');
				wrapper.append(hintInputElem);
				wrapper.append(angular.element(''));
				wrapper.append(inputElem);
				wrapper.append(angular.element('

'));

				element.empty();
				return wrapper[0].innerHTML;
			},
			compile: function ($element, $attrs) {
				var inputElem =     angular.element($element[0].querySelector('.textEntry'));
				var hintInputElem = angular.element($element[0].querySelector('.hintBox'));

				var ngModelName = '$parent.' + $attrs.ngModel;
				inputElem.attr('ng-model', ngModelName);

				var templateUrl = angular.isDefined($attrs.templateUrl) ? $attrs.templateUrl : defaultTemplateUrl;
				var hintList = angular.element('\

\
						\
						<div class="scroller" ng-hide="hints.length < 2">\

\

\

\

\

\
							{{noResultsText}}\

\

\
				');
				$element.append(hintList);

				var displayHint = false;
				return {
					pre: function(scope, element, attrs) {
						scope.hints = [];

						scope.displayPath = null;
						if (angular.isDefined(attrs.displayPath)) {
							scope.displayPath = attrs.displayPath;
						}

						scope.noResultsText = "No Results";
						if (angular.isDefined(attrs.noResultsText)) {
							scope.noResultsText = attrs.noResultsText;
						}

						scope.hoverOver = function(selectedIndex) {
							scope.selectRow(selectedIndex);
						};

						scope.getHintDisplay = function() {
							var hintDisplayObj = scope.hints[scope.selectedHintIndex];
							if (scope.displayPath !== null) {
								return $parse(scope.displayPath)(hintDisplayObj);
							}
							return hintDisplayObj;
						};
						scope.selectRow = function(index) {
							if (index === scope.selectedHintIndex) {return;}

							if (0 <= index && index < scope.hints.length) {
								var scroller = element[0].querySelector('.scroller');
								var hints =   angular.element(scroller).children();

								$timeout(function() {
									hintList.css('display', 'block');
									var selectedHint = scroller.querySelector('.selectedHint');
									if (selectedHint.offsetTop < scroller.scrollTop) {
										// scrollUp
										scroller.scrollTop = selectedHint.offsetTop;
									} else if (selectedHint.offsetTop + selectedHint.clientHeight > scroller.scrollTop + scroller.clientHeight) {
										// scrollDown
										scroller.scrollTop = selectedHint.offsetTop + selectedHint.clientHeight - scroller.clientHeight;
									}
									hintList.css('display', '');
								}, 0, false);

								scope.selectedHintIndex = index;
								if (displayHint === true) {
									var hintDisplayText = scope.getHintDisplay();
									var userInputString = inputElem.val();
									hintInputElem.val(userInputString + hintDisplayText.slice(userInputString.length, hintDisplayText.length));
								}
							}
						};

						/*
						positionHintsFn = function(hintList, inputElem) {
							$(hintList).position({
								my: "left top",
								at: "left bottom",
								of: inputElem,
								collision: 'flip'
							});
						}
						*/
						scope.positionHintsFn = function(){};
						if (angular.isDefined(attrs.positionHintsFn)) {
							var customPositionFunction = $parse(attrs.positionHintsFn)(scope.$parent);
							if (angular.isFunction(customPositionFunction)) {
								scope.positionHintsFn = customPositionFunction;
							}
						}

					},
					post: function (scope, element, attrs) {
						var modelCtrl = scope[controllerName];

						var displaySuggestions = function(hintResults) {
							scope.hints = hintResults;
							if (!scope.hints) {scope.hints = [];}

							if (scope.hints.length > 0) {
								var regex = new RegExp('^' + modelCtrl.$viewValue, 'i');
								var objParser = null;
								if (scope.displayPath !== null) {
									objParser = $parse(scope.displayPath);
								}
								scope.hints.forEach(function(hintObj) {
									if (!displayHint) {return;}

									if (objParser) {
										displayHint = displayHint && regex.test(objParser(hintObj));
									} else {
										displayHint = displayHint && regex.test(hintObj);
									}
								});
								scope.selectRow(0);
							} else {
								element.addClass('noResults');
							}

							$timeout(function() {
								if (!scope.positionHintsFn(hintList, inputElem)) {
									positionAndAddScrollBar(hintList, inputElem);
								}
							}, 0, false);

						};

						var getResultsFn = $parse(attrs.getResultsFn)(scope.$parent);
						if (!getResultsFn || !typeof getResultsFn === 'function') {
							throw 'A function that returns results is required!';
						}
						var pendingResultsFunctionCall;
						var getResults = function() {
							displayHint = inputElem[0].scrollWidth <= inputElem[0].clientWidth;
							//setParentModel();

							scope.selectedHintIndex = null;
							scope.hints = [];
							element.addClass('loading');
							element.removeClass('noResults');
							// Stop any pending requests

							$timeout.cancel(pendingResultsFunctionCall);

							if (angular.isDefined(modelCtrl.$viewValue) && minimumChars <= modelCtrl.$viewValue.length) {
								pendingResultsFunctionCall = $timeout(function() {
									element.removeClass('loading');
									getResultsFn( modelCtrl.$viewValue ).then(displaySuggestions);
								}, silentPeriod, true);
							} else {
								element.removeClass('loading');
							}
						};

						scope.select = function(selectedIndex) {
							scope.selectedHintIndex = selectedIndex;
							modelCtrl.$setViewValue(scope.getHintDisplay());
							scope.actualText = modelCtrl.$viewValue;
							inputElem.val(modelCtrl.$viewValue);
							inputElem[0].focus();
						};

						var minimumChars = +$parse(attrs.minChar)(scope.$parent);
						if (isNaN(minimumChars)) {minimumChars = 1;}
						if (minimumChars === 0) {
							if (!modelCtrl.$viewValue) {
								modelCtrl.$setViewValue('');
							}
							getResults();
						}

						var silentPeriod = +$parse(attrs.silentPeriod)(scope.$parent);
						if (isNaN(silentPeriod)) {silentPeriod = 250;}

						var isSelectionRequired = false;
						if (angular.isDefined(attrs.selectionRequired) && attrs.selectionRequired === 'true') {
							isSelectionRequired = true;
						}

						modelCtrl.$parsers.push(function(value) {
							hintInputElem.val('');
							if (value) {
								var result;
								if (isSelectionRequired) {
									var selectedObj = scope.hints[scope.selectedHintIndex];
									if (scope.hints && scope.hints.length > 0 &&
									( value === selectedObj || value === $parse(scope.displayPath)(selectedObj) ) ) {
										result = selectedObj;
									}
								} else {
									if (minimumChars <= value.length) {
										result = value;
									}
								}
								if (!result) {
									modelCtrl.$setValidity('hasSelection', false);
								}
							}
							getResults();
							return result;
						});
						modelCtrl.$formatters.push(function(value) {
							$timeout(getResults, 0, true);
							hintInputElem.val('');
							if (!value) {return;}
							var result;
							if (scope.displayPath) {
								result = $parse(scope.displayPath)(value);
							} else {
								result = value;
							}
							return result;
						});

						inputElem.bind("focus", function() {
							if (scope.hints && scope.hints.length > 0) {
								$timeout(function() {
									scope.positionHintsFn(hintList, inputElem);
								}, 0, false);
							}
						});

						inputElem.bind("keydown", function(e) {
							if (scope.selectedHintIndex !== null && (e.keyCode === 13 || e.keyCode === 9)) {
								var selectedObj = scope.hints[scope.selectedHintIndex];
								$parse(ngModelName).assign(scope, selectedObj);
								scope.$apply();
							} else if (e.keyCode === 40) {
								// key down
								if (scope.selectedHintIndex !== null && scope.hints.length > 1) {
									var newIndex;
									if (scope.selectedHintIndex === scope.hints.length - 1) {
										newIndex = 0;
									} else {
										newIndex = scope.selectedHintIndex + 1;
									}
									scope.selectRow(newIndex);
									scope.$apply();
								}
								e.preventDefault();
								e.stopPropagation();
							} else if (e.keyCode === 38) {
								// key up
								if (scope.selectedHintIndex !== null && scope.hints.length > 1) {
									var newIndex;
									if (scope.selectedHintIndex === 0) {
										newIndex = scope.hints.length - 1;
									} else {
										newIndex = scope.selectedHintIndex - 1;
									}
									scope.selectRow(newIndex);
									scope.$apply();
								}
								e.preventDefault();
								e.stopPropagation();
							}
						});

					}
				}
			}
		};
	});

})(angular);<commit_msg>Multiple Updates.<commit_after>(function(angular) {
	var module = angular.module('net.enzey.autocomplete', ['ngSanitize']);

	var defaultTemplateUrl = 'AutoComplete/hintTemplate.html';
	module.run(function($templateCache) {
		var defaultTemplate = '

';
		$templateCache.put(defaultTemplateUrl, defaultTemplate);
	});

	module.directive('nzAutoCompleteHintText', function($parse) {
		return {
			restrict: 'AE',
			link: {
				post: function(scope, element, attrs) {
					var inputText = scope.ngModelCtrl.$viewValue;
					var hintText = scope.displayPath === null ? 'hint' : 'hint.' + scope.displayPath;
					var highlightRegExp =  new RegExp('(' + inputText +  ')', 'gi');
					var text = $parse(hintText)(scope);
					if (text) {
						var markedText = text.replace(highlightRegExp, '$1');

						element[0].innerHTML = markedText;
					}
				}
			}
		};
	});

	module.directive('nzAutoCompleteInclude', function($parse, $compile, $http, $templateCache) {
		return {
			restrict: 'AE',
			compile: function() {
				var directiveName = this.name;
				return function (scope, element, attr) {
					var templateUrl = $parse(attr[directiveName])(scope);
					$http.get(templateUrl, {cache: $templateCache})
					.success(function(html) {
						element.replaceWith($compile(html)(scope));
					});
				}
			}
		};
	});

	var positionAndAddScrollBar = function(hintList, inputElem) {
		hintList.css('display', 'block');
		var scroller = hintList.find('div')[0];
		if (scroller.scrollHeight > scroller.clientHeight) {
			angular.element(scroller).css('overflow-y', 'scroll');
		} else {
			angular.element(scroller).css('overflow-y', '');
		}
		hintList.css('display', '');
	};

	module.directive('nzAutoComplete', function($parse, $timeout) {
		return {
			scope: {},
			restrict: 'AE',
			template: function(element, attr) {
				element.addClass('autoComplete');

				var inputElem = element[0].querySelector('input');
				if (inputElem) {
					inputElem = angular.element(inputElem);
				} else {
					inputElem = angular.element('<input type="text"></input>');
				}
				inputElem.removeAttr('ng-model');
				inputElem.removeAttr('data-ng-model');
				var hintInputElem = inputElem.clone();

				inputElem.addClass('textEntry');
				inputElem.attr('ng-keypress', "keyPressEvent($event)");
				hintInputElem.addClass('hintBox');
				hintInputElem.attr('tabindex', '-1');
				hintInputElem.removeAttr('placeholder');

				var wrapper = angular.element('

');
				wrapper.append(hintInputElem);
				wrapper.append(angular.element(''));
				wrapper.append(inputElem);
				wrapper.append(angular.element('

'));

				element.empty();
				return wrapper[0].innerHTML;
			},
			compile: function ($element, $attrs) {
				var inputElem =     angular.element($element[0].querySelector('.textEntry'));
				var hintInputElem = angular.element($element[0].querySelector('.hintBox'));

				var ngModelName = '$parent.' + $attrs.ngModel;
				inputElem.attr('ng-model', ngModelName);

				var templateUrl = angular.isDefined($attrs.templateUrl) ? $attrs.templateUrl : "'" + defaultTemplateUrl + "'";
				var hintList = angular.element('\

\
						\
						<div class="scroller" ng-hide="hints.length < 2">\

\

\

\

\

\
							{{noResultsText}}\

\

\
				');
				$element.append(hintList);

				var displayHint = false;
				return {
					pre: function(scope, element, attrs) {
						scope.hints = [];

						scope.keyPressEvent = function(e) {
							if (scope.selectedHintIndex !== null && (e.keyCode === 13 || e.keyCode === 9)) {
								scope.select(scope.selectedHintIndex);
							} else if (e.keyCode === 40) {
								// key down
								if (scope.selectedHintIndex !== null && scope.hints.length > 1) {
									var newIndex;
									if (scope.selectedHintIndex === scope.hints.length - 1) {
										newIndex = 0;
									} else {
										newIndex = scope.selectedHintIndex + 1;
									}
									scope.selectRow(newIndex);
								}
								e.preventDefault();
								e.stopPropagation();
							} else if (e.keyCode === 38) {
								// key up
								if (scope.selectedHintIndex !== null && scope.hints.length > 1) {
									var newIndex;
									if (scope.selectedHintIndex === 0) {
										newIndex = scope.hints.length - 1;
									} else {
										newIndex = scope.selectedHintIndex - 1;
									}
									scope.selectRow(newIndex);
								}
								e.preventDefault();
								e.stopPropagation();
							}
						};

						scope.displayPath = null;
						if (angular.isDefined(attrs.displayPath)) {
							scope.displayPath = attrs.displayPath;
						}

						scope.noResultsText = "No Results";
						if (angular.isDefined(attrs.noResultsText)) {
							scope.noResultsText = attrs.noResultsText;
						}

						scope.hoverOver = function(selectedIndex) {
							scope.selectRow(selectedIndex);
						};

					},
					post: function (scope, element, attrs) {
						var modelCtrl = angular.element(inputElem).controller('ngModel');
						scope.ngModelCtrl = modelCtrl;

						/*
						positionHintsFn = function(hintList, inputElem) {
							$(hintList).position({
								my: "left top",
								at: "left bottom",
								of: inputElem,
								collision: 'flip'
							});
						}
						*/
						var positionHintsFn = function(){};
						if (angular.isDefined(attrs.positionHintsFn)) {
							var customPositionFunction = $parse(attrs.positionHintsFn)(scope.$parent);
							if (angular.isFunction(customPositionFunction)) {
								positionHintsFn = customPositionFunction;
							}
						}

						var getResultsFn = $parse(attrs.getResultsFn)(scope.$parent);
						if (!getResultsFn || !typeof getResultsFn === 'function') {
							throw 'A function that returns results is required!';
						}

						var minimumChars = +$parse(attrs.minChar)(scope.$parent);
						if (isNaN(minimumChars)) {minimumChars = 1;}
						if (minimumChars === 0) {
							getResultsFn( modelCtrl.$viewValue ).then(displaySuggestions);
						}

						var silentPeriod = +$parse(attrs.silentPeriod)(scope.$parent);
						if (isNaN(silentPeriod)) {silentPeriod = 250;}

						var isSelectionRequired = false;
						if (angular.isDefined(attrs.selectionRequired) && attrs.selectionRequired === 'true') {
							isSelectionRequired = true;
						}

						var getHintDisplay = function() {
							var hintDisplayObj = scope.hints[scope.selectedHintIndex];
							if (scope.displayPath !== null) {
								return $parse(scope.displayPath)(hintDisplayObj);
							}
							return hintDisplayObj;
						};
						scope.selectRow = function(index) {
							if (index === scope.selectedHintIndex) {return;}

							if (0 <= index && index < scope.hints.length) {
								var scroller = element[0].querySelector('.scroller');
								var hints =   angular.element(scroller).children();

								$timeout(function() {
									hintList.css('display', 'block');
									var selectedHint = scroller.querySelector('.selectedHint');
									if (selectedHint.offsetTop < scroller.scrollTop) {
										// scrollUp
										scroller.scrollTop = selectedHint.offsetTop;
									} else if (selectedHint.offsetTop + selectedHint.clientHeight > scroller.scrollTop + scroller.clientHeight) {
										// scrollDown
										scroller.scrollTop = selectedHint.offsetTop + selectedHint.clientHeight - scroller.clientHeight;
									}
									hintList.css('display', '');
								}, 0, false);

								scope.selectedHintIndex = index;
								if (displayHint === true) {
									var hintDisplayText = getHintDisplay();
									var userInputString = inputElem.val();
									hintInputElem.val(userInputString + hintDisplayText.slice(userInputString.length, hintDisplayText.length));
								}
							}
						};

						scope.select = function(selectedIndex) {
							scope.selectedHintIndex = selectedIndex;
							var selectedObj = scope.hints[scope.selectedHintIndex];
							$parse(ngModelName).assign(scope, selectedObj);
							inputElem[0].focus();
						};

						var displaySuggestions = function(hintResults) {
							scope.hints = hintResults;
							if (!scope.hints) {scope.hints = [];}

							if (scope.hints.length > 0) {
								var regex = new RegExp('^' + modelCtrl.$viewValue, 'i');
								var objParser = null;
								if (scope.displayPath !== null) {
									objParser = $parse(scope.displayPath);
								}
								scope.hints.forEach(function(hintObj) {
									if (!displayHint) {return;}

									if (objParser) {
										displayHint = displayHint && regex.test(objParser(hintObj));
									} else {
										displayHint = displayHint && regex.test(hintObj);
									}
								});
								scope.selectRow(0);
							} else {
								element.addClass('noResults');
							}

							if (positionHintsFn) {
								$timeout(function() {
									if (!positionHintsFn(hintList, inputElem)) {
										positionAndAddScrollBar(hintList, inputElem);
									}
								}, 0, false);
							}

						};

						modelCtrl.$parsers.push(function(value) {
							hintInputElem.val('');
							if (value) {
								var result;
								if (isSelectionRequired) {
									var selectedObj = scope.hints[scope.selectedHintIndex];
									if (scope.hints && scope.hints.length > 0) {
										var selectedStringValue = selectedObj;
										if (angular.isDefined(scope.displayPath)) {
											selectedStringValue = $parse(scope.displayPath)(selectedStringValue)
										}
										if (new RegExp(selectedStringValue, 'gi').test(value)) {
											result = selectedObj;
										}
									}
								} else {
									if (minimumChars <= value.length) {
										result = value;
									}
								}
								modelCtrl.$setValidity('hasSelection', result ? true : false);
							}
							getResults();
							return result;
						});
						modelCtrl.$formatters.push(function(value) {
							$timeout(getResults, 0, true);
							hintInputElem.val('');
							if (!value) {return;}
							var result;
							if (scope.displayPath) {
								result = $parse(scope.displayPath)(value);
							} else {
								result = value;
							}
							return result;
						});

						var pendingResultsFunctionCall;
						var getResults = function() {
							displayHint = inputElem[0].scrollWidth <= inputElem[0].clientWidth;
							//setParentModel();

							scope.selectedHintIndex = null;
							scope.hints = [];
							element.addClass('loading');
							element.removeClass('noResults');
							// Stop any pending requests

							$timeout.cancel(pendingResultsFunctionCall);

							if (modelCtrl.$viewValue && minimumChars <= modelCtrl.$viewValue.length) {
								pendingResultsFunctionCall = $timeout(function() {
									element.removeClass('loading');
									getResultsFn( modelCtrl.$viewValue ).then(displaySuggestions);
								}, silentPeriod, true);
							} else {
								element.removeClass('loading');
							}
						};

						inputElem.bind("focus", function() {
							if (positionHintsFn && scope.hints) {
								$timeout(function() {
									positionHintsFn(hintList, inputElem);
								}, 1, false);
							}
						});

					}
				}
			}
		};
	});

})(angular);<|endoftext|>


<commit_before>$(document).ready(function() {

  module("Utility functions (uniqueId, template)");

  test("utility: noConflict", function() {
    var underscore = _.noConflict();
    ok(underscore.isUndefined(_), "The '_' variable has been returned to its previous state.");
    var intersection = underscore.intersect([-1, 0, 1, 2], [1, 2, 3, 4]);
    equals(intersection.join(', '), '1, 2', 'but the intersection function still works');
    window._ = underscore;
  });

  test("utility: identity", function() {
    var moe = {name : 'moe'};
    equals(_.identity(moe), moe, 'moe is the same as his identity');
  });

  test('utility: breakLoop', function() {
    var result = null;
    _([1,2,3,4,5,6]).each(function(num) {
      result = num;
      if (num == 3) _.breakLoop();
    });
    equals(result, 3, 'broke out of a loop');
  });

  test("utility: uniqueId", function() {
    var ids = [], i = 0;
    while(i++ < 100) ids.push(_.uniqueId());
    equals(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
  });

  test("utility: times", function() {
    var vals = [];
    _.times(3, function (i) { vals.push(i); });
    ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
    //
    vals = [];
    _(3).times(function (i) { vals.push(i); });
    ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
  });

  test("utility: mixin", function() {
    _.mixin({
      myReverse: function(string) {
        return string.split('').reverse().join('');
      }
    });
    equals(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
    equals(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
  });

  test("utility: template", function() {
    var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
    var result = basicTemplate({thing : 'This'});
    equals(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');

    var fancyTemplate = _.template("
<% for (key in people) { %>
<%= people[key] %>
<% } %>
");
    result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
    equals(result, "

Moe

Larry

Curly

", 'can run arbitrary javascript in templates');

    var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
<img src=\"<%= p %>\" />
<% }); %>");
    result = namespaceCollisionTemplate({
      pageCount: 3,
      thumbnails: {
        1: "p1-thumbnail.gif",
        2: "p2-thumbnail.gif",
        3: "p3-thumbnail.gif"
      }
    });
    equals(result, "3 p3-thumbnail.gif

");

    var noInterpolateTemplate = _.template("

Just some text. Hey, I know this is silly but it aids consistency.

");
    result = noInterpolateTemplate();
    equals(result, "

Just some text. Hey, I know this is silly but it aids consistency.

");

    var quoteTemplate = _.template("It's its, not it's");
    equals(quoteTemplate({}), "It's its, not it's");

    var quoteInStatementAndBody = _.template("<% if(foo == 'bar'){ %>Statement quotes and 'quotes'.<% } %>");
    equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");

    var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.');
    equals(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');

    _.templateSettings = {
      start       : '{{',
      end         : '}}',
      interpolate : /\{\{=(.+?)\}\}/g
    };

    var custom = _.template("
{{ for (key in people) { }}
{{= people[key] }}
{{ } }}
");
    result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
    equals(result, "

Moe

Larry

Curly

", 'can run arbitrary javascript in templates');

    var customQuote = _.template("It's its, not it's");
    equals(customQuote({}), "It's its, not it's");

    var quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
    equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");

    _.templateSettings = {
      start       : '<?',
      end         : '?>',
      interpolate : /<\?=(.+?)\?>/g
    };

    var customWithSpecialChars = _.template("
<? for (key in people) { ?>
<?= people[key] ?>
<? } ?>
");
    result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
    equals(result, "

Moe

Larry

Curly

", 'can run arbitrary javascript in templates');

    var customWithSpecialCharsQuote = _.template("It's its, not it's");
    equals(customWithSpecialCharsQuote({}), "It's its, not it's");

    var quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
    equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");

    _.templateSettings = {
      start       : '{{',
      end         : '}}',
      interpolate : /\{\{(.+?)\}\}/g
    };

    var mustache = _.template("Hello {{planet}}!");
    equals(mustache({planet : "World"}), "Hello World!", "can mimic mustache.js");
  });

});
<commit_msg>fixing test that tried to load nonexistent images in a template.<commit_after>$(document).ready(function() {

  module("Utility functions (uniqueId, template)");

  test("utility: noConflict", function() {
    var underscore = _.noConflict();
    ok(underscore.isUndefined(_), "The '_' variable has been returned to its previous state.");
    var intersection = underscore.intersect([-1, 0, 1, 2], [1, 2, 3, 4]);
    equals(intersection.join(', '), '1, 2', 'but the intersection function still works');
    window._ = underscore;
  });

  test("utility: identity", function() {
    var moe = {name : 'moe'};
    equals(_.identity(moe), moe, 'moe is the same as his identity');
  });

  test('utility: breakLoop', function() {
    var result = null;
    _([1,2,3,4,5,6]).each(function(num) {
      result = num;
      if (num == 3) _.breakLoop();
    });
    equals(result, 3, 'broke out of a loop');
  });

  test("utility: uniqueId", function() {
    var ids = [], i = 0;
    while(i++ < 100) ids.push(_.uniqueId());
    equals(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
  });

  test("utility: times", function() {
    var vals = [];
    _.times(3, function (i) { vals.push(i); });
    ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
    //
    vals = [];
    _(3).times(function (i) { vals.push(i); });
    ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
  });

  test("utility: mixin", function() {
    _.mixin({
      myReverse: function(string) {
        return string.split('').reverse().join('');
      }
    });
    equals(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
    equals(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
  });

  test("utility: template", function() {
    var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
    var result = basicTemplate({thing : 'This'});
    equals(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');

    var fancyTemplate = _.template("
<% for (key in people) { %>
<%= people[key] %>
<% } %>
");
    result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
    equals(result, "

Moe

Larry

Curly

", 'can run arbitrary javascript in templates');

    var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class=\"thumbnail\" rel=\"<%= p %>\">
<% }); %>");
    result = namespaceCollisionTemplate({
      pageCount: 3,
      thumbnails: {
        1: "p1-thumbnail.gif",
        2: "p2-thumbnail.gif",
        3: "p3-thumbnail.gif"
      }
    });
    equals(result, "3 p3-thumbnail.gif

");

    var noInterpolateTemplate = _.template("

Just some text. Hey, I know this is silly but it aids consistency.

");
    result = noInterpolateTemplate();
    equals(result, "

Just some text. Hey, I know this is silly but it aids consistency.

");

    var quoteTemplate = _.template("It's its, not it's");
    equals(quoteTemplate({}), "It's its, not it's");

    var quoteInStatementAndBody = _.template("<% if(foo == 'bar'){ %>Statement quotes and 'quotes'.<% } %>");
    equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");

    var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.');
    equals(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');

    _.templateSettings = {
      start       : '{{',
      end         : '}}',
      interpolate : /\{\{=(.+?)\}\}/g
    };

    var custom = _.template("
{{ for (key in people) { }}
{{= people[key] }}
{{ } }}
");
    result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
    equals(result, "

Moe

Larry

Curly

", 'can run arbitrary javascript in templates');

    var customQuote = _.template("It's its, not it's");
    equals(customQuote({}), "It's its, not it's");

    var quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
    equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");

    _.templateSettings = {
      start       : '<?',
      end         : '?>',
      interpolate : /<\?=(.+?)\?>/g
    };

    var customWithSpecialChars = _.template("
<? for (key in people) { ?>
<?= people[key] ?>
<? } ?>
");
    result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
    equals(result, "

Moe

Larry

Curly

", 'can run arbitrary javascript in templates');

    var customWithSpecialCharsQuote = _.template("It's its, not it's");
    equals(customWithSpecialCharsQuote({}), "It's its, not it's");

    var quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
    equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");

    _.templateSettings = {
      start       : '{{',
      end         : '}}',
      interpolate : /\{\{(.+?)\}\}/g
    };

    var mustache = _.template("Hello {{planet}}!");
    equals(mustache({planet : "World"}), "Hello World!", "can mimic mustache.js");
  });

});
<|endoftext|>


<commit_before>var fs = require('fs');
var config = JSON.parse(fs.readFileSync('config.json', 'utf8'));

var vds, positions, events = [];

var usingCache = true;

// VDS einlesen
var vdsJSON = config.cachePath + 'vds.json';
if (usingCache && fs.existsSync(vdsJSON)) {
	console.log('Load VDS from cache');
	vds = JSON.parse(fs.readFileSync(vdsJSON, 'utf8'));
} else {
	console.log('Import VDS');
	vds = require('vds').import(config.inputPath + 'vds/vds.tsv', config);
	fs.writeFileSync(vdsJSON, JSON.stringify(vds, null, '\t'), 'utf8');
}

var cells = JSON.parse(fs.readFileSync(config.inputPath + 'cells.json', 'utf8'));
cells.forEach(function (cell, index) { cell.index = index })

// Positionen ausrechnen
var positionJSON = config.cachePath + 'position.json';
if (usingCache && fs.existsSync(positionJSON)) {
	console.log('Load Position from cache');
	positions = JSON.parse(fs.readFileSync(positionJSON, 'utf8'));
} else {
	console.log('Calculate Position');
	positions = require('position').import(cells, vds, config);
	//fs.writeFileSync(positionJSON, JSON.stringify(positions, null, '\t'), 'utf8');
}

var telephoneEvents = vds.map(function (entry) {
	if (entry.type == 'internet') return false;
	return {
		type: entry.type,
		subtype: entry.subtype,
		timeDuration: entry.timeDuration,
		timeStart: entry.timeStart,
		timeEnd: entry.timeEnd,
		incoming: entry.data.incoming
	}
}).filter(function (entry) { return entry });
events = events.concat(telephoneEvents);

var data = {};

data.cells = [];
cells.forEach(function (cell) {
	data.cells[cell.index] = {
		x0: cell.x0,
		y0: cell.y0,
		x: cell.x,
		y: cell.y,
		acc: cell.acc,
		index: cell.index
	};
})

data.activities = positions.activities.map(function (activity) {
	return {
		index: activity.index,
		time: activity.time,
		cells: activity.cells.map(function (cell) { return cell.index })
	}
})

data.timeStart = config.timeStart;

data.events = events;

fs.writeFileSync('../vds-vis/data/data.js', 'var data = ' + JSON.stringify(data, null, '\t'), 'utf8')

<commit_msg>rename properties<commit_after>var fs = require('fs');
var config = JSON.parse(fs.readFileSync('config.json', 'utf8'));

var vds, positions, events = [];

var usingCache = true;

// VDS einlesen
var vdsJSON = config.cachePath + 'vds.json';
if (usingCache && fs.existsSync(vdsJSON)) {
	console.log('Load VDS from cache');
	vds = JSON.parse(fs.readFileSync(vdsJSON, 'utf8'));
} else {
	console.log('Import VDS');
	vds = require('vds').import(config.inputPath + 'vds/vds.tsv', config);
	fs.writeFileSync(vdsJSON, JSON.stringify(vds, null, '\t'), 'utf8');
}

var cells = JSON.parse(fs.readFileSync(config.inputPath + 'cells.json', 'utf8'));
cells.forEach(function (cell, index) { cell.index = index })

// Positionen ausrechnen
var positionJSON = config.cachePath + 'position.json';
if (usingCache && fs.existsSync(positionJSON)) {
	console.log('Load Position from cache');
	positions = JSON.parse(fs.readFileSync(positionJSON, 'utf8'));
} else {
	console.log('Calculate Position');
	positions = require('position').import(cells, vds, config);
	//fs.writeFileSync(positionJSON, JSON.stringify(positions, null, '\t'), 'utf8');
}

var telephoneEvents = vds.map(function (entry) {
	if (entry.type == 'internet') return false;
	return {
		type: entry.type,
		subtype: entry.subtype,
		dur: entry.timeDuration,
		start: entry.timeStart,
		end: entry.timeEnd,
		incoming: entry.data.incoming
	}
}).filter(function (entry) { return entry });
events = events.concat(telephoneEvents);

var data = {};

data.cells = [];
cells.forEach(function (cell) {
	data.cells[cell.index] = {
		x0: cell.x0,
		y0: cell.y0,
		x: cell.x,
		y: cell.y,
		acc: cell.acc,
		index: cell.index
	};
})

data.activities = positions.activities.map(function (activity) {
	return {
		index: activity.index,
		time: activity.time,
		cells: activity.cells.map(function (cell) { return cell.index })
	}
})

data.timeStart = config.timeStart;

data.events = events;

fs.writeFileSync('../vds-vis/data/data.js', 'var data = ' + JSON.stringify(data, null, '\t'), 'utf8')

<|endoftext|>


<commit_before>import React, {Component} from 'react';
import {fetch, post, remove} from '../../helpers/dbcalls';
import SimpleState from 'react-simple-state';
import Cards from '../../components/Cards/Cards';
import {base} from '../../config/constants';
import Votelist from '../../components/Votelist/Votelist';
import Styles from './Gameadmin.css.js';
import RaisedButton from 'material-ui/RaisedButton';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import Gavel from 'material-ui/svg-icons/action/gavel';
import Viewlist from 'material-ui/svg-icons/action/view-list';
import Deleteandroutebutton from '../../components/Deleteandroutebutton/Deleteandroutebutton';
const simpleState = new SimpleState();

export default class Gameadmin extends Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [],
      gameCode: null,
      voting: false,
      votes: []
    };
    this.componentDidMount = this.componentDidMount.bind(this);
  }

  clearVote = () => {
    const gameId = sessionStorage.lobbyNumber;
    let removeVoting = new Promise((resolve, reject) => {
      const collection = 'activegame/' + gameId + "/voting/";
      remove(resolve, reject, collection);
    })
    removeVoting.then((data) => {
      console.log(data);
      this.initVote();
    })

  }

  initVote = () => {
    this.setState({voting: true})
    const data = this.state.list
    console.log(data)
    let votingData = []
    for(let i = 0; i < data.length; i++){
      votingData[data[i].userKey] = {
        displayName: data[i].displayName,
        votes: 0
      }
    }
    console.log(votingData);
    const gameId = sessionStorage.lobbyNumber;
    let postVotingData = new Promise((resolve, reject) => {
      const collection = 'activegame/' + gameId + "/voting/data"
      post(resolve, reject, votingData, collection);
    })
    postVotingData.then((data) => {
      base.listenTo('activegame/' + gameId + "/voting/votes", {
        context: this,
        asArray: true,
        then(votesData){
          let getVoteData = new Promise((resolve, reject) => {
            const collection = 'activegame/' + gameId + "/voting/data/";
            fetch(resolve, reject, collection,{}, false);
          })
          getVoteData.then((voteData) =>{
            for(let i = 0; i < votesData.length; i++){
              const key = votesData[i].votedForKey;
              if(voteData[key].votedFor){
                voteData[key].votedFor = voteData[key].votedFor + ", " + votesData[i].displayName;
              }else{
                voteData[key].votedFor = votesData[i].displayName;
              }
              voteData[key].votes += 1;
            }
            const objectArr = Object.values(voteData)
            this.setState({votes: objectArr});
          })
        }
      })
    })
  }

  initList = () => {
    this.setState({voting: false})
  }

  componentDidMount(){
    if(simpleState.getState("gameId").id === "" && sessionStorage.lobbyNumber === undefined){
      this.props.history.push("main")
    }else{
      let gameId = "";
      if(simpleState.getState("gameId").id !== ""){
        gameId = simpleState.getState("gameId").id;
        sessionStorage.lobbyNumber = gameId
      }else if(sessionStorage.lobbyNumber !== undefined){
        gameId = sessionStorage.lobbyNumber
      }
      let getGameCode = new Promise((resolve, reject) => {
        const collection = 'activegame/' + gameId + "/code/"
        const arrayBoolean = false;
        fetch(resolve, reject, collection, {}, arrayBoolean);
      })
      getGameCode.then((data) => {
        this.setState({gameCode: data})
      })

      let getActiveCards = new Promise((resolve, reject) => {
        const collection = 'activegame/' + gameId + "/memberarray/"
        fetch(resolve, reject, collection);
      })
      getActiveCards.then((data) => {
        const activeData = data;
        let getCardInfos = new Promise((resolve, reject) => {
          const collection = 'cards/'
          fetch(resolve, reject, collection);
        })
        getCardInfos.then((data) => {

          for(var i = 0; i < activeData.length; i++){
            const cardId = activeData[i].card;
            const index = data.findIndex(i => i.key === cardId);
            activeData[i].userKey = activeData[i].key;
            activeData[i].key = data[index].key;
            activeData[i].pictureback = data[index].pictureback;
            activeData[i].picturefront = data[index].picturefront;
            activeData[i].description = data[index].description;
            activeData[i].name = data[index].name;
            activeData[i].cardHeader = activeData[i].displayName + ": "+data[index].name;
          }
          this.setState({list: activeData})
          console.log(activeData)
          simpleState.evoke("loader", false)
        })
      })
    }
  }
  render() {
    return (

Lobbynumber: {this.state.gameCode}

        {this.state.voting === false ?

Cards in game:

          <Cards counter={false} data={this.state.list}/>

          <Deleteandroutebutton
              route={"/main"}
              labelText={"Game finished"}
              dbReference={'activegame/' + sessionStorage.lobbyNumber}
              primary={true}/>

        <FloatingActionButton style={Styles.fab}
          onTouchTap={this.initVote}>
          <Gavel />
        </FloatingActionButton>

        :

          <Votelist
          disabled={true}
          voteData={this.state.votes}
          />
          <RaisedButton
              primary={true}
              label={"Clear vote"}
              onClick={
              this.clearVote}/>
          <FloatingActionButton style={Styles.fab}
          onTouchTap={this.initList}>
          <Viewlist />
          </FloatingActionButton>

        }

    )
  }
}<commit_msg>loader and removed c.l<commit_after>import React, {Component} from 'react';
import {fetch, post, remove} from '../../helpers/dbcalls';
import SimpleState from 'react-simple-state';
import Cards from '../../components/Cards/Cards';
import {base} from '../../config/constants';
import Votelist from '../../components/Votelist/Votelist';
import Styles from './Gameadmin.css.js';
import RaisedButton from 'material-ui/RaisedButton';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import Gavel from 'material-ui/svg-icons/action/gavel';
import Viewlist from 'material-ui/svg-icons/action/view-list';
import Deleteandroutebutton from '../../components/Deleteandroutebutton/Deleteandroutebutton';
const simpleState = new SimpleState();

export default class Gameadmin extends Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [],
      gameCode: null,
      voting: false,
      votes: []
    };
    this.componentDidMount = this.componentDidMount.bind(this);
  }

  clearVote = () => {
    simpleState.evoke("loader", true)
    const gameId = sessionStorage.lobbyNumber;
    let removeVoting = new Promise((resolve, reject) => {
      const collection = 'activegame/' + gameId + "/voting/";
      remove(resolve, reject, collection);
    })
    removeVoting.then((data) => {
      this.initVote();
    })

  }

  initVote = () => {
    simpleState.evoke("loader", true)
    this.setState({voting: true})
    const data = this.state.list
    let votingData = []
    for(let i = 0; i < data.length; i++){
      votingData[data[i].userKey] = {
        displayName: data[i].displayName,
        votes: 0
      }
    }
    const gameId = sessionStorage.lobbyNumber;
    let postVotingData = new Promise((resolve, reject) => {
      const collection = 'activegame/' + gameId + "/voting/data"
      post(resolve, reject, votingData, collection);
    })
    postVotingData.then((data) => {
      base.listenTo('activegame/' + gameId + "/voting/votes", {
        context: this,
        asArray: true,
        then(votesData){
          let getVoteData = new Promise((resolve, reject) => {
            const collection = 'activegame/' + gameId + "/voting/data/";
            fetch(resolve, reject, collection,{}, false);
          })
          getVoteData.then((voteData) =>{
            for(let i = 0; i < votesData.length; i++){
              const key = votesData[i].votedForKey;
              if(voteData[key].votedFor){
                voteData[key].votedFor = voteData[key].votedFor + ", " + votesData[i].displayName;
              }else{
                voteData[key].votedFor = votesData[i].displayName;
              }
              voteData[key].votes += 1;
            }
            const objectArr = Object.values(voteData)
            this.setState({votes: objectArr});
            simpleState.evoke("loader", false)
          })
        }
      })
    })
  }

  initList = () => {
    simpleState.evoke("loader", true)
    this.setState({voting: false})
  }

  componentDidMount(){
    if(simpleState.getState("gameId").id === "" && sessionStorage.lobbyNumber === undefined){
      this.props.history.push("main")
    }else{
      let gameId = "";
      if(simpleState.getState("gameId").id !== ""){
        gameId = simpleState.getState("gameId").id;
        sessionStorage.lobbyNumber = gameId
      }else if(sessionStorage.lobbyNumber !== undefined){
        gameId = sessionStorage.lobbyNumber
      }
      let getGameCode = new Promise((resolve, reject) => {
        const collection = 'activegame/' + gameId + "/code/"
        const arrayBoolean = false;
        fetch(resolve, reject, collection, {}, arrayBoolean);
      })
      getGameCode.then((data) => {
        this.setState({gameCode: data})
      })

      let getActiveCards = new Promise((resolve, reject) => {
        const collection = 'activegame/' + gameId + "/memberarray/"
        fetch(resolve, reject, collection);
      })
      getActiveCards.then((data) => {
        const activeData = data;
        let getCardInfos = new Promise((resolve, reject) => {
          const collection = 'cards/'
          fetch(resolve, reject, collection);
        })
        getCardInfos.then((data) => {

          for(var i = 0; i < activeData.length; i++){
            const cardId = activeData[i].card;
            const index = data.findIndex(i => i.key === cardId);
            activeData[i].userKey = activeData[i].key;
            activeData[i].key = data[index].key;
            activeData[i].pictureback = data[index].pictureback;
            activeData[i].picturefront = data[index].picturefront;
            activeData[i].description = data[index].description;
            activeData[i].name = data[index].name;
            activeData[i].cardHeader = activeData[i].displayName + ": "+data[index].name;
          }
          this.setState({list: activeData})
          simpleState.evoke("loader", false)
        })
      })
    }
  }
  render() {
    return (

Lobbynumber: {this.state.gameCode}

        {this.state.voting === false ?

Cards in game:

          <Cards counter={false} data={this.state.list}/>

          <Deleteandroutebutton
              route={"/main"}
              labelText={"Game finished"}
              dbReference={'activegame/' + sessionStorage.lobbyNumber}
              primary={true}/>

        <FloatingActionButton style={Styles.fab}
          onTouchTap={this.initVote}>
          <Gavel />
        </FloatingActionButton>

        :

          <Votelist
          disabled={true}
          voteData={this.state.votes}
          />
          <RaisedButton
              style={Styles.centeredOnlyHorizontal}
              primary={true}
              label={"Clear vote"}
              onClick={
              this.clearVote}/>
          <FloatingActionButton style={Styles.fab}
          onTouchTap={this.initList}>
          <Viewlist />
          </FloatingActionButton>

        }

    )
  }
}<|endoftext|>


<commit_before>!function t(e,n,o){function r(s,c){if(!n[s]){if(!e[s]){var a="function"==typeof require&&require;if(!c&&a)return a(s,!0);if(i)return i(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[s]={exports:{}};e[s][0].call(u.exports,function(t){var n=e[s][1][t];return r(n?n:t)},u,u.exports,t,e,n,o)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s<o.length;s++)r(o[s]);return r}({1:[function(t,e,n){"use strict";function o(t){return"undefined"==typeof t}function r(t,e){for(var n=0,o=e.split("."),r=o.length;r>n;n++){if(!t||"object"!=typeof t)return!1;t=t[o[n]]}return"undefined"==typeof t?!1:t}var i=t("./socket"),s=t("./emitter"),c=(t("./notify"),t("./tab"),t("./browser.utils")),a=function(t){this.options=t,this.socket=i,this.emitter=s,this.utils=c,this.tabHidden=!1;var e=this;i.on("options:set",function(t){s.emit("notify","Setting options..."),e.options=t.options}),s.on("tab:hidden",function(){e.tabHidden=!0}),s.on("tab:visible",function(){e.tabHidden=!1})};a.prototype.canSync=function(t,e){if(t=t||{},t.override)return!0;var n=!0;return e&&(n=this.getOption(e)),n&&t.url===window.location.pathname},a.prototype.getOption=function(t){if(t&&t.match(/\./))return r(this.options,t);var e=this.options[t];return o(e)?!1:e},e.exports=a},{"./browser.utils":2,"./emitter":5,"./notify":16,"./socket":17,"./tab":18}],2:[function(t,e,n){"use strict";var o=n;o.getWindow=function(){return window},o.getDocument=function(){return document},o.getBody=function(){return document.getElementsByTagName("body")[0]},o.getBrowserScrollPosition=function(){var t,e,o=n.getWindow(),r=n.getDocument(),i=r.documentElement,s=r.body;return void 0!==o.pageYOffset?(t=o.pageXOffset,e=o.pageYOffset):(t=i.scrollLeft||s.scrollLeft||0,e=i.scrollTop||s.scrollTop||0),{x:t,y:e}},o.getScrollSpace=function(){var t=n.getDocument(),e=t.documentElement,o=t.body;return{x:o.scrollHeight-e.clientWidth,y:o.scrollHeight-e.clientHeight}},o.saveScrollPosition=function(){var t=o.getBrowserScrollPosition();t=[t.x,t.y],o.getDocument.cookie="bs_scroll_pos="+t.join(",")},o.restoreScrollPosition=function(){var t=o.getDocument().cookie.replace(/(?:(?:^|.*;\s*)bs_scroll_pos\s*\=\s*([^;]*).*$)|^.*$/,"$1").split(",");o.getWindow().scrollTo(t[0],t[1])},o.getElementIndex=function(t,e){var n=o.getDocument().getElementsByTagName(t);return Array.prototype.indexOf.call(n,e)},o.forceChange=function(t){t.blur(),t.focus()},o.getElementData=function(t){var e=t.tagName,n=o.getElementIndex(e,t);return{tagName:e,index:n}},o.getSingleElement=function(t,e){var n=o.getDocument().getElementsByTagName(t);return n[e]},o.getBody=function(){return o.getDocument().getElementsByTagName("body")[0]},o.setScroll=function(t){o.getWindow().scrollTo(t.x,t.y)},o.reloadBrowser=function(){o.getWindow().location.reload(!0)},o.forEach=function(t,e){for(var n=0,o=t.length;o>n;n+=1)e(t[n],n,t)},o.isOldIe=function(){return"undefined"!=typeof o.getWindow().attachEvent},o.getLocation=function(t){var e=o.getDocument().createElement("a");return e.href=t,""===e.host&&(e.href=e.href),e}},{}],3:[function(t,e,n){"indexOf"in Array.prototype||(Array.prototype.indexOf=function(t,e){void 0===e&&(e=0),0>e&&(e+=this.length),0>e&&(e=0);for(var n=this.length;n>e;e+=1)if(e in this&&this[e]===t)return e;return-1}),Array.prototype.map||(Array.prototype.map=function(t,e){var n,o,r;if(null==this)throw new TypeError(" this is null or not defined");var i=Object(this),s=i.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(arguments.length>1&&(n=e),o=new Array(s),r=0;s>r;){var c,a;r in i&&(c=i[r],a=t.call(n,c,r,i),o[r]=a),r++}return o}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(void 0===this||null===this)throw new TypeError;var e=Object(this),n=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var o=[],r=arguments.length>=2?arguments[1]:void 0,i=0;n>i;i++)if(i in e){var s=e[i];t.call(r,s,i,e)&&o.push(s)}return o})},{}],4:[function(t,e,n){"use strict";var o,r=t("./events"),i=t("./browser.utils"),s=t("./emitter"),c=n,a={tagNames:{css:"link",jpg:"img",jpeg:"img",png:"img",svg:"img",gif:"img",js:"script"},attrs:{link:"href",img:"src",script:"src"}},l="codeSync",u=function(){return window.location.pathname};c.init=function(t){t.options.tagNames&&(a.tagNames=t.options.tagNames),"window.name"===t.options.scrollRestoreTechnique?c.saveScrollInName(s):c.saveScrollInCookie(i.getWindow(),i.getDocument()),t.socket.on("file:reload",c.reload(t)),t.socket.on("browser:reload",function(){t.canSync({url:u()},l)&&c.reloadBrowser(!0,t)})},c.saveScrollInName=function(){var t="<<BS_START>>",e="<<BS_END>>",n=new RegExp(t+"(.+?)"+e),o=i.getWindow(),r={};s.on("browser:hardReload",function(n){var r=[o.name,t,JSON.stringify({bs:{hardReload:!0,scroll:n.scrollPosition}}),e].join("");o.name=r});try{var c=o.name.match(n);c&&(r=JSON.parse(c[1]))}catch(a){r={}}r.bs&&r.bs.hardReload&&r.bs.scroll&&i.setScroll(r.bs.scroll),o.name=o.name.replace(n,"")},c.saveScrollInCookie=function(t,e){i.isOldIe()&&("complete"===e.readyState?i.restoreScrollPosition():r.manager.addEvent(e,"readystatechange",function(){"complete"===e.readyState&&i.restoreScrollPosition()}),s.on("browser:hardReload",i.saveScrollPosition))},c.updateSearch=function(t,e,n){return""===t?"?"+n:"?"+t.slice(1).split("&").map(function(t){return t.split("=")}).filter(function(t){return t[0]!==e}).map(function(t){return[t[0],t[1]].join("=")}).concat(n).join("&")},c.swapFile=function(t,e,n){var r=t[e],s=(new Date).getTime(),a="rel",l=a+"="+s,u=i.getLocation(r),f=c.updateSearch(u.search,a,l);n.timestamps===!1?t[e]=u.href:t[e]=u.href.split("?")[0]+f;var d=document.body;return setTimeout(function(){o?(o.style.display="none",o.style.display="block"):(o=document.createElement("DIV"),d.appendChild(o))},200),{elem:t,timeStamp:s}},c.getFilenameOnly=function(t){return/^[^\?]+(?=\?)/.exec(t)},c.reload=function(t){return function(e){if(t.canSync({url:u()},l)){var n,o=t.options,r=t.emitter;if((e.url||!o.injectChanges)&&c.reloadBrowser(!0),e.basename&&e.ext){var i=c.getElems(e.ext),s=c.getMatches(i.elems,e.basename,i.attr);s.length&&o.notify&&r.emit("notify",{message:"Injected: "+e.basename});for(var a=0,f=s.length;f>a;a+=1)n=c.swapFile(s[a],i.attr,o)}return n}}},c.getTagName=function(t){return a.tagNames[t]},c.getAttr=function(t){return a.attrs[t]},c.getMatches=function(t,e,n){if("*"===e[0])return t;for(var o=[],r=new RegExp("(^|/)"+e),i=0,s=t.length;s>i;i+=1)r.test(t[i][n])&&o.push(t[i]);return o},c.getElems=function(t){var e=c.getTagName(t),n=c.getAttr(e);return{elems:document.getElementsByTagName(e),attr:n}},c.reloadBrowser=function(t){s.emit("browser:hardReload",{scrollPosition:i.getBrowserScrollPosition()}),t&&i.reloadBrowser()}},{"./browser.utils":2,"./emitter":5,"./events":6}],5:[function(t,e,n){"use strict";n.events={},n.emit=function(t,e){var o,r=n.events[t];if(r&&r.listeners){o=r.listeners;for(var i=0,s=o.length;s>i;i+=1)o[i](e)}},n.on=function(t,e){var o=n.events;o[t]?o[t].listeners.push(e):o[t]={listeners:[e]}}},{}],6:[function(t,e,n){n._ElementCache=function(){var t={},e=1,n="data"+(new Date).getTime();this.getData=function(o){var r=o[n];return r||(r=o[n]=e++,t[r]={}),t[r]},this.removeData=function(e){var o=e[n];if(o){delete t[o];try{delete e[n]}catch(r){e.removeAttribute&&e.removeAttribute(n)}}}},n._fixEvent=function(t){function e(){return!0}function n(){return!1}if(!t||!t.stopPropagation){var o=t||window.event;t={};for(var r in o)t[r]=o[r];if(t.target||(t.target=t.srcElement||document),t.relatedTarget=t.fromElement===t.target?t.toElement:t.fromElement,t.preventDefault=function(){t.returnValue=!1,t.isDefaultPrevented=e},t.isDefaultPrevented=n,t.stopPropagation=function(){t.cancelBubble=!0,t.isPropagationStopped=e},t.isPropagationStopped=n,t.stopImmediatePropagation=function(){this.isImmediatePropagationStopped=e,this.stopPropagation()},t.isImmediatePropagationStopped=n,null!=t.clientX){var i=document.documentElement,s=document.body;t.pageX=t.clientX+(i&&i.scrollLeft||s&&s.scrollLeft||0)-(i&&i.clientLeft||s&&s.clientLeft||0),t.pageY=t.clientY+(i&&i.scrollTop||s&&s.scrollTop||0)-(i&&i.clientTop||s&&s.clientTop||0)}t.which=t.charCode||t.keyCode,null!=t.button&&(t.button=1&t.button?0:4&t.button?1:2&t.button?2:0)}return t},n._EventManager=function(t){function e(e,n){function o(t){for(var e in t)return!1;return!0}var r=t.getData(e);0===r.handlers[n].length&&(delete r.handlers[n],document.removeEventListener?e.removeEventListener(n,r.dispatcher,!1):document.detachEvent&&e.detachEvent("on"+n,r.dispatcher)),o(r.handlers)&&(delete r.handlers,delete r.dispatcher),o(r)&&t.removeData(e)}var o=1;this.addEvent=function(e,r,i){var s=t.getData(e);s.handlers||(s.handlers={}),s.handlers[r]||(s.handlers[r]=[]),i.guid||(i.guid=o++),s.handlers[r].push(i),s.dispatcher||(s.disabled=!1,s.dispatcher=function(t){if(!s.disabled){t=n._fixEvent(t);var o=s.handlers[t.type];if(o)for(var r=0;r<o.length;r++)o[r].call(e,t)}}),1==s.handlers[r].length&&(document.addEventListener?e.addEventListener(r,s.dispatcher,!1):document.attachEvent&&e.attachEvent("on"+r,s.dispatcher))},this.removeEvent=function(n,o,r){var i=t.getData(n);if(i.handlers){var s=function(t){i.handlers[t]=[],e(n,t)};if(o){var c=i.handlers[o];if(c){if(!r)return void s(o);if(r.guid)for(var a=0;a<c.length;a++)c[a].guid===r.guid&&c.splice(a--,1);e(n,o)}}else for(var l in i.handlers)s(l)}},this.proxy=function(t,e){e.guid||(e.guid=o++);var n=function(){return e.apply(t,arguments)};return n.guid=e.guid,n}},n.triggerClick=function(t){var e;document.createEvent?window.setTimeout(function(){e=document.createEvent("MouseEvents"),e.initEvent("click",!0,!0),t.dispatchEvent(e)},0):window.setTimeout(function(){document.createEventObject&&(e=document.createEventObject(),e.cancelBubble=!0,t.fireEvent("onclick",e))},0)};var o=new n._ElementCache,r=new n._EventManager(o);r.triggerClick=n.triggerClick,n.manager=r},{}],7:[function(t,e,n){"use strict";var o="click",r="ghostMode.clicks";n.canEmitEvents=!0,n.init=function(t,e){e.addEvent(document.body,o,n.browserEvent(t)),t.socket.on(o,n.socketEvent(t,e))},n.browserEvent=function(t){return function(e){if(n.canEmitEvents){var r=e.target||e.srcElement;if("checkbox"===r.type||"radio"===r.type)return void t.utils.forceChange(r);t.socket.emit(o,t.utils.getElementData(r))}else n.canEmitEvents=!0}},n.socketEvent=function(t,e){return function(o){if(!t.canSync(o,r)||t.tabHidden)return!1;var i=t.utils.getSingleElement(o.tagName,o.index);i&&(n.canEmitEvents=!1,e.triggerClick(i))}}},{}],8:[function(t,e,n){"use strict";var o="input:text",r="ghostMode.forms.inputs";n.canEmitEvents=!0,n.init=function(t,e){e.addEvent(document.body,"keyup",n.browserEvent(t)),t.socket.on(o,n.socketEvent(t,e))},n.browserEvent=function(t){return function(e){var r,i=e.target||e.srcElement;n.canEmitEvents?("INPUT"===i.tagName||"TEXTAREA"===i.tagName)&&(r=t.utils.getElementData(i),r.value=i.value,t.socket.emit(o,r)):n.canEmitEvents=!0}},n.socketEvent=function(t){return function(e){if(!t.canSync(e,r))return!1;var n=t.utils.getSingleElement(e.tagName,e.index);return n?(n.value=e.value,n):!1}}},{}],9:[function(t,e,n){"use strict";n.plugins={inputs:t("./ghostmode.forms.input"),toggles:t("./ghostmode.forms.toggles"),submit:t("./ghostmode.forms.submit")},n.init=function(t,e){function o(o){n.plugins[o].init(t,e)}var r=!0,i=t.options.ghostMode.forms;i===!0&&(r=!1);for(var s in n.plugins)r?i[s]&&o(s):o(s)}},{"./ghostmode.forms.input":8,"./ghostmode.forms.submit":10,"./ghostmode.forms.toggles":11}],10:[function(t,e,n){"use strict";var o="form:submit",r="ghostMode.forms.submit";n.canEmitEvents=!0,n.init=function(t,e){var r=n.browserEvent(t);e.addEvent(document.body,"submit",r),e.addEvent(document.body,"reset",r),t.socket.on(o,n.socketEvent(t,e))},n.browserEvent=function(t){return function(e){if(n.canEmitEvents){var r=e.target||e.srcElement,i=t.utils.getElementData(r);i.type=e.type,t.socket.emit(o,i)}else n.canEmitEvents=!0}},n.socketEvent=function(t){return function(e){if(!t.canSync(e,r))return!1;var o=t.utils.getSingleElement(e.tagName,e.index);return n.canEmitEvents=!1,o&&"submit"===e.type&&o.submit(),o&&"reset"===e.type&&o.reset(),!1}}},{}],11:[function(t,e,n){"use strict";var o="input:toggles",r="ghostMode.forms.toggles";n.canEmitEvents=!0,n.init=function(t,e){var r=n.browserEvent(t);n.addEvents(e,r),t.socket.on(o,n.socketEvent(t,e))},n.addEvents=function(t,e){function n(n){for(var o=0,r=n.length;r>o;o+=1)t.addEvent(n[o],"change",e)}var o=document.getElementsByTagName("select"),r=document.getElementsByTagName("input");n(o),n(r)},n.browserEvent=function(t){return function(e){if(n.canEmitEvents){var r,i=e.target||e.srcElement;("radio"===i.type||"checkbox"===i.type||"SELECT"===i.tagName)&&(r=t.utils.getElementData(i),r.type=i.type,r.value=i.value,r.checked=i.checked,t.socket.emit(o,r))}else n.canEmitEvents=!0}},n.socketEvent=function(t){return function(e){if(!t.canSync(e,r))return!1;n.canEmitEvents=!1;var o=t.utils.getSingleElement(e.tagName,e.index);return o?("radio"===e.type&&(o.checked=!0),"checkbox"===e.type&&(o.checked=e.checked),"SELECT"===e.tagName&&(o.value=e.value),o):!1}}},{}],12:[function(t,e,n){"use strict";var o=t("./events").manager;n.plugins={scroll:t("./ghostmode.scroll"),clicks:t("./ghostmode.clicks"),forms:t("./ghostmode.forms"),location:t("./ghostmode.location")},n.init=function(t){for(var e in n.plugins)t.options.ghostMode[e]&&n.plugins[e].init(t,o)}},{"./events":6,"./ghostmode.clicks":7,"./ghostmode.forms":9,"./ghostmode.location":13,"./ghostmode.scroll":14}],13:[function(t,e,n){"use strict";var o="browser:location",r="ghostMode.location";n.canEmitEvents=!0,n.init=function(t){t.socket.on(o,n.socketEvent(t))},n.socketEvent=function(t){return function(e){return t.canSync(e,r)?void(e.path?n.setPath(e.path):n.setUrl(e.url)):!1}},n.setUrl=function(t){window.location=t},n.setPath=function(t){window.location=window.location.protocol+"//"+window.location.host+t}},{}],14:[function(t,e,n){"use strict";var o,r="scroll",i="scroll:element",s="ghostMode.scroll";n.canEmitEvents=!0,n.init=function(t,e){function s(i,s){c[i]&&c[i].length&&"querySelectorAll"in document&&o.forEach(c[i],function(i){var c=document.querySelectorAll(i)||[];o.forEach(c,function(i){var c=o.getElementData(i);c.cacheSelector=c.tagName+":"+c.index,c.map=s,a[c.cacheSelector]=i,e.addEvent(i,r,n.browserEventForElement(t,i,c))})})}o=t.utils;var c=t.options;e.addEvent(window,r,n.browserEvent(t)),t.socket.on(r,n.socketEvent(t));var a={};s("scrollElements",!1),s("scrollElementMapping",!0),t.socket.on(i,n.socketEventForElement(t,a))},n.socketEvent=function(t){return function(e){if(!t.canSync(e,s))return!1;var r=o.getScrollSpace();return n.canEmitEvents=!1,t.options&&t.options.scrollProportionally?window.scrollTo(0,r.y*e.position.proportional):window.scrollTo(0,e.position.raw.y)}},n.socketEventForElement=function(t,e){return function(o){function r(t,n){e[t]&&(e[t].scrollTop=n)}return t.canSync(o,s)?(n.canEmitEvents=!1,o.map?Object.keys(e).forEach(function(t){r(t,o.position)}):void r(o.elem.cacheSelector,o.position)):!1}},n.browserEventForElement=function(t,e,o){return function(){var r=n.canEmitEvents;r&&t.socket.emit(i,{position:e.scrollTop,elem:o,map:o.map}),n.canEmitEvents=!0}},n.browserEvent=function(t){return function(){var e=n.canEmitEvents;e&&t.socket.emit(r,{position:n.getScrollPosition()}),n.canEmitEvents=!0}},n.getScrollPosition=function(){var t=o.getBrowserScrollPosition();return{raw:t,proportional:n.getScrollTopPercentage(t)}},n.getScrollPercentage=function(t,e){var n=e.x/t.x,o=e.y/t.y;return{x:n||0,y:o}},n.getScrollTopPercentage=function(t){var e=o.getScrollSpace(),r=n.getScrollPercentage(e,t);return r.y}},{}],15:[function(t,e,n){"use strict";var o=t("./socket"),r=(t("./client-shims"),t("./notify")),i=t("./code-sync"),s=t("./browser-sync"),c=t("./ghostmode"),a=(t("./emitter"),t("./events"),t("./browser.utils")),l=!1,u=!1;n.init=function(t){l&&t.reloadOnRestart&&a.reloadBrowser();var e=window.___browserSync___||{};if(!e.client){e.client=!0;var n=new s(t);c.init(n),i.init(n),r.init(n),t.notify&&r.flash("Connected to BrowserSync")}u||(o.on("disconnect",function(){t.notify&&r.flash("Disconnected from BrowserSync"),l=!0}),u=!0)},o.on("connection",n.init)},{"./browser-sync":1,"./browser.utils":2,"./client-shims":3,"./code-sync":4,"./emitter":5,"./events":6,"./ghostmode":12,"./ghostmode.clicks":7,"./ghostmode.forms":9,"./ghostmode.forms.input":8,"./ghostmode.forms.submit":10,"./ghostmode.forms.toggles":11,"./ghostmode.location":13,"./ghostmode.scroll":14,"./notify":16,"./socket":17}],16:[function(t,e,n){"use strict";var o,r,i,s=(t("./ghostmode.scroll"),t("./browser.utils")),c={display:"none",padding:"15px",fontFamily:"sans-serif",position:"fixed",fontSize:"0.9em",zIndex:9999,right:0,top:0,borderBottomLeftRadius:"5px",backgroundColor:"#1B2032",margin:0,color:"white",textAlign:"center"};n.init=function(t){r=t.options;var e=c;if(r.notify.styles)if("[object Array]"===Object.prototype.toString.call(r.notify.styles))e=r.notify.styles.join(";");else for(var i in r.notify.styles)r.notify.styles.hasOwnProperty(i)&&(e[i]=r.notify.styles[i]);if(o=document.createElement("DIV"),o.id="__bs_notify__","string"==typeof e)o.style.cssText=e;else for(var s in e)o.style[s]=e[s];var a=n.watchEvent(t);return t.emitter.on("notify",a),t.socket.on("browser:notify",a),o},n.watchEvent=function(t){return function(e){if(t.options.notify||e.override){if("string"==typeof e)return n.flash(e);n.flash(e.message,e.timeout)}}},n.getElem=function(){return o},n.flash=function(t,e){var o=n.getElem(),r=s.getBody();return o?(o.innerHTML=t,o.style.display="block",r.appendChild(o),i&&(clearTimeout(i),i=void 0),i=window.setTimeout(function(){o.style.display="none",o.parentNode&&r.removeChild(o)},e||2e3),o):!1}},{"./browser.utils":2,"./ghostmode.scroll":14}],17:[function(t,e,n){"use strict";var o=window.___browserSync___||{};n.socket=o.socket||{emit:function(){},on:function(){}},n.getPath=function(){return window.location.pathname},n.emit=function(t,e){var o=n.socket;o&&o.emit&&(e.url=n.getPath(),o.emit(t,e))},n.on=function(t,e){n.socket.on(t,e)}},{}],18:[function(t,e,n){function o(){a[r]?c.emit("tab:hidden"):c.emit("tab:visible")}var r,i,s=t("./browser.utils"),c=t("./emitter"),a=s.getDocument();"undefined"!=typeof a.hidden?(r="hidden",i="visibilitychange"):"undefined"!=typeof a.mozHidden?(r="mozHidden",i="mozvisibilitychange"):"undefined"!=typeof a.msHidden?(r="msHidden",i="msvisibilitychange"):"undefined"!=typeof a.webkitHidden&&(r="webkitHidden",i="webkitvisibilitychange"),"undefined"==typeof a.addEventListener||"undefined"==typeof a[r]||a.addEventListener(i,o,!1)},{"./browser.utils":2,"./emitter":5}]},{},[15]);<commit_msg>Migrate browsersync-client<commit_after><|endoftext|>