<commit_before>(function()
{
    'use strict';

    angular
        .module('lumx.search-filter')
        .filter('lxSearchHighlight', lxSearchHighlight)
        .directive('lxSearchFilter', lxSearchFilter);

    lxSearchHighlight.$inject = ['$sce'];

    function lxSearchHighlight($sce)
    {
        function escapeRegexp(queryToEscape)
        {
            return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
        }

        return function (matchItem, query, icon)
        {
            var string = '';

            if (icon)
            {
                string += '';
            }

            string += query && matchItem ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem;

            return $sce.trustAsHtml(string);
        };
    }

    function lxSearchFilter()
    {
        return {
            restrict: 'E',
            templateUrl: 'search-filter.html',
            scope:
            {
                autocomplete: '&?lxAutocomplete',
                closed: '=?lxClosed',
                color: '@?lxColor',
                icon: '@?lxIcon',
                onSelect: '=?lxOnSelect',
                searchOnFocus: '=?lxSearchOnFocus',
                theme: '@?lxTheme',
                width: '@?lxWidth'
            },
            link: link,
            controller: LxSearchFilterController,
            controllerAs: 'lxSearchFilter',
            bindToController: true,
            replace: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrl, transclude)
        {
            var input;

            attrs.$observe('lxWidth', function(newWidth)
            {
                if (angular.isDefined(scope.lxSearchFilter.closed) && scope.lxSearchFilter.closed)
                {
                    element.find('.search-filter__container').css('width', newWidth);
                }
            });

            transclude(function()
            {
                input = element.find('input');

                ctrl.setInput(input);
                ctrl.setModel(input.data('$ngModelController'));

                input.on('focus', ctrl.focusInput);
                input.on('blur', ctrl.blurInput);
                input.on('keydown', ctrl.keyEvent);
            });

            scope.$on('$destroy', function()
            {
                input.off();
            });
        }
    }

    LxSearchFilterController.$inject = ['$element', '$scope', 'LxDropdownService', 'LxNotificationService', 'LxUtils'];

    function LxSearchFilterController($element, $scope, LxDropdownService, LxNotificationService, LxUtils)
    {
        var lxSearchFilter = this;
        var debouncedAutocomplete;
        var input;
        var itemSelected = false;

        lxSearchFilter.blurInput = blurInput;
        lxSearchFilter.clearInput = clearInput;
        lxSearchFilter.focusInput = focusInput;
        lxSearchFilter.getClass = getClass;
        lxSearchFilter.keyEvent = keyEvent;
        lxSearchFilter.openInput = openInput;
        lxSearchFilter.selectItem = selectItem;
        lxSearchFilter.setInput = setInput;
        lxSearchFilter.setModel = setModel;

        lxSearchFilter.activeChoiceIndex = -1;
        lxSearchFilter.color = angular.isDefined(lxSearchFilter.color) ? lxSearchFilter.color : 'black';
        lxSearchFilter.dropdownId = LxUtils.generateUUID();
        lxSearchFilter.theme = angular.isDefined(lxSearchFilter.theme) ? lxSearchFilter.theme : 'light';

        ////////////

        function blurInput()
        {
            if (angular.isDefined(lxSearchFilter.closed) && lxSearchFilter.closed && !input.val())
            {
                $element.velocity(
                {
                    width: 40
                },
                {
                    duration: 400,
                    easing: 'easeOutQuint',
                    queue: false
                });
            }

            if (!input.val())
            {
                lxSearchFilter.modelController.$setViewValue(undefined);
            }
        }

        function clearInput()
        {
            lxSearchFilter.modelController.$setViewValue(undefined);
            lxSearchFilter.modelController.$render();

            input.focus();
        }

        function focusInput()
        {
            if (!lxSearchFilter.searchOnFocus)
            {
                return;
            }

            updateAutocomplete(lxSearchFilter.modelController.$viewValue, true);
        }

        function getClass()
        {
            var searchFilterClass = [];

            if (angular.isUndefined(lxSearchFilter.closed) || !lxSearchFilter.closed)
            {
                searchFilterClass.push('search-filter--opened-mode');
            }

            if (angular.isDefined(lxSearchFilter.closed) && lxSearchFilter.closed)
            {
                searchFilterClass.push('search-filter--closed-mode');
            }

            if (input.val())
            {
                searchFilterClass.push('search-filter--has-clear-button');
            }

            if (angular.isDefined(lxSearchFilter.color))
            {
                searchFilterClass.push('search-filter--' + lxSearchFilter.color);
            }

            if (angular.isDefined(lxSearchFilter.theme))
            {
                searchFilterClass.push('search-filter--theme-' + lxSearchFilter.theme);
            }

            if (angular.isFunction(lxSearchFilter.autocomplete))
            {
                searchFilterClass.push('search-filter--autocomplete');
            }

            if (LxDropdownService.isOpen(lxSearchFilter.dropdownId))
            {
                searchFilterClass.push('search-filter--is-open');
            }

            return searchFilterClass;
        }

        function keyEvent(_event)
        {
            if (!angular.isFunction(lxSearchFilter.autocomplete))
            {
                return;
            }

            if (!LxDropdownService.isOpen(lxSearchFilter.dropdownId))
            {
                lxSearchFilter.activeChoiceIndex = -1;
            }

            switch (_event.keyCode) {
                case 13:
                    keySelect();
                    if (lxSearchFilter.activeChoiceIndex > -1)
                    {
                        _event.preventDefault();
                    }
                    break;

                case 38:
                    keyUp();
                    _event.preventDefault();
                    break;

                case 40:
                    keyDown();
                    _event.preventDefault();
                    break;
            }

            $scope.$apply();
        }

        function keyDown()
        {
            if (lxSearchFilter.autocompleteList.length)
            {
                lxSearchFilter.activeChoiceIndex += 1;

                if (lxSearchFilter.activeChoiceIndex >= lxSearchFilter.autocompleteList.length)
                {
                    lxSearchFilter.activeChoiceIndex = 0;
                }
            }
        }

        function keySelect()
        {
            if (!lxSearchFilter.autocompleteList || lxSearchFilter.activeChoiceIndex === -1)
            {
                return;
            }

            selectItem(lxSearchFilter.autocompleteList[lxSearchFilter.activeChoiceIndex]);
        }

        function keyUp()
        {
            if (lxSearchFilter.autocompleteList.length)
            {
                lxSearchFilter.activeChoiceIndex -= 1;

                if (lxSearchFilter.activeChoiceIndex < 0)
                {
                    lxSearchFilter.activeChoiceIndex = lxSearchFilter.autocompleteList.length - 1;
                }
            }
        }

        function onAutocompleteSuccess(autocompleteList)
        {
            lxSearchFilter.autocompleteList = autocompleteList;

            if (lxSearchFilter.autocompleteList.length)
            {
                LxDropdownService.open(lxSearchFilter.dropdownId, $element);
            }
            else
            {
                LxDropdownService.close(lxSearchFilter.dropdownId);
            }
            lxSearchFilter.isLoading = false;
        }

        function onAutocompleteError(error)
        {
            LxNotificationService.error(error);
            lxSearchFilter.isLoading = false;
        }

        function openInput()
        {
            if (angular.isDefined(lxSearchFilter.closed) && lxSearchFilter.closed)
            {
                $element.velocity(
                {
                    width: angular.isDefined(lxSearchFilter.width) ? parseInt(lxSearchFilter.width) : 240
                },
                {
                    duration: 400,
                    easing: 'easeOutQuint',
                    queue: false,
                    complete: function()
                    {
                        input.focus();
                    }
                });
            }
            else
            {
                input.focus();
            }
        }

        function selectItem(_item)
        {
            itemSelected = true;

            LxDropdownService.close(lxSearchFilter.dropdownId);

            lxSearchFilter.modelController.$setViewValue(_item);
            lxSearchFilter.modelController.$render();

            if (angular.isFunction(lxSearchFilter.onSelect))
            {
                lxSearchFilter.onSelect(_item);
            }
        }

        function setInput(_input)
        {
            input = _input;
        }

        function setModel(_modelController)
        {
            lxSearchFilter.modelController = _modelController;

            if (angular.isFunction(lxSearchFilter.autocomplete) && angular.isFunction(lxSearchFilter.autocomplete()))
            {
                debouncedAutocomplete = LxUtils.debounce(function()
                {
                    lxSearchFilter.isLoading = true;
                    (lxSearchFilter.autocomplete()).apply(this, arguments);
                }, 500);
                lxSearchFilter.modelController.$parsers.push(updateAutocomplete);
            }
        }

        function updateAutocomplete(_newValue, _immediate)
        {
            if ((_newValue || (angular.isUndefined(_newValue) && lxSearchFilter.searchOnFocus)) && !itemSelected)
            {
                if (_immediate)
                {
                    lxSearchFilter.isLoading = true;
                    (lxSearchFilter.autocomplete())(_newValue, onAutocompleteSuccess, onAutocompleteError);
                }
                else
                {
                    debouncedAutocomplete(_newValue, onAutocompleteSuccess, onAutocompleteError);
                }
            }
            else
            {
                debouncedAutocomplete.clear();
                LxDropdownService.close(lxSearchFilter.dropdownId);
            }

            itemSelected = false;

            return _newValue;
        }
    }
})();<commit_msg>fix search-filter: clearing input should not trigger a search again<commit_after>(function()
{
    'use strict';

    angular
        .module('lumx.search-filter')
        .filter('lxSearchHighlight', lxSearchHighlight)
        .directive('lxSearchFilter', lxSearchFilter);

    lxSearchHighlight.$inject = ['$sce'];

    function lxSearchHighlight($sce)
    {
        function escapeRegexp(queryToEscape)
        {
            return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
        }

        return function (matchItem, query, icon)
        {
            var string = '';

            if (icon)
            {
                string += '';
            }

            string += query && matchItem ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem;

            return $sce.trustAsHtml(string);
        };
    }

    function lxSearchFilter()
    {
        return {
            restrict: 'E',
            templateUrl: 'search-filter.html',
            scope:
            {
                autocomplete: '&?lxAutocomplete',
                closed: '=?lxClosed',
                color: '@?lxColor',
                icon: '@?lxIcon',
                onSelect: '=?lxOnSelect',
                searchOnFocus: '=?lxSearchOnFocus',
                theme: '@?lxTheme',
                width: '@?lxWidth'
            },
            link: link,
            controller: LxSearchFilterController,
            controllerAs: 'lxSearchFilter',
            bindToController: true,
            replace: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrl, transclude)
        {
            var input;

            attrs.$observe('lxWidth', function(newWidth)
            {
                if (angular.isDefined(scope.lxSearchFilter.closed) && scope.lxSearchFilter.closed)
                {
                    element.find('.search-filter__container').css('width', newWidth);
                }
            });

            transclude(function()
            {
                input = element.find('input');

                ctrl.setInput(input);
                ctrl.setModel(input.data('$ngModelController'));

                input.on('focus', ctrl.focusInput);
                input.on('blur', ctrl.blurInput);
                input.on('keydown', ctrl.keyEvent);
            });

            scope.$on('$destroy', function()
            {
                input.off();
            });
        }
    }

    LxSearchFilterController.$inject = ['$element', '$scope', 'LxDropdownService', 'LxNotificationService', 'LxUtils'];

    function LxSearchFilterController($element, $scope, LxDropdownService, LxNotificationService, LxUtils)
    {
        var lxSearchFilter = this;
        var debouncedAutocomplete;
        var input;
        var itemSelected = false;

        lxSearchFilter.blurInput = blurInput;
        lxSearchFilter.clearInput = clearInput;
        lxSearchFilter.focusInput = focusInput;
        lxSearchFilter.getClass = getClass;
        lxSearchFilter.keyEvent = keyEvent;
        lxSearchFilter.openInput = openInput;
        lxSearchFilter.selectItem = selectItem;
        lxSearchFilter.setInput = setInput;
        lxSearchFilter.setModel = setModel;

        lxSearchFilter.activeChoiceIndex = -1;
        lxSearchFilter.color = angular.isDefined(lxSearchFilter.color) ? lxSearchFilter.color : 'black';
        lxSearchFilter.dropdownId = LxUtils.generateUUID();
        lxSearchFilter.theme = angular.isDefined(lxSearchFilter.theme) ? lxSearchFilter.theme : 'light';

        ////////////

        function blurInput()
        {
            if (angular.isDefined(lxSearchFilter.closed) && lxSearchFilter.closed && !input.val())
            {
                $element.velocity(
                {
                    width: 40
                },
                {
                    duration: 400,
                    easing: 'easeOutQuint',
                    queue: false
                });
            }

            if (!input.val())
            {
                lxSearchFilter.modelController.$setViewValue(undefined);
            }
        }

        function clearInput()
        {
            lxSearchFilter.modelController.$setViewValue(undefined);
            lxSearchFilter.modelController.$render();

            // Temporarily disabling search on focus since we never want to trigger it when clearing the input.
            var searchOnFocus = lxSearchFilter.searchOnFocus;
            lxSearchFilter.searchOnFocus = false;

            input.focus();

            lxSearchFilter.searchOnFocus = searchOnFocus;
        }

        function focusInput()
        {
            if (!lxSearchFilter.searchOnFocus)
            {
                return;
            }

            updateAutocomplete(lxSearchFilter.modelController.$viewValue, true);
        }

        function getClass()
        {
            var searchFilterClass = [];

            if (angular.isUndefined(lxSearchFilter.closed) || !lxSearchFilter.closed)
            {
                searchFilterClass.push('search-filter--opened-mode');
            }

            if (angular.isDefined(lxSearchFilter.closed) && lxSearchFilter.closed)
            {
                searchFilterClass.push('search-filter--closed-mode');
            }

            if (input.val())
            {
                searchFilterClass.push('search-filter--has-clear-button');
            }

            if (angular.isDefined(lxSearchFilter.color))
            {
                searchFilterClass.push('search-filter--' + lxSearchFilter.color);
            }

            if (angular.isDefined(lxSearchFilter.theme))
            {
                searchFilterClass.push('search-filter--theme-' + lxSearchFilter.theme);
            }

            if (angular.isFunction(lxSearchFilter.autocomplete))
            {
                searchFilterClass.push('search-filter--autocomplete');
            }

            if (LxDropdownService.isOpen(lxSearchFilter.dropdownId))
            {
                searchFilterClass.push('search-filter--is-open');
            }

            return searchFilterClass;
        }

        function keyEvent(_event)
        {
            if (!angular.isFunction(lxSearchFilter.autocomplete))
            {
                return;
            }

            if (!LxDropdownService.isOpen(lxSearchFilter.dropdownId))
            {
                lxSearchFilter.activeChoiceIndex = -1;
            }

            switch (_event.keyCode) {
                case 13:
                    keySelect();
                    if (lxSearchFilter.activeChoiceIndex > -1)
                    {
                        _event.preventDefault();
                    }
                    break;

                case 38:
                    keyUp();
                    _event.preventDefault();
                    break;

                case 40:
                    keyDown();
                    _event.preventDefault();
                    break;
            }

            $scope.$apply();
        }

        function keyDown()
        {
            if (lxSearchFilter.autocompleteList.length)
            {
                lxSearchFilter.activeChoiceIndex += 1;

                if (lxSearchFilter.activeChoiceIndex >= lxSearchFilter.autocompleteList.length)
                {
                    lxSearchFilter.activeChoiceIndex = 0;
                }
            }
        }

        function keySelect()
        {
            if (!lxSearchFilter.autocompleteList || lxSearchFilter.activeChoiceIndex === -1)
            {
                return;
            }

            selectItem(lxSearchFilter.autocompleteList[lxSearchFilter.activeChoiceIndex]);
        }

        function keyUp()
        {
            if (lxSearchFilter.autocompleteList.length)
            {
                lxSearchFilter.activeChoiceIndex -= 1;

                if (lxSearchFilter.activeChoiceIndex < 0)
                {
                    lxSearchFilter.activeChoiceIndex = lxSearchFilter.autocompleteList.length - 1;
                }
            }
        }

        function onAutocompleteSuccess(autocompleteList)
        {
            lxSearchFilter.autocompleteList = autocompleteList;

            if (lxSearchFilter.autocompleteList.length)
            {
                LxDropdownService.open(lxSearchFilter.dropdownId, $element);
            }
            else
            {
                LxDropdownService.close(lxSearchFilter.dropdownId);
            }
            lxSearchFilter.isLoading = false;
        }

        function onAutocompleteError(error)
        {
            LxNotificationService.error(error);
            lxSearchFilter.isLoading = false;
        }

        function openInput()
        {
            if (angular.isDefined(lxSearchFilter.closed) && lxSearchFilter.closed)
            {
                $element.velocity(
                {
                    width: angular.isDefined(lxSearchFilter.width) ? parseInt(lxSearchFilter.width) : 240
                },
                {
                    duration: 400,
                    easing: 'easeOutQuint',
                    queue: false,
                    complete: function()
                    {
                        input.focus();
                    }
                });
            }
            else
            {
                input.focus();
            }
        }

        function selectItem(_item)
        {
            itemSelected = true;

            LxDropdownService.close(lxSearchFilter.dropdownId);

            lxSearchFilter.modelController.$setViewValue(_item);
            lxSearchFilter.modelController.$render();

            if (angular.isFunction(lxSearchFilter.onSelect))
            {
                lxSearchFilter.onSelect(_item);
            }
        }

        function setInput(_input)
        {
            input = _input;
        }

        function setModel(_modelController)
        {
            lxSearchFilter.modelController = _modelController;

            if (angular.isFunction(lxSearchFilter.autocomplete) && angular.isFunction(lxSearchFilter.autocomplete()))
            {
                debouncedAutocomplete = LxUtils.debounce(function()
                {
                    lxSearchFilter.isLoading = true;
                    (lxSearchFilter.autocomplete()).apply(this, arguments);
                }, 500);
                lxSearchFilter.modelController.$parsers.push(updateAutocomplete);
            }
        }

        function updateAutocomplete(_newValue, _immediate)
        {
            if ((_newValue || (angular.isUndefined(_newValue) && lxSearchFilter.searchOnFocus)) && !itemSelected)
            {
                if (_immediate)
                {
                    lxSearchFilter.isLoading = true;
                    (lxSearchFilter.autocomplete())(_newValue, onAutocompleteSuccess, onAutocompleteError);
                }
                else
                {
                    debouncedAutocomplete(_newValue, onAutocompleteSuccess, onAutocompleteError);
                }
            }
            else
            {
                debouncedAutocomplete.clear();
                LxDropdownService.close(lxSearchFilter.dropdownId);
            }

            itemSelected = false;

            return _newValue;
        }
    }
})();<|endoftext|>


<commit_before>var util = require('util');
var Service = require('../../service').Service;
var ServiceNode = require('../../node').ServiceNode;
var os = require('os');
var mage = require('../../../mage');
var requirePeer = require('codependency').get('mage');
var zooKeeper = requirePeer('node-zookeeper-client');
var logger = mage.core.logger.context('zooKeeper');

var CONNECT_TIMEOUT = 5 * 1000;

// choose the first valid ip as the one we will announce
var announceIps;

/**
 * Builds a list of every announce-able ips on the server
 *
 * @returns {string} The ip list
 * @todo Support from env variables?
 */
function getAnnounceIps() {
	if (announceIps) {
		return announceIps;
	}

	var interfaces = os.networkInterfaces();
	var ifaceNames = Object.keys(interfaces);

	announceIps = [];
	for (var i = 0; i < ifaceNames.length; i++) {
		var addresses = interfaces[ifaceNames[i]];

		for (var j = 0; j < addresses.length; j++) {
			var address = addresses[j];

			// skip anything that doesn't interest us
			if (address.internal) {
				continue;
			}

			// found it, store it and break
			announceIps.push(address.address);
		}
	}

	// just in case
	return announceIps;
}

/**
 * Creates a zookeeper client, sets up relevant event listeners and connects.
 *
 * @param {Object} options
 * @returns {zooKeeper.client}
 */
function createZooKeeperClient(options) {
	options = options || {};

	if (!options.hosts) {
		throw new Error('Missing configuration server.discoveryService.options.hosts for ZooKeeper');
	}

	// client options, with better defaults than node-zookeeper-client provides

	var clientOpts = options.options || {};

	clientOpts.sessionTimeout = clientOpts.hasOwnProperty('sessionTimeout') ? clientOpts.sessionTimeout : 30000;
	clientOpts.spinDelay = clientOpts.hasOwnProperty('spinDelay') ? clientOpts.spinDelay : 1000;
	clientOpts.retries = clientOpts.hasOwnProperty('retries') ? clientOpts.retries : 3;

	// connect to the database

	var client = zooKeeper.createClient(options.hosts, clientOpts);

	client.on('connected', function () {
		logger.verbose('ZooKeeper connection established');
	});

	client.on('connectedReadOnly', function () {
		logger.error('ZooKeeper connection established to a read-only server');
	});

	client.on('disconnected', function () {
		logger.verbose('ZooKeeper connection dropped');
	});

	client.on('expired', function () {
		logger.verbose('ZooKeeper client session expired');
	});

	client.on('authenticationFailed', function () {
		logger.error('ZooKeeper authentication failed');
	});

	return client;
}

/**
 * This is our service instance for zookeeper
 *
 * @param {string} name    The name of the service we want to announce
 * @param {string} type    The type of service (tcp or udp)
 * @param {Object} options The options to provide to the service
 * @constructor
 */
function ZooKeeperService(name, type, options) {
	this.name = name;
	this.type = type;
	this.client = createZooKeeperClient(options);

	// this is the base path we will use to announce this service
	this.baseAnnouncePath = ['/mage', this.name, this.type].join('/');

	// those are the nodes we know on the given path
	this.nodes = [];

	// node data is stored apart
	this.services = {};

	// connect

	logger.verbose('ZooKeeper client connecting to', options.hosts);

	var that = this;

	this.client.connect();

	this.connectTimer = setTimeout(function () {
		var state = that.client.getState();

		if (state !== zooKeeper.State.SYNC_CONNECTED) {
			logger.alert.data('connection-options', options).log(
				'Still not connected to ZooKeeper server after', CONNECT_TIMEOUT / 1000, 'seconds.',
				'Please inspect your configuration.'
			);
		}

		that.connectTimer = null;
	}, CONNECT_TIMEOUT);
}

util.inherits(ZooKeeperService, Service);

/**
 * Announce our service to the world.
 * Flow:
 * 1. Remove the existing node (just in case, because we've seen lingering ephemeral nodes causing
 *    nasty errors)
 * 2. Create the parent directory
 * 3. Create the node
 *
 * @param {number}   port     The port to announce
 * @param {Object}   metadata Some metadata that will be transferred to clients on the network
 * @param {Function} cb       This callback is called once the announcement is done. If any error
 *                            occurred, it is returned in the first argument
 */
ZooKeeperService.prototype.announce = function (port, metadata, cb) {
	var that = this;

	// enrich metadata with some extra stuff from us
	metadata = {
		ips: getAnnounceIps(),
		data: metadata
	};

	// check if the parent path exists

	var dataBuffer = new Buffer(JSON.stringify(metadata));
	var announcePath = [this.baseAnnouncePath, os.hostname() + ':' + port].join('/');

	logger.verbose('Removing', announcePath, '(this can time out or hang forever if zookeeper is not reachable).');

	that.client.remove(announcePath, function (error) {
		// ignore error if remove failed because our node didn't exist to begin with (the common case)

		if (error && error.getCode() !== zooKeeper.Exception.NO_NODE) {
			return cb(error);
		}

		logger.verbose('Creating directory', that.baseAnnouncePath);

		that.client.mkdirp(that.baseAnnouncePath, function (error) {
			if (error) {
				return cb(error);
			}

			logger.verbose('Creating service node', announcePath);

			that.client.create(announcePath, dataBuffer, zooKeeper.CreateMode.EPHEMERAL, function (error) {
				if (error) {
					// Be ultra verbose about what we know should not happen and why.
					// Normal emergency logging happens outside this library, but we want to log
					// this particular message.

					if (error.getCode() === zooKeeper.Exception.NODE_EXISTS) {
						logger.emergency
							.details('That can only mean the following.')
							.details('(1) Double callbacks during the MAGE setup phase.')
							.details('(2) A race condition between two master processes ' +
								'that both identify as ' + announcePath + '.')
							.log('NODE_EXISTS on our node creation should *never* happen, but it just did.');
					}
				}

				cb(error);
			});
		});
	});
};

/**
 * Retrieve the details from a node, then emit the `up` event with the node details
 *
 * @param {string} node
 * @private
 */
ZooKeeperService.prototype.discoverNode = function (node) {
	var that = this;

	// get the data from the node
	this.client.getData([this.baseAnnouncePath, node].join('/'), function (error, data) {
		if (error) {
			that.emit('error', error);
			return;
		}

		// parse the metadata
		data = JSON.parse(data);

		// retrieve the host/port from the node name
		var nodeData = node.split(':');
		var host = nodeData[0];
		var port = nodeData[1];

		// store the metadata so that we can retrieve it when the node goes down
		that.services[node] = new ServiceNode(host, port, data.ips, data.data);

		// emit the up signal
		that.emit('up', that.services[node]);
	});
};

/**
 * Called when an event happened on our parent node, it will retrieve the list of children and update the network
 * informations
 *
 * @param {zooKeeper.Event} event
 * @private
 */
ZooKeeperService.prototype.onWatchEvent = function (event) {
	var that = this;
	logger.verbose.data(event).log('ZooKeeper path changed');

	function onWatch(event) {
		that.onWatchEvent(event);
	}

	if ((event.name === 'NODE_CHILDREN_CHANGED') && (event.path === this.baseAnnouncePath)) {
		this.client.getChildren(this.baseAnnouncePath, onWatch, function (error, children) {
			if (error) {
				that.emit('error', error);
				return;
			}

			logger.verbose.data(children).log('Updating network');

			that.updateNetwork(children);
		});
	}
};

/**
 * Takes a list of nodes (ip:port as a string) and checks for differences with the currently known nodes on the network.
 *
 * @param {string[]} children
 * @private
 */
ZooKeeperService.prototype.updateNetwork = function (children) {
	// we move new nodes and already known nodes there so that we can list deleted nodes easily
	var newNetwork = [];
	var i;

	for (i = 0; i < children.length; i++) {
		var child = children[i];
		var n;

		if ((n = this.nodes.indexOf(child)) === -1) {
			newNetwork.push(child);

			logger.verbose('New node on the network', child);

			// pull data from the node
			this.discoverNode(child);
		} else {
			newNetwork.push(this.nodes.splice(n, 1)[0]);
		}
	}

	// now everything left are nodes that don't exists anymore on the network, delete them
	for (i = 0; i < this.nodes.length; i++) {
		var node = this.nodes[i];

		logger.verbose('Down node', node);

		// if we know what the node is
		if (this.services[node]) {
			// emit the down signal
			this.emit('down', this.services[node]);

			// we don't need the node's data anymore, remove it
			delete this.services[node];
		}
	}

	logger.verbose.data(newNetwork).log('Network updated!');

	// then switch old network map with new one
	this.nodes = newNetwork;
};

/**
 * Start the discovery process
 */
ZooKeeperService.prototype.discover = function () {
	var that = this;

	logger.debug('Discovering network');

	function onWatch(event) {
		that.onWatchEvent(event);
	}

	// first retrieve nodes on the network, and put a watcher on that path
	this.client.getChildren(this.baseAnnouncePath, onWatch, function (error, children) {
		if (error) {
			return that.emit('error', error);
		}

		// update the network with the found children
		that.updateNetwork(children);
	});
};

ZooKeeperService.prototype.close = function (cb) {
	var state = this.client.getState();

	if (this.connectTimer) {
		clearTimeout(this.connectTimer);
		this.connectTimer = null;
	}

	// manually closing makes the ephemeral nodes disappear instantly instead of several seconds later

	if (state === zooKeeper.State.SYNC_CONNECTED) {
		this.client.close();
	}

	setImmediate(cb);
};

/**
 * Creates a version of the service using the type and options provided
 *
 * @param {string} name    The name of the service we want to announce/discover
 * @param {string} type    The type of service, udp or tcp
 * @param {Object} options Options to provide to the service
 * @returns {ZooKeeperService}
 */
exports.create = function (name, type, options) {
	return new ZooKeeperService(name, type, options);
};
<commit_msg>zookeeper connection loss<commit_after>var util = require('util');
var Service = require('../../service').Service;
var ServiceNode = require('../../node').ServiceNode;
var os = require('os');
var mage = require('../../../mage');
var requirePeer = require('codependency').get('mage');
var zooKeeper = requirePeer('node-zookeeper-client');
var logger = mage.core.logger.context('zooKeeper');

var CONNECT_TIMEOUT = 5 * 1000;

// choose the first valid ip as the one we will announce
var announceIps;

/**
 * Builds a list of every announce-able ips on the server
 *
 * @returns {string} The ip list
 * @todo Support from env variables?
 */
function getAnnounceIps() {
	if (announceIps) {
		return announceIps;
	}

	var interfaces = os.networkInterfaces();
	var ifaceNames = Object.keys(interfaces);

	announceIps = [];
	for (var i = 0; i < ifaceNames.length; i++) {
		var addresses = interfaces[ifaceNames[i]];

		for (var j = 0; j < addresses.length; j++) {
			var address = addresses[j];

			// skip anything that doesn't interest us
			if (address.internal) {
				continue;
			}

			// found it, store it and break
			announceIps.push(address.address);
		}
	}

	// just in case
	return announceIps;
}

/**
 * Creates a zookeeper client, sets up relevant event listeners and connects.
 *
 * @param {Object} options
 * @returns {zooKeeper.client}
 */
function createZooKeeperClient(options) {
	options = options || {};

	if (!options.hosts) {
		throw new Error('Missing configuration server.discoveryService.options.hosts for ZooKeeper');
	}

	// client options, with better defaults than node-zookeeper-client provides

	var clientOpts = options.options || {};

	clientOpts.sessionTimeout = clientOpts.hasOwnProperty('sessionTimeout') ? clientOpts.sessionTimeout : 30000;
	clientOpts.spinDelay = clientOpts.hasOwnProperty('spinDelay') ? clientOpts.spinDelay : 1000;
	clientOpts.retries = clientOpts.hasOwnProperty('retries') ? clientOpts.retries : 3;

	// connect to the database

	var client = zooKeeper.createClient(options.hosts, clientOpts);

	client.on('connected', function () {
		logger.verbose('ZooKeeper connection established');
	});

	client.on('connectedReadOnly', function () {
		logger.error('ZooKeeper connection established to a read-only server');
	});

	client.on('disconnected', function () {
		logger.verbose('ZooKeeper connection dropped');
	});

	client.on('expired', function () {
		logger.verbose('ZooKeeper client session expired');
	});

	client.on('authenticationFailed', function () {
		logger.error('ZooKeeper authentication failed');
	});

	return client;
}

/**
 * This is our service instance for zookeeper
 *
 * @param {string} name    The name of the service we want to announce
 * @param {string} type    The type of service (tcp or udp)
 * @param {Object} options The options to provide to the service
 * @constructor
 */
function ZooKeeperService(name, type, options) {
	this.name = name;
	this.type = type;
	this.client = createZooKeeperClient(options);

	// this is the base path we will use to announce this service
	this.baseAnnouncePath = ['/mage', this.name, this.type].join('/');

	// those are the nodes we know on the given path
	this.nodes = [];

	// node data is stored apart
	this.services = {};

	// connect

	logger.verbose('ZooKeeper client connecting to', options.hosts);

	var that = this;

	this.client.connect();

	this.connectTimer = setTimeout(function () {
		var state = that.client.getState();

		if (state !== zooKeeper.State.SYNC_CONNECTED) {
			logger.alert.data('connection-options', options).log(
				'Still not connected to ZooKeeper server after', CONNECT_TIMEOUT / 1000, 'seconds.',
				'Please inspect your configuration.'
			);
		}

		that.connectTimer = null;
	}, CONNECT_TIMEOUT);
}

util.inherits(ZooKeeperService, Service);

/**
 * Announce our service to the world.
 * Flow:
 * 1. Remove the existing node (just in case, because we've seen lingering ephemeral nodes causing
 *    nasty errors)
 * 2. Create the parent directory
 * 3. Create the node
 *
 * @param {number}   port     The port to announce
 * @param {Object}   metadata Some metadata that will be transferred to clients on the network
 * @param {Function} cb       This callback is called once the announcement is done. If any error
 *                            occurred, it is returned in the first argument
 */
ZooKeeperService.prototype.announce = function (port, metadata, cb) {
	var that = this;

	// enrich metadata with some extra stuff from us
	metadata = {
		ips: getAnnounceIps(),
		data: metadata
	};

	// check if the parent path exists

	var dataBuffer = new Buffer(JSON.stringify(metadata));
	var announcePath = [this.baseAnnouncePath, os.hostname() + ':' + port].join('/');

	logger.verbose('Removing', announcePath, '(this can time out or hang forever if zookeeper is not reachable).');

	that.client.remove(announcePath, function (error) {
		// ignore error if remove failed because our node didn't exist to begin with (the common case)

		if (error && error.getCode() !== zooKeeper.Exception.NO_NODE) {
			return cb(error);
		}

		logger.verbose('Creating directory', that.baseAnnouncePath);

		that.client.mkdirp(that.baseAnnouncePath, function (error) {
			if (error) {
				return cb(error);
			}

			logger.verbose('Creating service node', announcePath);

			that.client.create(announcePath, dataBuffer, zooKeeper.CreateMode.EPHEMERAL, function (error) {
				if (error) {
					// Be ultra verbose about what we know should not happen and why.
					// Normal emergency logging happens outside this library, but we want to log
					// this particular message.

					if (error.getCode() === zooKeeper.Exception.NODE_EXISTS) {
						logger.emergency
							.details('That can only mean the following.')
							.details('(1) Double callbacks during the MAGE setup phase.')
							.details('(2) A race condition between two master processes ' +
								'that both identify as ' + announcePath + '.')
							.log('NODE_EXISTS on our node creation should *never* happen, but it just did.');
					}
				}

				cb(error);
			});
		});
	});
};

/**
 * Retrieve the details from a node, then emit the `up` event with the node details
 *
 * @param {string} node
 * @private
 */
ZooKeeperService.prototype.discoverNode = function (node) {
	var that = this;

	// get the data from the node
	this.client.getData([this.baseAnnouncePath, node].join('/'), function (error, data) {
		if (error) {
			that.emitError(error);
			return;
		}

		// parse the metadata
		data = JSON.parse(data);

		// retrieve the host/port from the node name
		var nodeData = node.split(':');
		var host = nodeData[0];
		var port = nodeData[1];

		// store the metadata so that we can retrieve it when the node goes down
		that.services[node] = new ServiceNode(host, port, data.ips, data.data);

		// emit the up signal
		that.emit('up', that.services[node]);
	});
};

/**
 * Called when an event happened on our parent node, it will retrieve the list of children and update the network
 * informations
 *
 * @param {zooKeeper.Event} event
 * @private
 */
ZooKeeperService.prototype.onWatchEvent = function (event) {
	var that = this;
	logger.verbose.data(event).log('ZooKeeper path changed');

	function onWatch(event) {
		that.onWatchEvent(event);
	}

	if ((event.name === 'NODE_CHILDREN_CHANGED') && (event.path === this.baseAnnouncePath)) {
		this.client.getChildren(this.baseAnnouncePath, onWatch, function (error, children) {
			if (error) {
				that.emitError(error);
				return;
			}

			logger.verbose.data(children).log('Updating network');

			that.updateNetwork(children);
		});
	}
};

/**
 * Takes a list of nodes (ip:port as a string) and checks for differences with the currently known nodes on the network.
 *
 * @param {string[]} children
 * @private
 */
ZooKeeperService.prototype.updateNetwork = function (children) {
	// we move new nodes and already known nodes there so that we can list deleted nodes easily
	var newNetwork = [];
	var i;

	for (i = 0; i < children.length; i++) {
		var child = children[i];
		var n;

		if ((n = this.nodes.indexOf(child)) === -1) {
			newNetwork.push(child);

			logger.verbose('New node on the network', child);

			// pull data from the node
			this.discoverNode(child);
		} else {
			newNetwork.push(this.nodes.splice(n, 1)[0]);
		}
	}

	// now everything left are nodes that don't exists anymore on the network, delete them
	for (i = 0; i < this.nodes.length; i++) {
		var node = this.nodes[i];

		logger.verbose('Down node', node);

		// if we know what the node is
		if (this.services[node]) {
			// emit the down signal
			this.emit('down', this.services[node]);

			// we don't need the node's data anymore, remove it
			delete this.services[node];
		}
	}

	logger.verbose.data(newNetwork).log('Network updated!');

	// then switch old network map with new one
	this.nodes = newNetwork;
};

/**
 * Start the discovery process
 */
ZooKeeperService.prototype.discover = function () {
	var that = this;

	logger.debug('Discovering network');

	function onWatch(event) {
		that.onWatchEvent(event);
	}

	// first retrieve nodes on the network, and put a watcher on that path
	this.client.getChildren(this.baseAnnouncePath, onWatch, function (error, children) {
		if (error) {
			return that.emitError(error);
		}

		// update the network with the found children
		that.updateNetwork(children);
	});
};

ZooKeeperService.prototype.close = function (cb) {
	var state = this.client.getState();

	if (this.connectTimer) {
		clearTimeout(this.connectTimer);
		this.connectTimer = null;
	}

	// manually closing makes the ephemeral nodes disappear instantly instead of several seconds later

	if (state === zooKeeper.State.SYNC_CONNECTED) {
		this.client.close();
	}

	setImmediate(cb);
};

ZooKeeperService.prototype.emitError = function (error) {
	if (error.name !== 'CONNECTION_LOSS') {
	// We ignore connection losses since any persisting connnectivity issues
	// should be managed by the other event handlers, and connection loss for in-flight requests
	// will be retried by zookeper.
	//
	// See https://github.com/alexguan/node-zookeeper-client/blob/master/index.js#L138 for more details
		return logger.warning
			.details('node-zookeeper-client will retry the query; you may ignore')
			.details('this warning, unless it happens too frequently')
			.log('Received CONNECTION_LOSS event');
	}

	this.emit('error', error);
};

/**
 * Creates a version of the service using the type and options provided
 *
 * @param {string} name    The name of the service we want to announce/discover
 * @param {string} type    The type of service, udp or tcp
 * @param {Object} options Options to provide to the service
 * @returns {ZooKeeperService}
 */
exports.create = function (name, type, options) {
	return new ZooKeeperService(name, type, options);
};
<|endoftext|>


<commit_before>module.exports.name = 'jade';

module.exports.build = function (config) {
  var gulp = require('gulp');
  var jade = require('gulp-jade');
  var rename = require('gulp-rename');

  var jadeOptions = {
    basedir: config.__dirname
  };

  return function () {
    gulp.src([
      'jade/**.jade',
      '!jade/_**.jade',
      '!jade/templates/**.jade'
    ])
    .pipe(jade(jadeOptions))
    .pipe(rename({
      ext: 'ascx'
    }))
    .pipe(gulp.dest(config.dist));
  };
}
<commit_msg>fixed gulp-rename for task-jade<commit_after>module.exports.name = 'jade';

module.exports.build = function (config) {
  var gulp = require('gulp');
  var jade = require('gulp-jade');
  var rename = require('gulp-rename');

  var jadeOptions = {
    basedir: config.__dirname
  };

  return function () {
    gulp.src([
      'jade/**.jade',
      '!jade/_**.jade',
      '!jade/templates/**.jade'
    ])
    .pipe(jade(jadeOptions))
    .pipe(rename(function (path) {
      path.extname = '.ascx';
    }))
    .pipe(gulp.dest(config.dist));
  };
}
<|endoftext|>


<commit_before>var stops = [{"lat": 42.36, "lng": -71.07}, {"lat": 42.36, "lng": -71.08}, {"lat": 42.32, "lng": -71.08}
];

var stopCircles = [];

var initialLocation;

function randomlyPulse() {

};

$(document).ready(function() {
  var center;

  var latLng = new google.maps.LatLng(42.36, -71.08);
  var myOptions = {
    center: latLng,
    zoom: 12,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  $("#create_chat").hide();

  var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

  for (var i in stops) {
    var stopOptions;
    var stop;
    stop = stops[i];
    console.log("stop: " + stop.lat);
    center = new google.maps.LatLng(stop.lat, stop.lng);
    stopOptions = {
      strokeColor: "blue",
      strokeOpacity: 0.6,
      strokeWeight: 4,
      fillColor: "#FFFFFF",
      fillOpacity: 0.1,
      map: map,
      center: center,
      radius: 180
    }
    stopCircle = new google.maps.Circle(stopOptions);
    stopCircles.push(stopCircle);
    attachEventHandlerToStop(stopCircle, stop);
  }

  function attachEventHandlerToStop(stopCircle, stop) {
    google.maps.event.addListener(stopCircle, 'mouseover', function() {
      console.log("Stop "+stop.stop_name+" touched");
      stopCircle.setOptions({strokeColor: "red", radius: 220, strokeWeight: 7});
    });
    google.maps.event.addListener(stopCircle, 'mouseout', function() {
      stopCircle.setOptions({strokeColor: "blue", radius: 180, strokeWeight: 4});
    });
  }

  randomlyPulse();

  if(navigator.geolocation) {
    browserSupportFlag = true;
    navigator.geolocation.getCurrentPosition(function(position) {
      initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
      $("#create_chat").show();
    }, function() {
      // console.log("No geolocation");
    });
  }

});

<commit_msg>delete console.log statements<commit_after>var stops = [{"lat": 42.36, "lng": -71.07}, {"lat": 42.36, "lng": -71.08}, {"lat": 42.32, "lng": -71.08}
];

var stopCircles = [];

var initialLocation;

function randomlyPulse() {

};

$(document).ready(function() {
  var center;

  var latLng = new google.maps.LatLng(42.36, -71.08);
  var myOptions = {
    center: latLng,
    zoom: 12,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  $("#create_chat").hide();

  var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

  for (var i in stops) {
    var stopOptions;
    var stop;
    stop = stops[i];
    center = new google.maps.LatLng(stop.lat, stop.lng);
    stopOptions = {
      strokeColor: "blue",
      strokeOpacity: 0.6,
      strokeWeight: 4,
      fillColor: "#FFFFFF",
      fillOpacity: 0.1,
      map: map,
      center: center,
      radius: 180
    }
    stopCircle = new google.maps.Circle(stopOptions);
    stopCircles.push(stopCircle);
    attachEventHandlerToStop(stopCircle, stop);
  }

  function attachEventHandlerToStop(stopCircle, stop) {
    google.maps.event.addListener(stopCircle, 'mouseover', function() {
      stopCircle.setOptions({strokeColor: "red", radius: 220, strokeWeight: 7});
    });
    google.maps.event.addListener(stopCircle, 'mouseout', function() {
      stopCircle.setOptions({strokeColor: "blue", radius: 180, strokeWeight: 4});
    });
  }

  randomlyPulse();

  if(navigator.geolocation) {
    browserSupportFlag = true;
    navigator.geolocation.getCurrentPosition(function(position) {
      initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
      $("#create_chat").show();
    }, function() {
      // console.log("No geolocation");
    });
  }

});

<|endoftext|>


<commit_before>(function(root) {

  'use strict';

  root.app = root.app || {};

  root.app.Router = Backbone.Router.extend({

    routes: {
      // HOME
      '': 'home',
      // HOME
      'faqs(/)': 'faqs',
      // APP
      'apps/:id(/)': 'category',
      //THEME
      'themes/:id(/)': 'tag',
      // POST
      'gfw/:id' : 'post',
      'climate/:id' : 'post',
      'fires/:id' : 'post',
      'commodities/:id' : 'post',

    },

    ParamsModel: Backbone.Model.extend({}),

    initialize: function(settings) {
      var opts = settings && settings.options ? settings.options : {};
      this.options = _.extend({}, this.defaults, opts);

      this.params = new this.ParamsModel(); // This object save the URL params
    },

    /**
     * Set params and update model
     * @param {String} name
     * @param {String|Object|Array} value
     * @param {Array[String]} keys
     */
    setParams: function(name, value, keys) {
      if (typeof value === 'string' || typeof value === 'number') {
        this.params.set(name, value);
      } else if (typeof value === 'object' && !_.isArray(value)) {
        if (keys && _.isArray(keys)) {
          // var params = _.pick(value, 'id', 'opacity', 'order');
          // this.params.set(name, JSON.stringify(params));
        } else {
          this.params.set(name, JSON.stringify(value));
        }
      } else if (typeof value === 'object' && _.isArray(value)) {
        if (keys && _.isArray(keys)) {
          var params = _.map(value, function(v) {
            return _.pick(v, keys);
          });
          this.params.set(name, JSON.stringify(params));
        } else {
          this.params.set(name, JSON.stringify(value));
        }
      }
    },

    /**
     * Change url with params
     */
    updateUrl: function() {
      var url = location.pathname.slice(1) + '?' + this._serializeParams();
      this.navigate(url, { trigger: false });
    },

    /**
     * This method will update this.params object when URL change
     * @param  {String} routeName
     * @param  {Array} params
     */
    updateParams: function(params, routeName) {
      if (this.options.decoded && params[0]) {
        try {
          params = this._decodeParams(params[0]);
        } catch(err) {
          console.error('Invalid params. ' + err);
          params = null;
          return this.navigate('map');
        }
        this.params.clear({ silent: true }).set({ config: params });
      } else {
        var p = this._unserializeParams();
        this.params.clear({ silent: true }).set(this._unserializeParams());
      }
    },

    /**
     * Transform URL string params to object
     * @return {Object}
     */
    _unserializeParams: function() {
      var params = {};
      if (location.search.length) {
        var paramsArr = decodeURIComponent(location.search.slice(1)).split('&'),
          temp = [];
        for (var p = paramsArr.length; p--;) {
          temp = paramsArr[p].split('=');
          if (temp[1] && !_.isNaN(Number(temp[1]))) {
            params[temp[0]] = Number(temp[1]);
          } else if (temp[1]) {
            params[temp[0]] = temp[1];
          }
        }
      }
      return params;
    },

    /**
     * Transform object params to URL string
     * @return {String}
     */
    _serializeParams: function() {
      return this.params ? $.param(this.params.attributes) : null;
    }

  });

})(this);
<commit_msg>routing odp post<commit_after>(function(root) {

  'use strict';

  root.app = root.app || {};

  root.app.Router = Backbone.Router.extend({

    routes: {
      // HOME
      '': 'home',
      // HOME
      'faqs(/)': 'faqs',
      // APP
      'apps/:id(/)': 'category',
      //THEME
      'themes/:id(/)': 'tag',
      // POST
      'gfw/:id' : 'post',
      'climate/:id' : 'post',
      'fires/:id' : 'post',
      'commodities/:id' : 'post',
      'odp/:id': 'post'
    },

    ParamsModel: Backbone.Model.extend({}),

    initialize: function(settings) {
      var opts = settings && settings.options ? settings.options : {};
      this.options = _.extend({}, this.defaults, opts);

      this.params = new this.ParamsModel(); // This object save the URL params
    },

    /**
     * Set params and update model
     * @param {String} name
     * @param {String|Object|Array} value
     * @param {Array[String]} keys
     */
    setParams: function(name, value, keys) {
      if (typeof value === 'string' || typeof value === 'number') {
        this.params.set(name, value);
      } else if (typeof value === 'object' && !_.isArray(value)) {
        if (keys && _.isArray(keys)) {
          // var params = _.pick(value, 'id', 'opacity', 'order');
          // this.params.set(name, JSON.stringify(params));
        } else {
          this.params.set(name, JSON.stringify(value));
        }
      } else if (typeof value === 'object' && _.isArray(value)) {
        if (keys && _.isArray(keys)) {
          var params = _.map(value, function(v) {
            return _.pick(v, keys);
          });
          this.params.set(name, JSON.stringify(params));
        } else {
          this.params.set(name, JSON.stringify(value));
        }
      }
    },

    /**
     * Change url with params
     */
    updateUrl: function() {
      var url = location.pathname.slice(1) + '?' + this._serializeParams();
      this.navigate(url, { trigger: false });
    },

    /**
     * This method will update this.params object when URL change
     * @param  {String} routeName
     * @param  {Array} params
     */
    updateParams: function(params, routeName) {
      if (this.options.decoded && params[0]) {
        try {
          params = this._decodeParams(params[0]);
        } catch(err) {
          console.error('Invalid params. ' + err);
          params = null;
          return this.navigate('map');
        }
        this.params.clear({ silent: true }).set({ config: params });
      } else {
        var p = this._unserializeParams();
        this.params.clear({ silent: true }).set(this._unserializeParams());
      }
    },

    /**
     * Transform URL string params to object
     * @return {Object}
     */
    _unserializeParams: function() {
      var params = {};
      if (location.search.length) {
        var paramsArr = decodeURIComponent(location.search.slice(1)).split('&'),
          temp = [];
        for (var p = paramsArr.length; p--;) {
          temp = paramsArr[p].split('=');
          if (temp[1] && !_.isNaN(Number(temp[1]))) {
            params[temp[0]] = Number(temp[1]);
          } else if (temp[1]) {
            params[temp[0]] = temp[1];
          }
        }
      }
      return params;
    },

    /**
     * Transform object params to URL string
     * @return {String}
     */
    _serializeParams: function() {
      return this.params ? $.param(this.params.attributes) : null;
    }

  });

})(this);
<|endoftext|>


<commit_before>
/*!--------------------------------*\
   3-Jekyll Theme
   @author Peiwen Lu (P233)
   https://github.com/P233/3-Jekyll
\*---------------------------------*/

// Detect window size, if less than 1280px add class 'mobile' to sidebar therefore it will be auto hide when trigger the pjax request in small screen devices.
if ($(window).width() <= 1280) {
  $('#sidebar').addClass('mobile')
}

// Variables
    tag1       = $('.pl_all'),
    tag2       = $('.one'),
    tag3       = $('.two'),
    tag4       = $('.thr'),
    tag5       = $('.fou'),
    tag6       = $('.fiv');
var sidebar    = $('#sidebar'),
    container  = $('#post'),
    content    = $('#pjax'),
    button     = $('#icon-arrow');

// Tags switcher
var clickHandler = function(k) {
  return function() {
    $(this).addClass('active').siblings().removeClass('active');
    tag1.hide();
    window['tag'+k].delay(50).fadeIn(350);
  }
};
for (var i = 1; i <= 6; i++) {
  $('#js-label' + i).on('click', clickHandler(i));
}

// If sidebar has class 'mobile', hide it after clicking.
tag1.on('click', function() {
  $(this).addClass('active').siblings().removeClass('active');
  if (sidebar.hasClass('mobile')) {
    $('#sidebar, #pjax, #icon-arrow').addClass('fullscreen');
  }
});

// Enable fullscreen.
$('#js-fullscreen').on('click', function() {
  if (button.hasClass('fullscreen')) {
    sidebar.removeClass('fullscreen');
    button.removeClass('fullscreen');
    content.delay(300).queue(function(){
      $(this).removeClass('fullscreen').dequeue();
    });
  } else {
    sidebar.addClass('fullscreen');
    button.addClass('fullscreen');
    content.delay(200).queue(function(){
      $(this).addClass('fullscreen').dequeue();
    });
  }
});

$('#mobile-avatar').on('click', function(){
  $('#sidebar, #pjax, #icon-arrow').addClass('fullscreen');
});

// Pjax
$(document).pjax('#avatar, #mobile-avatar, .pl__all', '#pjax', { fragment: '#pjax', timeout: 10000 });
$(document).on({
  'pjax:click': function() {
    content.removeClass('fadeIn').addClass('fadeOut');
    NProgress.start();
  },
  'pjax:start': function() {
    content.css({'opacity':0});
  },
  'pjax:end': function() {
    NProgress.done();
    container.scrollTop(0);
    content.css({'opacity':1}).removeClass('fadeOut').addClass('fadeIn');
    afterPjax();
  }
});

// Codepen embed js
// http://codepen.io/assets/embed/ei.js
// Added on 17 Nov 2013
var CodePenEmbed={width:"100%",init:function(){this.showCodePenEmbeds(),this.listenToParentPostMessages()},showCodePenEmbeds:function(){var e=document.getElementsByClassName("codepen");for(var t=e.length-1;t>-1;t--){var n=this._getParamsFromAttributes(e[t]);n=this._convertOldDataAttributesToNewDataAttributes(n);var r=this._buildURL(n),i=this._buildIFrame(n,r);this._addIFrameToPage(e[t],i)}},_getParamsFromAttributes:function(e){var t={},n=e.attributes;for(var r=0,i=n.length;r<i;r++)name=n[r].name,name.indexOf("data-")===0&&(t[name.replace("data-","")]=n[r].value);return t},_convertOldDataAttributesToNewDataAttributes:function(e){return e.href&&(e["slug-hash"]=e.href),e.type&&(e["default-tab"]=e.type),e.safe&&(e["safe"]=="true"?e.animations="run":e.animations="stop-after-5"),e},_buildURL:function(e){var t=this._getHost(e),n=e.user?e.user:"anon",r="?"+this._getGetParams(e),i=[t,n,"embed",e["slug-hash"]+r].join("/");return i.replace(/\/\//g,"//")},_getHost:function(e){return e.host?e.host:document.location.protocol=="file:"?"http://codepen.io":"//codepen.io"},_getGetParams:function(e){var t="",n=0;for(var r in e)t!==""&&(t+="&"),t+=r+"="+encodeURIComponent(e[r]);return t},_buildIFrame:function(e,t){var n={id:"cp_embed_"+e["slug-hash"].replace("/","_"),src:t,scrolling:"no",frameborder:"0",height:this._getHeight(e),allowTransparency:"true","class":"cp_embed_iframe",style:"width: "+this.width+"; overflow: hidden;"},r="",r},_getHeight:function(e){return e.height?e["height"]=="auto"?300:e.height:300},_addIFrameToPage:function(e,t){if(e.parentNode){var n=document.createElement("div");n.innerHTML=t,e.parentNode.replaceChild(n,e)}else e.innerHTML=t},listenToParentPostMessages:function(){var eventMethod=window.addEventListener?"addEventListener":"attachEvent",eventListener=window[eventMethod],messageEvent=eventMethod=="attachEvent"?"onmessage":"message";eventListener(messageEvent,function(e){try{var dataObj=eval("("+e.data+")"),iframe=document.getElementById("cp_embed_"+dataObj.hash);iframe&&(iframe.height=dataObj.height)}catch(err){}},!1)}};

// Re-run scripts for post content after pjax
function afterPjax() {
  // Open links in new tab
  $('#post__content a').attr('target','_blank');

  // Embed codepen after pjax
  CodePenEmbed.init();

  // Generate post TOC for h1 h2 and h3
  var toc = $('#post__toc-ul');
  // Empty TOC and generate an entry for h1
  toc.empty().append('
' + $('#post__title').text() + '
');

  // Generate entries for h2 and h3
  $('#post__content').children('h2,h3').each(function() {
    // Generate random ID for each heading
    $(this).attr('id', function() {
      var ID = "",
          alphabet = "abcdefghijklmnopqrstuvwxyz";

      for(var i=0; i < 5; i++) {
        ID += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
      }
      return ID;
    });

    if ($(this).prop("tagName") == 'H2') {
      toc.append('
' + $(this).text() + '
');
    } else {
      toc.append('
' + $(this).text() + '
');
    }
  });

  // Smooth scrolling
  $('.js-anchor-link').on('click', function() {
    var target = $(this.hash);
    container.animate({scrollTop: target.offset().top + container.scrollTop() - 70}, 500, function() {
      target.addClass('flash').delay(700).queue(function() {
        $(this).removeClass('flash').dequeue();
      });
    });
  });

  // Lazy Loading Disqus
  // http://jsfiddle.net/dragoncrew/SHGwe/1/
  var ds_loaded = false,
      top = $('#disqus_thread').offset().top;
      identifier = $('#post__title').data('identifier');
  window.disqus_shortname = '';
  window.disqus_identifier = identifier;

  function check() {
    if ( !ds_loaded && container.scrollTop() + container.height() > top ) {
      $.ajax({
        type: 'GET',
        url: 'http://' + disqus_shortname + '.disqus.com/embed.js',
        dataType: 'script',
        cache: true
      });
      ds_loaded = true;
    }
  }check();
  container.scroll(check);
}afterPjax();

<commit_msg>change content test html<commit_after>
/*!--------------------------------*\
   3-Jekyll Theme
   @author Peiwen Lu (P233)
   https://github.com/P233/3-Jekyll
\*---------------------------------*/

// Detect window size, if less than 1280px add class 'mobile' to sidebar therefore it will be auto hide when trigger the pjax request in small screen devices.
if ($(window).width() <= 1280) {
  $('#sidebar').addClass('mobile')
}

// Variables
    tag1       = $('.pl__all'),
    tag2       = $('.one'),
    tag3       = $('.two'),
    tag4       = $('.thr'),
    tag5       = $('.fou'),
    tag6       = $('.fiv');
var sidebar    = $('#sidebar'),
    container  = $('#post'),
    content    = $('#pjax'),
    button     = $('#icon-arrow');

// Tags switcher
var clickHandler = function(k) {
  return function() {
    $(this).addClass('active').siblings().removeClass('active');
    tag1.hide();
    window['tag'+k].delay(50).fadeIn(350);
  }
};
for (var i = 1; i <= 6; i++) {
  $('#js-label' + i).on('click', clickHandler(i));
}

// If sidebar has class 'mobile', hide it after clicking.
tag1.on('click', function() {
  $(this).addClass('active').siblings().removeClass('active');
  if (sidebar.hasClass('mobile')) {
    $('#sidebar, #pjax, #icon-arrow').addClass('fullscreen');
  }
});

// Enable fullscreen.
$('#js-fullscreen').on('click', function() {
  if (button.hasClass('fullscreen')) {
    sidebar.removeClass('fullscreen');
    button.removeClass('fullscreen');
    content.delay(300).queue(function(){
      $(this).removeClass('fullscreen').dequeue();
    });
  } else {
    sidebar.addClass('fullscreen');
    button.addClass('fullscreen');
    content.delay(200).queue(function(){
      $(this).addClass('fullscreen').dequeue();
    });
  }
});

$('#mobile-avatar').on('click', function(){
  $('#sidebar, #pjax, #icon-arrow').addClass('fullscreen');
});

// Pjax
$(document).pjax('#avatar, #mobile-avatar, .pl__all', '#pjax', { fragment: '#pjax', timeout: 10000 });
$(document).on({
  'pjax:click': function() {
    content.removeClass('fadeIn').addClass('fadeOut');
    NProgress.start();
  },
  'pjax:start': function() {
    content.css({'opacity':0});
  },
  'pjax:end': function() {
    NProgress.done();
    container.scrollTop(0);
    content.css({'opacity':1}).removeClass('fadeOut').addClass('fadeIn');
    afterPjax();
  }
});

// Codepen embed js
// http://codepen.io/assets/embed/ei.js
// Added on 17 Nov 2013
var CodePenEmbed={width:"100%",init:function(){this.showCodePenEmbeds(),this.listenToParentPostMessages()},showCodePenEmbeds:function(){var e=document.getElementsByClassName("codepen");for(var t=e.length-1;t>-1;t--){var n=this._getParamsFromAttributes(e[t]);n=this._convertOldDataAttributesToNewDataAttributes(n);var r=this._buildURL(n),i=this._buildIFrame(n,r);this._addIFrameToPage(e[t],i)}},_getParamsFromAttributes:function(e){var t={},n=e.attributes;for(var r=0,i=n.length;r<i;r++)name=n[r].name,name.indexOf("data-")===0&&(t[name.replace("data-","")]=n[r].value);return t},_convertOldDataAttributesToNewDataAttributes:function(e){return e.href&&(e["slug-hash"]=e.href),e.type&&(e["default-tab"]=e.type),e.safe&&(e["safe"]=="true"?e.animations="run":e.animations="stop-after-5"),e},_buildURL:function(e){var t=this._getHost(e),n=e.user?e.user:"anon",r="?"+this._getGetParams(e),i=[t,n,"embed",e["slug-hash"]+r].join("/");return i.replace(/\/\//g,"//")},_getHost:function(e){return e.host?e.host:document.location.protocol=="file:"?"http://codepen.io":"//codepen.io"},_getGetParams:function(e){var t="",n=0;for(var r in e)t!==""&&(t+="&"),t+=r+"="+encodeURIComponent(e[r]);return t},_buildIFrame:function(e,t){var n={id:"cp_embed_"+e["slug-hash"].replace("/","_"),src:t,scrolling:"no",frameborder:"0",height:this._getHeight(e),allowTransparency:"true","class":"cp_embed_iframe",style:"width: "+this.width+"; overflow: hidden;"},r="",r},_getHeight:function(e){return e.height?e["height"]=="auto"?300:e.height:300},_addIFrameToPage:function(e,t){if(e.parentNode){var n=document.createElement("div");n.innerHTML=t,e.parentNode.replaceChild(n,e)}else e.innerHTML=t},listenToParentPostMessages:function(){var eventMethod=window.addEventListener?"addEventListener":"attachEvent",eventListener=window[eventMethod],messageEvent=eventMethod=="attachEvent"?"onmessage":"message";eventListener(messageEvent,function(e){try{var dataObj=eval("("+e.data+")"),iframe=document.getElementById("cp_embed_"+dataObj.hash);iframe&&(iframe.height=dataObj.height)}catch(err){}},!1)}};

// Re-run scripts for post content after pjax
function afterPjax() {
  // Open links in new tab
  $('#post__content a').attr('target','_blank');

  // Embed codepen after pjax
  CodePenEmbed.init();

  // Generate post TOC for h1 h2 and h3
  var toc = $('#post__toc-ul');
  // Empty TOC and generate an entry for h1
  toc.empty().append('
' + $('#post__title').text() + '
');

  // Generate entries for h2 and h3
  $('#post__content').children('h2,h3').each(function() {
    // Generate random ID for each heading
    $(this).attr('id', function() {
      var ID = "",
          alphabet = "abcdefghijklmnopqrstuvwxyz";

      for(var i=0; i < 5; i++) {
        ID += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
      }
      return ID;
    });

    if ($(this).prop("tagName") == 'H2') {
      toc.append('
' + $(this).text() + '
');
    } else {
      toc.append('
' + $(this).text() + '
');
    }
  });

  // Smooth scrolling
  $('.js-anchor-link').on('click', function() {
    var target = $(this.hash);
    container.animate({scrollTop: target.offset().top + container.scrollTop() - 70}, 500, function() {
      target.addClass('flash').delay(700).queue(function() {
        $(this).removeClass('flash').dequeue();
      });
    });
  });

  // Lazy Loading Disqus
  // http://jsfiddle.net/dragoncrew/SHGwe/1/
  var ds_loaded = false,
      top = $('#disqus_thread').offset().top;
      identifier = $('#post__title').data('identifier');
  window.disqus_shortname = '';
  window.disqus_identifier = identifier;

  function check() {
    if ( !ds_loaded && container.scrollTop() + container.height() > top ) {
      $.ajax({
        type: 'GET',
        url: 'http://' + disqus_shortname + '.disqus.com/embed.js',
        dataType: 'script',
        cache: true
      });
      ds_loaded = true;
    }
  }check();
  container.scroll(check);
}afterPjax();

<|endoftext|>


<commit_before>/**
 * Author: whizkydee(Olaolu Olawuyi)

 * Date Created: 20/08/2015

 * Last Modified: 12/12/2015

 * Twitter: @whizkydee, @webtwic

 * Blog: http://whizkydee.tumblr.com

 * Github: https://github.com/whizkydee/webtwic

*/

var s;
s = $(window).scrollTop();

jQuery(document).ready(function() {

	// Define Variables
	var is_DisabledFeatures = $("div").hasClass("dfvisible"), img = $("img"), is_noAlt = img.attr("alt", null), scripts = $("script"), is_noType = scripts.attr("type", null), is_noCharset = scripts.attr("charset", null);

	var $to_top = $("a.to-top"), is_toggle_active = $(".hamburger").hasClass("is_active"), height = 200;

	// Performance Fixes

	// Start Performance Functions

	function addAlt() {
		$(img, this).attr("alt", "...");
	}

	function addCharset() {
		$(scripts, this).attr("charset", "utf-8");
	}

	function addType() {
		$(scripts, this).attr("type", "text/javascript");
	}

	if(is_noAlt) {
		addAlt();
	} else {
		return img.attr("alt");
	}

	if(is_noCharset) {
		addCharset();
	} else {
		return scripts.attr("charset");
	}

	if(is_noType) {
		addType();
	} else {
		return scripts.attr("type");
	}

	// Notification for disabled features
	function showDisabledFeatures() {
		$(".top-stripe").before(
			"
Certain features which affect the functionality of webtwic are disabled in your browser. Please try refreshing the page or get a better browser.
"
		);
		$(".close-button").on("click",
			function() {
				hideDisabledFeatures();
				undoSiteAdjust();
			});
	}

	function hideDisabledFeatures() {
		$("#disabledFeatures").removeClass("dfvisible");
	}
	function adjustSiteContent() {
		$(".top-stripe").addClass("adjustedMargin");
		$("#header .logo").addClass("adjustedTop");
		$(".main-menu").addClass("adjustedMargin");
		$("#header").addClass("adjustSiteContent");
	}
	function undoSiteAdjust() {
		$(".top-stripe").removeClass("adjustedMargin");
		$("#header .logo").removeClass("adjustedTop");
		$(".main-menu").removeClass("adjustedMargin");
		$("#header").removeClass("adjustSiteContent");
	}

	// Modernizr funnctions

	function resetSite() {
		showDisabledFeatures();
		adjustSiteContent();
	}

	function undoReset() {
		hideDisabledFeatures();
		undoSiteAdjust();
	}

	if (!Modernizr.flexbox || !Modernizr.inlinesvg || !Modernizr.svg || !Modernizr.svgclippaths || !Modernizr.fontface || !Modernizr.boxshadow || !Modernizr.borderradius || !Modernizr.csstransforms) {
		resetSite();
	} else {
		undoReset();
	}

	// Start Main Page

	$("nav li ul.drop-nav").hide().removeClass("dropNavFallback");

	if ( $(window).width() > 860 ) {
		$("nav li.dropdown").hover(function() {
			$("ul.drop-nav", this).stop().slideDown("fast");
		}, function() {
			$("ul.drop-nav", this).stop().slideUp("fast");
		});
	}

	$(".active-menu").append(
		"<svg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><path d='M 16.682,19.674c 0.010-0.012, 0.014-0.028, 0.024-0.040l 6.982-7.714c 0.39-0.434, 0.39-1.138,0-1.572 c-0.004-0.004-0.008-0.006-0.012-0.008C 23.496,10.13, 23.244,10, 22.964,10L 8.998,10 c-0.286,0-0.54,0.138-0.722,0.352L 8.272,10.348 c-0.39,0.434-0.39,1.138,0,1.572l 6.998,7.754C 15.66,20.108, 16.292,20.108, 16.682,19.674z'></path></svg>"
	);

	$("a.hamburger").click(function(e) {
		$(this).toggleClass("is_active");
		$("nav ul").stop().slideToggle(200);

		e.preventDefault();
	});

	$(window).scroll(function() {
		($(this).scrollTop() > height) ? $to_top.addClass("topVisible"): $to_top.removeClass("topVisible");
	});

	// Styles for homepage article-social

	$(".article .article-social a").hover(function() {
		$("span", this).eq(1).fadeIn(400);
	}, function() {
		$("span", this).eq(1).fadeOut(250);
	});

	// Functions for search-icon and ui-overlay-search
	$(".header-follow-search .search-wrap").on("click", function() {
		openUiOverlay();
	});

	$(".header-follow-search .close-icon").on("click", function() {
		closeUiOverlay();
	});

	function openUiOverlay() {
		$(".ui-overlay-search").fadeIn(400).addClass("is_open");
	}

	function closeUiOverlay() {
		$(".ui-overlay-search").fadeOut(400).removeClass("is_open");
	}

	$(".ui-overlay-search .search-input input").focus(function() {
		$(".search-input").attr("data-focused", true);
		$(".search-input input").addClass("_is-focused");
		$("#__expand").addClass("visible");
	});

	$(".ui-overlay-search .search-input input").blur(function() {
		$(".search-input").attr("data-focused", false);
		$(".search-input input").removeClass("_is-focused");
		$("#__expand").removeClass("visible");
	});

	$(".post-meta .post-meta-inner .cta-btns a.is_inactive").on("click", function(e) {
		e.preventDefault();
	});

	$(document).keydown(function(e) {
    if (e.keyCode == 27) {
        closeUiOverlay();
    } else {
		 return;
	 }});

	$to_top.on("click", function(e) {
		$("body,html").animate({
			scrollTop: 0
		}, 1000);

		e.preventDefault();
	});

});
<commit_msg>Update variables<commit_after>/**
 * Author: whizkydee(Olaolu Olawuyi)

 * Date Created: 20/08/2015

 * Last Modified: 12/12/2015

 * Twitter: @whizkydee, @webtwic

 * Blog: http://whizkydee.tumblr.com

 * Github: https://github.com/whizkydee/webtwic

*/

var s;
s = $(window).scrollTop();

jQuery(document).ready(function() {

	// Define Variables
	var is_DisabledFeatures = $("div").hasClass("dfvisible"),
	img = $("img"),
	is_noAlt = img.attr("alt", null),
	scripts = $("script"),
	is_noType = scripts.attr("type", null),
	is_noCharset = scripts.attr("charset", null);

	var $to_top = $("a.to-top"),
	is_toggle_active = $(".hamburger").hasClass("is_active"),
	height = 200;

	// Performance Fixes

	// Start Performance Functions

	function addAlt() {
		$(img, this).attr("alt", "...");
	}

	function addCharset() {
		$(scripts, this).attr("charset", "utf-8");
	}

	function addType() {
		$(scripts, this).attr("type", "text/javascript");
	}

	if(is_noAlt) {
		addAlt();
	} else {
		return img.attr("alt");
	}

	if(is_noCharset) {
		addCharset();
	} else {
		return scripts.attr("charset");
	}

	if(is_noType) {
		addType();
	} else {
		return scripts.attr("type");
	}

	// Notification for disabled features
	function showDisabledFeatures() {
		$(".top-stripe").before(
			"
Certain features which affect the functionality of webtwic are disabled in your browser. Please try refreshing the page or get a better browser.
"
		);
		$(".close-button").on("click",
			function() {
				hideDisabledFeatures();
				undoSiteAdjust();
			});
	}

	function hideDisabledFeatures() {
		$("#disabledFeatures").removeClass("dfvisible");
	}
	function adjustSiteContent() {
		$(".top-stripe").addClass("adjustedMargin");
		$("#header .logo").addClass("adjustedTop");
		$(".main-menu").addClass("adjustedMargin");
		$("#header").addClass("adjustSiteContent");
	}
	function undoSiteAdjust() {
		$(".top-stripe").removeClass("adjustedMargin");
		$("#header .logo").removeClass("adjustedTop");
		$(".main-menu").removeClass("adjustedMargin");
		$("#header").removeClass("adjustSiteContent");
	}

	// Modernizr funnctions

	function resetSite() {
		showDisabledFeatures();
		adjustSiteContent();
	}

	function undoReset() {
		hideDisabledFeatures();
		undoSiteAdjust();
	}

	if (!Modernizr.flexbox || !Modernizr.inlinesvg || !Modernizr.svg || !Modernizr.svgclippaths || !Modernizr.fontface || !Modernizr.boxshadow || !Modernizr.borderradius || !Modernizr.csstransforms) {
		resetSite();
	} else {
		undoReset();
	}

	// Start Main Page

	$("nav li ul.drop-nav").hide().removeClass("dropNavFallback");

	if ( $(window).width() > 860 ) {
		$("nav li.dropdown").hover(function() {
			$("ul.drop-nav", this).stop().slideDown("fast");
		}, function() {
			$("ul.drop-nav", this).stop().slideUp("fast");
		});
	}

	$(".active-menu").append(
		"<svg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><path d='M 16.682,19.674c 0.010-0.012, 0.014-0.028, 0.024-0.040l 6.982-7.714c 0.39-0.434, 0.39-1.138,0-1.572 c-0.004-0.004-0.008-0.006-0.012-0.008C 23.496,10.13, 23.244,10, 22.964,10L 8.998,10 c-0.286,0-0.54,0.138-0.722,0.352L 8.272,10.348 c-0.39,0.434-0.39,1.138,0,1.572l 6.998,7.754C 15.66,20.108, 16.292,20.108, 16.682,19.674z'></path></svg>"
	);

	$("a.hamburger").click(function(e) {
		$(this).toggleClass("is_active");
		$("nav ul").stop().slideToggle(200);

		e.preventDefault();
	});

	$(window).scroll(function() {
		($(this).scrollTop() > height) ? $to_top.addClass("topVisible"): $to_top.removeClass("topVisible");
	});

	// Styles for homepage article-social

	$(".article .article-social a").hover(function() {
		$("span", this).eq(1).fadeIn(400);
	}, function() {
		$("span", this).eq(1).fadeOut(250);
	});

	// Functions for search-icon and ui-overlay-search
	$(".header-follow-search .search-wrap").on("click", function() {
		openUiOverlay();
	});

	$(".header-follow-search .close-icon").on("click", function() {
		closeUiOverlay();
	});

	function openUiOverlay() {
		$(".ui-overlay-search").fadeIn(400).addClass("is_open");
	}

	function closeUiOverlay() {
		$(".ui-overlay-search").fadeOut(400).removeClass("is_open");
	}

	$(".ui-overlay-search .search-input input").focus(function() {
		$(".search-input").attr("data-focused", true);
		$(".search-input input").addClass("_is-focused");
		$("#__expand").addClass("visible");
	});

	$(".ui-overlay-search .search-input input").blur(function() {
		$(".search-input").attr("data-focused", false);
		$(".search-input input").removeClass("_is-focused");
		$("#__expand").removeClass("visible");
	});

	$(".post-meta .post-meta-inner .cta-btns a.is_inactive").on("click", function(e) {
		e.preventDefault();
	});

	$(document).keydown(function(e) {
    if (e.keyCode == 27) {
        closeUiOverlay();
    } else {
		 return;
	 }});

	$to_top.on("click", function(e) {
		$("body,html").animate({
			scrollTop: 0
		}, 1000);

		e.preventDefault();
	});

});
<|endoftext|>


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

  toSection(".section_welcome")

  $("body").css("height",$(window).innerHeight())
  $(".main_content_top").css("height",$(window).innerHeight()/2-$(".main_keyslider").height()/2)
  $(".main_content_bottom").css("height",$(window).innerHeight()/2-$(".main_keyslider").height()/2)
  $(".main_content_top_label").css("margin-top", $(".header").height())

  //
  // Crypt & decrypt
  //
  var emoji_list = ['😹','😤','😐','😖','😀','😻','😕','🙍','😠','😨','😘','😇','😄','😂']
  _.each(emoji_list, function(d){
    $(".keyslider_content").append('
'+d+'
')
  })
  $('.main_content_top_input').bind('input propertychange', function() {
    var text = $('.main_content_top_input').val()
    $('.main_content_bottom_input').text(Criptoloji.encrypt(text))
  })
  $('.key').click(function(){
    var text = $('.main_content_top_input').val()
    var key = $(this).attr('key')
    Criptoloji.key = key
    console.log('Chosen key', key)
    $('.main_content_bottom_input').text(Criptoloji.encrypt(text))
  })
})

function toSection(button){
  $(".section").hide()
  $(button).show()
}

//
// Key Slider
//
function keysliderGoto(toElem, elementWidth) {
  $('.keyslider').animate({scrollLeft: toElem*elementWidth}, 200)
}
var debouncedKeysliderGoto = _.debounce(keysliderGoto, 200)
var lastPos = 0
var $wrapper = $('.keyslider')
$('.keyslider').scroll(function (event) {
  // debugger;
  var elementWidth = $('.key:nth-child(1)', $wrapper).outerWidth(true)
  console.log('elwidth', elementWidth)
  var currPos = $wrapper.scrollLeft()
  var direction = (currPos > lastPos) ? 'right' : 'left'
  console.log('keyslider direction: ' + direction)
  // calculate proper slide to element
  var toElem = (currPos / elementWidth)
  var rightThreshold = 0.5
  var leftThreshold = 0.75
  var decimal = (toElem % 1).toFixed(1)
  console.log(toElem, decimal)
  if (direction === 'right' && decimal > rightThreshold)
    toElem += 1
  if (direction === 'left' && decimal > 0 && decimal < leftThreshold)
    toElem -= 1
  toElem = Math.ceil(toElem)
  console.log('keyslider goTo', toElem)
  debouncedKeysliderGoto(toElem, elementWidth)
  lastPos = currPos
});
<commit_msg>more emoji for testing<commit_after> $(document).ready(function(){

  toSection(".section_welcome")

  $("body").css("height",$(window).innerHeight())
  $(".main_content_top").css("height",$(window).innerHeight()/2-$(".main_keyslider").height()/2)
  $(".main_content_bottom").css("height",$(window).innerHeight()/2-$(".main_keyslider").height()/2)
  $(".main_content_top_label").css("margin-top", $(".header").height())

  //
  // Crypt & decrypt
  //
  var emoji_list = ['😹','😤','😐','😖','😀','😻','😕','🙍','😠','😨','😘','😇','😄','😂','😹','😤','😐','😖','😀','😻','😕','🙍','😠','😨','😘','😇','😄','😂']
  _.each(emoji_list, function(d){
    $(".keyslider_content").append('
'+d+'
')
  })
  $('.main_content_top_input').bind('input propertychange', function() {
    var text = $('.main_content_top_input').val()
    $('.main_content_bottom_input').text(Criptoloji.encrypt(text))
  })
  $('.key').click(function(){
    var text = $('.main_content_top_input').val()
    var key = $(this).attr('key')
    Criptoloji.key = key
    console.log('Chosen key', key)
    $('.main_content_bottom_input').text(Criptoloji.encrypt(text))
  })
})

function toSection(button){
  $(".section").hide()
  $(button).show()
}

//
// Key Slider
//
function keysliderGoto(toElem, elementWidth) {
  $('.keyslider').animate({scrollLeft: toElem*elementWidth}, 200)
}
var debouncedKeysliderGoto = _.debounce(keysliderGoto, 200)
var lastPos = 0
var $wrapper = $('.keyslider')
$('.keyslider').scroll(function (event) {
  // debugger;
  var elementWidth = $('.key:nth-child(1)', $wrapper).outerWidth(true)
  console.log('elwidth', elementWidth)
  var currPos = $wrapper.scrollLeft()
  var direction = (currPos > lastPos) ? 'right' : 'left'
  console.log('keyslider direction: ' + direction)
  // calculate proper slide to element
  var toElem = (currPos / elementWidth)
  var rightThreshold = 0.5
  var leftThreshold = 0.75
  var decimal = (toElem % 1).toFixed(1)
  console.log(toElem, decimal)
  if (direction === 'right' && decimal > rightThreshold)
    toElem += 1
  if (direction === 'left' && decimal > 0 && decimal < leftThreshold)
    toElem -= 1
  toElem = Math.ceil(toElem)
  console.log('keyslider goTo', toElem)
  debouncedKeysliderGoto(toElem, elementWidth)
  lastPos = currPos
});
<|endoftext|>


<commit_before>$(function(){

	var note = $('#note'),
		ts = new Date(2016,11 ,25),
		Tobys = true;

	if((new Date()) > ts){
		// The new year is here! Count towards something else.
		// Notice the *1000 at the end - time must be in milliseconds
		ts = (new Date()).getTime() + 10*24*60*60*1000;
		newYear = false;
	}

	$('#countdown').countdown({
		timestamp	: ts,
		callback	: function(days, hours, minutes, seconds){

			var message = "";

			message += days + " day" + ( days==1 ? '':'s' ) + ", ";
			message += hours + " hour" + ( hours==1 ? '':'s' ) + ", ";
			message += minutes + " minute" + ( minutes==1 ? '':'s' ) + " and ";
			message += seconds + " second" + ( seconds==1 ? '':'s' ) + "
";

			if(Tobys){
				message += "left until Santa visits Toby's house";
			}
			else {
				message += "left to 10 days from now!";
			}

			note.html(message);
		}
	});

});
<commit_msg>Update script.js<commit_after>$(function(){

	var note = $('#note'),
		ts = new Date(2017,11 ,25),
		Tobys = true;

	if((new Date()) > ts){
		// The new year is here! Count towards something else.
		// Notice the *1000 at the end - time must be in milliseconds
		ts = (new Date()).getTime() + 10*24*60*60*1000;
		newYear = false;
	}

	$('#countdown').countdown({
		timestamp	: ts,
		callback	: function(days, hours, minutes, seconds){

			var message = "";

			message += days + " day" + ( days==1 ? '':'s' ) + ", ";
			message += hours + " hour" + ( hours==1 ? '':'s' ) + ", ";
			message += minutes + " minute" + ( minutes==1 ? '':'s' ) + " and ";
			message += seconds + " second" + ( seconds==1 ? '':'s' ) + "
";

			if(Tobys){
				message += "left until Santa visits Toby's house";
			}
			else {
				message += "left to 10 days from now!";
			}

			note.html(message);
		}
	});

});
<|endoftext|>


<commit_before>(function ( $ ) {
	"use strict";

	$(function () {

		// catch the upvote/downvote action
		$( 'div.comment-weight-container' ).on( 'click', 'span > a', function( e ){
			e.preventDefault();
			var value = 0;
			var comment_id = $(this).data('commentId');
			if ( $(this).hasClass( 'vote-up' ) ) {
				value = 1;
			} else if( $(this).hasClass( 'vote-down' ) ) {
				value = -1;
			}

			var post = $.post( comment_popularity.ajaxurl, {action: 'comment_vote', vote: value, comment_id: comment_id, hmn_vote_nonce: comment_popularity.hmn_vote_nonce} );

			post.done( function( data ) {

				if ( data.success === false ) {
					alert( data.data.error_message );
				} else {
					// update karma
					$( 'div#comment-' + data.data.comment_id + ' span.comment-weight' ).text( data.data.weight );
				}

			});

		});

	});

}(jQuery));<commit_msg>Target specific element for the weight value<commit_after>(function ( $ ) {
	"use strict";

	$(function () {

		// catch the upvote/downvote action
		$( 'div.comment-weight-container' ).on( 'click', 'span > a', function( e ){
			e.preventDefault();
			var value = 0;
			var comment_id = $(this).data('commentId');
			if ( $(this).hasClass( 'vote-up' ) ) {
				value = 1;
			} else if( $(this).hasClass( 'vote-down' ) ) {
				value = -1;
			}

			var post = $.post( comment_popularity.ajaxurl, {action: 'comment_vote', vote: value, comment_id: comment_id, hmn_vote_nonce: comment_popularity.hmn_vote_nonce} );

			post.done( function( data ) {

				if ( data.success === false ) {
					alert( data.data.error_message );
				} else {
					// update karma
					$( '#comment-weight-value-' + data.data.comment_id ).text( data.data.weight );
				}

			});

		});

	});

}(jQuery));<|endoftext|>