<commit_before>(function () {
	var unlistenableWindowEvents = {
		click: 1,
		dblclick: 1,
		keyup: 1,
		keypress: 1,
		keydown: 1,
		mousedown: 1,
		mouseup: 1,
		mousemove: 1,
		mouseover: 1,
		mouseenter: 1,
		mouseleave: 1,
		mouseout: 1,
		storage: 1,
		storagecommit: 1,
		textinput: 1
	};

	function indexOf(array, element) {
		var
		index = -1,
		length = array.length;

		while (++index < length) {
			if (index in array && array[index] === element) {
				return index;
			}
		}

		return -1;
	}

	var existingProto = (window.Event && window.Event.prototype) || null;
	window.Event = Window.prototype.Event = function Event(type, eventInitDict) {
		if (!type) {
			throw new Error('Not enough arguments');
		}

		// Shortcut if browser supports createEvent
		if ('createEvent' in document) {
			var event = document.createEvent('Event');
			var bubbles = eventInitDict && eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
			var cancelable = eventInitDict && eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;

			event.initEvent(type, bubbles, cancelable);

			return event;
		}

		var event = document.createEventObject();

		event.type = type;
		event.bubbles = eventInitDict && eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
		event.cancelable = eventInitDict && eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;

		return event;
	};
	if (existingProto) {
		Object.defineProperty(window.Event, 'prototype', {
			configurable: false,
			enumerable: false,
			writable: true,
			value: existingProto
		});
	}

	if (!('createEvent' in document)) {
		window.addEventListener = Window.prototype.addEventListener = Document.prototype.addEventListener = Element.prototype.addEventListener = function addEventListener() {
			var
			element = this,
			type = arguments[0],
			listener = arguments[1];

			if (element === window && type in unlistenableWindowEvents) {
				throw new Error('In IE8 the event: ' + type + ' is not available on the window object. Please see https://github.com/Financial-Times/polyfill-service/issues/317 for more information.');
			}

			if (!element._events) {
				element._events = {};
			}

			if (!element._events[type]) {
				element._events[type] = function (event) {
					var
					list = element._events[event.type].list,
					events = list.slice(),
					index = -1,
					length = events.length,
					eventElement;

					event.preventDefault = function preventDefault() {
						if (event.cancelable !== false) {
							event.returnValue = false;
						}
					};

					event.stopPropagation = function stopPropagation() {
						event.cancelBubble = true;
					};

					event.stopImmediatePropagation = function stopImmediatePropagation() {
						event.cancelBubble = true;
						event.cancelImmediate = true;
					};

					event.currentTarget = element;
					event.relatedTarget = event.fromElement || null;
					event.target = event.target || event.srcElement || element;
					event.timeStamp = new Date().getTime();

					if (event.clientX) {
						event.pageX = event.clientX + document.documentElement.scrollLeft;
						event.pageY = event.clientY + document.documentElement.scrollTop;
					}

					while (++index < length && !event.cancelImmediate) {
						if (index in events) {
							eventElement = events[index];

							if (indexOf(list, eventElement) !== -1) {
								eventElement.call(element, event);
							}
						}
					}
				};

				element._events[type].list = [];

				if (element.attachEvent) {
					element.attachEvent('on' + type, element._events[type]);
				}
			}

			element._events[type].list.push(listener);
		};

		window.removeEventListener = Window.prototype.removeEventListener = Document.prototype.removeEventListener = Element.prototype.removeEventListener = function removeEventListener() {
			var
			element = this,
			type = arguments[0],
			listener = arguments[1],
			index;

			if (element._events && element._events[type] && element._events[type].list) {
				index = indexOf(element._events[type].list, listener);

				if (index !== -1) {
					element._events[type].list.splice(index, 1);

					if (!element._events[type].list.length) {
						if (element.detachEvent) {
							element.detachEvent('on' + type, element._events[type]);
						}
						delete element._events[type];
					}
				}
			}
		};

		window.dispatchEvent = Window.prototype.dispatchEvent = Document.prototype.dispatchEvent = Element.prototype.dispatchEvent = function dispatchEvent(event) {
			if (!arguments.length) {
				throw new Error('Not enough arguments');
			}

			if (!event || typeof event.type !== 'string') {
				throw new Error('DOM Events Exception 0');
			}

			var element = this, type = event.type;

			try {
				if (!event.bubbles) {
					event.cancelBubble = true;

					var cancelBubbleEvent = function (event) {
						event.cancelBubble = true;

						(element || window).detachEvent('on' + type, cancelBubbleEvent);
					};

					this.attachEvent('on' + type, cancelBubbleEvent);
				}

				this.fireEvent('on' + type, event);
			} catch (error) {
				event.target = element;

				do {
					event.currentTarget = element;

					if ('_events' in element && typeof element._events[type] === 'function') {
						element._events[type].call(element, event);
					}

					if (typeof element['on' + type] === 'function') {
						element['on' + type].call(element, event);
					}

					element = element.nodeType === 9 ? element.parentWindow : element.parentNode;
				} while (element && !event.cancelBubble);
			}

			return true;
		};
	}
})();
<commit_msg>Added callback type check in addEventListener to avoid exceptions<commit_after>(function () {
	var unlistenableWindowEvents = {
		click: 1,
		dblclick: 1,
		keyup: 1,
		keypress: 1,
		keydown: 1,
		mousedown: 1,
		mouseup: 1,
		mousemove: 1,
		mouseover: 1,
		mouseenter: 1,
		mouseleave: 1,
		mouseout: 1,
		storage: 1,
		storagecommit: 1,
		textinput: 1
	};

	function indexOf(array, element) {
		var
		index = -1,
		length = array.length;

		while (++index < length) {
			if (index in array && array[index] === element) {
				return index;
			}
		}

		return -1;
	}

	var existingProto = (window.Event && window.Event.prototype) || null;
	window.Event = Window.prototype.Event = function Event(type, eventInitDict) {
		if (!type) {
			throw new Error('Not enough arguments');
		}

		// Shortcut if browser supports createEvent
		if ('createEvent' in document) {
			var event = document.createEvent('Event');
			var bubbles = eventInitDict && eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
			var cancelable = eventInitDict && eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;

			event.initEvent(type, bubbles, cancelable);

			return event;
		}

		var event = document.createEventObject();

		event.type = type;
		event.bubbles = eventInitDict && eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
		event.cancelable = eventInitDict && eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;

		return event;
	};
	if (existingProto) {
		Object.defineProperty(window.Event, 'prototype', {
			configurable: false,
			enumerable: false,
			writable: true,
			value: existingProto
		});
	}

	if (!('createEvent' in document)) {
		window.addEventListener = Window.prototype.addEventListener = Document.prototype.addEventListener = Element.prototype.addEventListener = function addEventListener() {
			var
			element = this,
			type = arguments[0],
			listener = arguments[1];

			if (element === window && type in unlistenableWindowEvents) {
				throw new Error('In IE8 the event: ' + type + ' is not available on the window object. Please see https://github.com/Financial-Times/polyfill-service/issues/317 for more information.');
			}

			if (!element._events) {
				element._events = {};
			}

			if (!element._events[type]) {
				element._events[type] = function (event) {
					var
					list = element._events[event.type].list,
					events = list.slice(),
					index = -1,
					length = events.length,
					eventElement;

					event.preventDefault = function preventDefault() {
						if (event.cancelable !== false) {
							event.returnValue = false;
						}
					};

					event.stopPropagation = function stopPropagation() {
						event.cancelBubble = true;
					};

					event.stopImmediatePropagation = function stopImmediatePropagation() {
						event.cancelBubble = true;
						event.cancelImmediate = true;
					};

					event.currentTarget = element;
					event.relatedTarget = event.fromElement || null;
					event.target = event.target || event.srcElement || element;
					event.timeStamp = new Date().getTime();

					if (event.clientX) {
						event.pageX = event.clientX + document.documentElement.scrollLeft;
						event.pageY = event.clientY + document.documentElement.scrollTop;
					}

					while (++index < length && !event.cancelImmediate) {
						if (index in events) {
							eventElement = events[index];

							if (indexOf(list, eventElement) !== -1 && typeof eventElement === 'function') {
								eventElement.call(element, event);
							}
						}
					}
				};

				element._events[type].list = [];

				if (element.attachEvent) {
					element.attachEvent('on' + type, element._events[type]);
				}
			}

			element._events[type].list.push(listener);
		};

		window.removeEventListener = Window.prototype.removeEventListener = Document.prototype.removeEventListener = Element.prototype.removeEventListener = function removeEventListener() {
			var
			element = this,
			type = arguments[0],
			listener = arguments[1],
			index;

			if (element._events && element._events[type] && element._events[type].list) {
				index = indexOf(element._events[type].list, listener);

				if (index !== -1) {
					element._events[type].list.splice(index, 1);

					if (!element._events[type].list.length) {
						if (element.detachEvent) {
							element.detachEvent('on' + type, element._events[type]);
						}
						delete element._events[type];
					}
				}
			}
		};

		window.dispatchEvent = Window.prototype.dispatchEvent = Document.prototype.dispatchEvent = Element.prototype.dispatchEvent = function dispatchEvent(event) {
			if (!arguments.length) {
				throw new Error('Not enough arguments');
			}

			if (!event || typeof event.type !== 'string') {
				throw new Error('DOM Events Exception 0');
			}

			var element = this, type = event.type;

			try {
				if (!event.bubbles) {
					event.cancelBubble = true;

					var cancelBubbleEvent = function (event) {
						event.cancelBubble = true;

						(element || window).detachEvent('on' + type, cancelBubbleEvent);
					};

					this.attachEvent('on' + type, cancelBubbleEvent);
				}

				this.fireEvent('on' + type, event);
			} catch (error) {
				event.target = element;

				do {
					event.currentTarget = element;

					if ('_events' in element && typeof element._events[type] === 'function') {
						element._events[type].call(element, event);
					}

					if (typeof element['on' + type] === 'function') {
						element['on' + type].call(element, event);
					}

					element = element.nodeType === 9 ? element.parentWindow : element.parentNode;
				} while (element && !event.cancelBubble);
			}

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


<commit_before>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

var PlaybackPlugin = require('../../base/playback_plugin');
var Styler = require('../../base/styler');

var HTML5VideoPlaybackPlugin = PlaybackPlugin.extend({
  pluginName: 'html5_video_playback',
  attributes: {
    'data-html5-video': ''
  },
  events: {
    'timeupdate': 'timeUpdated',
    'ended': 'ended'
  },
  tagName: 'video',
  initialize: function(options) {
    this.firstPlay = true;
    this.el.src = options.src;
    this.container.settings = ['play', 'pause', 'stop', 'seekbar', 'fullscreen', 'volume'];
    this.listenTo(this.container, 'container:play', this.play);
    this.listenTo(this.container, 'container:pause', this.pause);
    this.listenTo(this.container, 'container:seek', this.seek);
    //this.listenTo(this.container, 'container:fullscreen', this.fullscreen);
    this.listenTo(this.container, 'container:volume', this.volume);
    this.listenTo(this.container, 'container:stop', this.stop);
  },
  play: function() {
    this.container.buffering();
    if(this.firstPlay) {
      this.render();
      this.$el.show();
      this.firstPlay = false;
    }
    this.el.play();
  },
  pause: function() {
    this.el.pause();
  },
  stop: function() {
    this.pause();
    this.el.currentTime = 0;
    this.firstPlay = true;
    this.$el.hide();
  },
  fullscreen: function() {
    //this is not right, the player goes fullscreen, not the playback.
    this.el.webkitRequestFullscreen();
  },
  volume: function(value) {
    this.el.volume = value / 100;
  },
  mute: function() {
    this.el.volume = 0;
  },
  unmute: function() {
    this.el.volume = 1;
  },
  isMuted: function() {
    return !!this.el.volume;
  },
  ended: function() {
    this.trigger('container:timeupdate', 0);
  },
  seek: function(seekBarValue) {
    var time = this.el.duration * (seekBarValue / 100);
    this.el.currentTime = time;
  },
  getCurrentTime: function() {
    return this.el.currentTime;
  },
  getDuration: function() {
    return this.el.duration;
  },
  timeUpdated: function() {
    var time = (100 / this.el.duration) * this.el.currentTime;
    this.container.timeUpdated(time);
  },
  render: function() {
    var style = Styler.getStyleFor(this.pluginName);
    this.container.$el.append(style);
    this.container.$el.append(this.el);
    return this;
  },
});

module.exports = HTML5VideoPlaybackPlugin;
<commit_msg>html5 video plugin: close #8<commit_after>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

var PlaybackPlugin = require('../../base/playback_plugin');
var Styler = require('../../base/styler');

var HTML5VideoPlaybackPlugin = PlaybackPlugin.extend({
  pluginName: 'html5_video_playback',
  attributes: {
    'data-html5-video': ''
  },
  events: {
    'timeupdate': 'timeUpdated',
    'ended': 'ended'
  },
  tagName: 'video',
  initialize: function(options) {
    this.firstPlay = true;
    this.el.src = options.src;
    this.container.settings = ['play', 'pause', 'stop', 'seekbar', 'fullscreen', 'volume'];
    this.listenTo(this.container, 'container:play', this.play);
    this.listenTo(this.container, 'container:pause', this.pause);
    this.listenTo(this.container, 'container:seek', this.seek);
    //this.listenTo(this.container, 'container:fullscreen', this.fullscreen);
    this.listenTo(this.container, 'container:volume', this.volume);
    this.listenTo(this.container, 'container:stop', this.stop);
    this.render();
  },
  play: function() {
    this.el.play();
  },
  pause: function() {
    this.el.pause();
  },
  stop: function() {
    this.pause();
    this.el.currentTime = 0;
  },
  fullscreen: function() {
    //this is not right, the player goes fullscreen, not the playback.
    this.el.webkitRequestFullscreen();
  },
  volume: function(value) {
    this.el.volume = value / 100;
  },
  mute: function() {
    this.el.volume = 0;
  },
  unmute: function() {
    this.el.volume = 1;
  },
  isMuted: function() {
    return !!this.el.volume;
  },
  ended: function() {
    this.trigger('container:timeupdate', 0);
  },
  seek: function(seekBarValue) {
    var time = this.el.duration * (seekBarValue / 100);
    this.el.currentTime = time;
  },
  getCurrentTime: function() {
    return this.el.currentTime;
  },
  getDuration: function() {
    return this.el.duration;
  },
  timeUpdated: function() {
    var time = (100 / this.el.duration) * this.el.currentTime;
    this.container.timeUpdated(time);
  },
  render: function() {
    var style = Styler.getStyleFor(this.pluginName);
    this.container.$el.append(style);
    this.container.$el.append(this.el);
    return this;
  },
});

module.exports = HTML5VideoPlaybackPlugin;
<|endoftext|>


<commit_before>/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

define([
    "jquery",
    "base1/cockpit",
    "storage/client",
    "storage/jobs",
    "storage/overview",
    "storage/details",
    "storage/utils",
    "translated!base1/po",
], function($, cockpit, client, jobs, overview, details, utils, po) {
    cockpit.locale(po);
    var _ = cockpit.gettext;
    var C_ = cockpit.gettext;

    /* INITIALIZATION AND NAVIGATION
     */

    function init() {
        var jobs_manager;
        var overview_page;
        var details_page;

        $('body').on('click', '[data-goto-block]', function () {
            cockpit.location.go([ $(this).attr('data-goto-block') ]);
        });

        $('body').on('click', '[data-goto-mdraid]', function () {
            cockpit.location.go([ 'mdraid', $(this).attr('data-goto-mdraid') ]);
        });

        $('body').on('click', '[data-goto-vgroup]', function () {
            cockpit.location.go([ 'vg', $(this).attr('data-goto-vgroup') ]);
        });

        function navigate() {
            var path = cockpit.location.path;

            if (path.length === 0) {
                details_page.hide();
                overview_page.show();
            } else if (path.length == 1) {
                overview_page.hide();
                details_page.show('block', path[0]);
            } else if (path.length == 2 && path[0] == 'mdraid') {
                overview_page.hide();
                details_page.show('mdraid', path[1]);
            } else if (path.length == 2 && path[0] == 'vg') {
                overview_page.hide();
                details_page.show('vgroup', path[1]);
            } else { /* redirect */
                console.warn("not a init location: " + path);
                cockpit.location = '';
            }
            $("body").show();
        }

        client.init(function () {
            cockpit.translate();
            if (client.features === false) {
                $('#unsupported').show();
                $("body").show();
            } else {
                jobs_manager = jobs.init(client);
                overview_page = overview.init(client, jobs_manager);
                details_page = details.init(client, jobs_manager);
                $(cockpit).on("locationchanged", navigate);
                navigate();
            }
        });

        // Watching multipath for brokeness

        var multipathd_service = utils.get_multipathd_service();

        function update_multipath_broken() {
            $('#multipath-broken').toggle(client.broken_multipath_present && multipathd_service.state !== "running");
        }

        $(multipathd_service).on('changed', update_multipath_broken);
        $(client).on('changed', update_multipath_broken);
        update_multipath_broken();

        $('#activate-multipath').on('click', function () {
            cockpit.spawn([ "mpathconf", "--enable", "--with_multipathd", "y" ],
                          { superuser: "try"
                          }).
                fail(function (error) {
                    $('#error-popup-title').text(_("Error"));
                    $('#error-popup-message').text(error.toString());
                    $('#error-popup').modal('show');
                });
        });
    }

    return init;
});
<commit_msg>storaged: Don't show multipath alert when state is unknown<commit_after>/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

define([
    "jquery",
    "base1/cockpit",
    "storage/client",
    "storage/jobs",
    "storage/overview",
    "storage/details",
    "storage/utils",
    "translated!base1/po",
], function($, cockpit, client, jobs, overview, details, utils, po) {
    cockpit.locale(po);
    var _ = cockpit.gettext;
    var C_ = cockpit.gettext;

    /* INITIALIZATION AND NAVIGATION
     */

    function init() {
        var jobs_manager;
        var overview_page;
        var details_page;

        $('body').on('click', '[data-goto-block]', function () {
            cockpit.location.go([ $(this).attr('data-goto-block') ]);
        });

        $('body').on('click', '[data-goto-mdraid]', function () {
            cockpit.location.go([ 'mdraid', $(this).attr('data-goto-mdraid') ]);
        });

        $('body').on('click', '[data-goto-vgroup]', function () {
            cockpit.location.go([ 'vg', $(this).attr('data-goto-vgroup') ]);
        });

        function navigate() {
            var path = cockpit.location.path;

            if (path.length === 0) {
                details_page.hide();
                overview_page.show();
            } else if (path.length == 1) {
                overview_page.hide();
                details_page.show('block', path[0]);
            } else if (path.length == 2 && path[0] == 'mdraid') {
                overview_page.hide();
                details_page.show('mdraid', path[1]);
            } else if (path.length == 2 && path[0] == 'vg') {
                overview_page.hide();
                details_page.show('vgroup', path[1]);
            } else { /* redirect */
                console.warn("not a init location: " + path);
                cockpit.location = '';
            }
            $("body").show();
        }

        client.init(function () {
            cockpit.translate();
            if (client.features === false) {
                $('#unsupported').show();
                $("body").show();
            } else {
                jobs_manager = jobs.init(client);
                overview_page = overview.init(client, jobs_manager);
                details_page = details.init(client, jobs_manager);
                $(cockpit).on("locationchanged", navigate);
                navigate();
            }
        });

        // Watching multipath for brokeness

        var multipathd_service = utils.get_multipathd_service();

        function update_multipath_broken() {
            // When in doubt, assume it is running
            var multipathd_running = !multipathd_service.state || multipathd_service.state === "running";
            $('#multipath-broken').toggle(client.broken_multipath_present && !multipathd_running);
        }

        $(multipathd_service).on('changed', update_multipath_broken);
        $(client).on('changed', update_multipath_broken);
        update_multipath_broken();

        $('#activate-multipath').on('click', function () {
            cockpit.spawn([ "mpathconf", "--enable", "--with_multipathd", "y" ],
                          { superuser: "try"
                          }).
                fail(function (error) {
                    $('#error-popup-title').text(_("Error"));
                    $('#error-popup-message').text(error.toString());
                    $('#error-popup').modal('show');
                });
        });
    }

    return init;
});
<|endoftext|>


<commit_before>var hoverZoomPlugins = hoverZoomPlugins || [];
hoverZoomPlugins.push({
    name:'clips.twitch.tv',
    prepareImgLinks:function (callback) {
        if (!options.zoomVideos) return;
        $('a[href*="clips.twitch.tv/"]').one('mouseenter', function() {
            hoverZoom.prepareFromDocument($(this), this.href, function (doc) {
                let meta = doc.querySelector('meta[property="og:image"][content]');
                return meta ? meta.content.replace('-social-preview.jpg', '.mp4') : false;
            });
        });
    }
});
<commit_msg>Fix for twitch clips<commit_after>var hoverZoomPlugins = hoverZoomPlugins || [];
hoverZoomPlugins.push({
    name:'clips.twitch.tv',
    prepareImgLinks:function (callback) {
        $('a[href*="clips.twitch.tv/"]').one('mouseenter', function() {
            if(!options.zoomVideos) return;
            var link = $(this),
                slug = this.href.replace(/.*clips.twitch.tv\/(\w+).*/, '$1');
            $.get('https://clips.twitch.tv/api/v2/clips/' + slug + '/status', function (data) {
                if (data && data.quality_options) {
                    link.data().hoverZoomSrc = [data.quality_options[0].source]
                    link.addClass('hoverZoomLink');
                    hoverZoom.displayPicFromElement(link);
                }
            });
        });
    }
});
<|endoftext|>


<commit_before>// This plugin checks for clients that talk before we sent a response

var ipaddr = require('ipaddr.js');
var isIPv6 = require('net').isIPv6;

exports.register = function() {
    var plugin = this;
    plugin.load_config();
    plugin.register_hook('connect_init', 'early_talker');
    plugin.register_hook('data',         'early_talker');
};

exports.load_config = function () {
    var plugin = this;

    plugin.cfg = plugin.config.get('early_talker.ini', {
        booleans: [
            '+main.reject'
        ]
    },
    function () {
        plugin.load_config();
    });

    // Generate a white list of IP addresses
    plugin.whitelist = plugin.load_ip_list(Object.keys(plugin.cfg.ip_whitelist));

    if (plugin.cfg.main && plugin.cfg.main.pause) {
        plugin.pause = plugin.cfg.main.pause * 1000;
        return;
    }

    // config/early_talker.pause is in milliseconds
    plugin.pause = plugin.config.get('early_talker.pause', function () {
        plugin.load_config();
    });
};

exports.early_talker = function(next, connection) {
    var plugin = this;
    if (!plugin.pause) return next();

    if (connection.relaying) {    // Don't delay AUTH/RELAY clients
        if (connection.early_talker) {
            connection.results.add(plugin, { skip: 'relay client'});
        }
        return next();
    }

    // Don't delay whitelisted IPs
    if (plugin.ip_in_list(connection.remote_ip)) { // check connecting IP
        connection.results.add(plugin, { skip: 'whitelist' });
        return next();
    }

    var check = function () {
        if (!connection) return next();
        if (!connection.early_talker) {
            connection.results.add(plugin, {pass: 'early'});
            return next();
        }
        connection.results.add(plugin, {fail: 'early'});
        if (!plugin.cfg.main.reject) return next();
        return next(DENYDISCONNECT, "You talk too soon");
    };

    var pause = plugin.pause;
    if (plugin.hook === 'connect_init') {
        var elapsed = (Date.now() - connection.start_time);
        if (elapsed > plugin.pause) {
            // Something else already waited
            return check();
        }
        pause = plugin.pause - elapsed;
    }

    setTimeout(function () { check(); }, pause);
};

/**
 * Check if an ip is whitelisted
 *
 * @param  {String} ip       The remote IP to verify
 * @return {Boolean}         True if is whitelisted
 */
exports.ip_in_list = function (ip) {
    var plugin = this;
    var ipobj = ipaddr.parse(ip);

    if (!plugin.whitelist) {
        return false;
    }

    for (var i = 0; i < plugin.whitelist.length; i++) {
        try {
            if (ipobj.match(plugin.whitelist[i])) {
                return true;
            }
        } catch (ignore) {
        }
    }
    return false;
};

/**
 * Convert config ip to ipaddr objects
 *
 * @param  {Array} list A list of IP addresses / subnets
 * @return {Array}      The converted array
 */
exports.load_ip_list = function(list) {
    var whitelist = [];

    for (var i = 0; i < list.length; i++) {
        try {
            var addr = list[i];
            if (addr.match(/\/\d+$/)) {
                addr = ipaddr.parseCIDR(addr);
            }
            else {
                addr = ipaddr.parseCIDR(addr + ((isIPv6(addr)) ? '/128' : '/32'));
            }

            whitelist.push(addr);
        } catch (ignore) {
        }
    }
    return whitelist;
};
<commit_msg>Reorder checks, see #1423<commit_after>// This plugin checks for clients that talk before we sent a response

var ipaddr = require('ipaddr.js');
var isIPv6 = require('net').isIPv6;

exports.register = function() {
    var plugin = this;
    plugin.load_config();
    plugin.register_hook('connect_init', 'early_talker');
    plugin.register_hook('data',         'early_talker');
};

exports.load_config = function () {
    var plugin = this;

    plugin.cfg = plugin.config.get('early_talker.ini', {
        booleans: [
            '+main.reject'
        ]
    },
    function () {
        plugin.load_config();
    });

    // Generate a white list of IP addresses
    plugin.whitelist = plugin.load_ip_list(Object.keys(plugin.cfg.ip_whitelist));

    if (plugin.cfg.main && plugin.cfg.main.pause) {
        plugin.pause = plugin.cfg.main.pause * 1000;
        return;
    }

    // config/early_talker.pause is in milliseconds
    plugin.pause = plugin.config.get('early_talker.pause', function () {
        plugin.load_config();
    });
};

exports.early_talker = function(next, connection) {
    var plugin = this;
    if (!plugin.pause) return next();

    if (connection.relaying) {    // Don't delay AUTH/RELAY clients
        if (connection.early_talker) {
            connection.results.add(plugin, { skip: 'relay client'});
        }
        return next();
    }

    // Don't delay whitelisted IPs
    if (plugin.ip_in_list(connection.remote_ip)) { // check connecting IP
        connection.results.add(plugin, { skip: 'whitelist' });
        return next();
    }

    var check = function () {
        if (!connection) return next();
        if (!connection.early_talker) {
            connection.results.add(plugin, {pass: 'early'});
            return next();
        }
        connection.results.add(plugin, {fail: 'early'});
        if (!plugin.cfg.main.reject) return next();
        return next(DENYDISCONNECT, "You talk too soon");
    };

    var pause = plugin.pause;
    if (plugin.hook === 'connect_init') {
        var elapsed = (Date.now() - connection.start_time);
        if (elapsed > plugin.pause) {
            // Something else already waited
            return check();
        }
        pause = plugin.pause - elapsed;
    }

    setTimeout(function () { check(); }, pause);
};

/**
 * Check if an ip is whitelisted
 *
 * @param  {String} ip       The remote IP to verify
 * @return {Boolean}         True if is whitelisted
 */
exports.ip_in_list = function (ip) {
    var plugin = this;

    if (!plugin.whitelist) {
        return false;
    }

    var ipobj = ipaddr.parse(ip);

    for (var i = 0; i < plugin.whitelist.length; i++) {
        try {
            if (ipobj.match(plugin.whitelist[i])) {
                return true;
            }
        } catch (ignore) {
        }
    }
    return false;
};

/**
 * Convert config ip to ipaddr objects
 *
 * @param  {Array} list A list of IP addresses / subnets
 * @return {Array}      The converted array
 */
exports.load_ip_list = function(list) {
    var whitelist = [];

    for (var i = 0; i < list.length; i++) {
        try {
            var addr = list[i];
            if (addr.match(/\/\d+$/)) {
                addr = ipaddr.parseCIDR(addr);
            }
            else {
                addr = ipaddr.parseCIDR(addr + ((isIPv6(addr)) ? '/128' : '/32'));
            }

            whitelist.push(addr);
        } catch (ignore) {
        }
    }
    return whitelist;
};
<|endoftext|>


<commit_before>// Create a socket plugin
const socketIO = require('socket.io');
const extend = require('extend');

const listeners = {};

module.exports = {
  name: 'socket',
  options: {
    path: {
      env: false
    },
    serveClient: {},
    adapter: {},
    origins: {},
    parser: {},
    pingTimeout: {},
    pingInterval: {},
    upgradeTimeout: {},
    maxHttpBufferSize: {},
    allowRequest: {},
    transports: {},
    allowUpgrades: {},
    perMessageDeflate: {},
    httpCompression: {},
    cookie: {},
    cookiePath: {},
    cookieHttpOnly: {},
    wsEngine: {}
  },
  router: (path, middle) => {
    listeners[path] = listeners[path] || [];
    listeners[path].push(middle);
  },
  launch: ctx => {
    if (!ctx.options.socket) return;
    console.log(ctx.options.socket);
    ctx.io = socketIO(ctx.server, ctx.options.socket);
    ctx.io.on('connect', socket => {
      // console.log(socket.client.request.session);
      for (let path in listeners) {
        if (path !== 'connect') {
          listeners[path].forEach(cb => {
            socket.on(path, data => {
              cb(extend(socket.client.request, ctx, { path, socket, data }));
            });
          });
        }
      }
      if (listeners['connect']) {
        listeners['connect'].forEach(cb => {
          cb(extend(socket.client.request, ctx, { path: 'connect', socket }));
        });
      }
    });
  }
};
<commit_msg>Fixed path for sockett<commit_after>// Create a socket plugin
const socketIO = require('socket.io');
const extend = require('extend');

const listeners = {};

module.exports = {
  name: 'socket',
  options: {
    path: {
      env: 'SOCKET_PATH'
    },
    serveClient: {},
    adapter: {},
    origins: {},
    parser: {},
    pingTimeout: {},
    pingInterval: {},
    upgradeTimeout: {},
    maxHttpBufferSize: {},
    allowRequest: {},
    transports: {},
    allowUpgrades: {},
    perMessageDeflate: {},
    httpCompression: {},
    cookie: {},
    cookiePath: {},
    cookieHttpOnly: {},
    wsEngine: {}
  },
  router: (path, middle) => {
    listeners[path] = listeners[path] || [];
    listeners[path].push(middle);
  },
  launch: ctx => {
    if (!ctx.options.socket) return;
    ctx.io = socketIO(ctx.server, ctx.options.socket);
    ctx.io.on('connect', socket => {
      // console.log(socket.client.request.session);
      for (let path in listeners) {
        if (path !== 'connect') {
          listeners[path].forEach(cb => {
            socket.on(path, data => {
              cb(extend(socket.client.request, ctx, { path, socket, data }));
            });
          });
        }
      }
      if (listeners['connect']) {
        listeners['connect'].forEach(cb => {
          cb(extend(socket.client.request, ctx, { path: 'connect', socket }));
        });
      }
    });
  }
};
<|endoftext|>


<commit_before>// Set initial values for drawing the map image
var mapW, mapH;	// integers: width and height of map image
var zoom = 0; // integer: zoom level -- should always default to 0
var mapBoxW = initMapBoxW;	// integer: western bound of map image (per IMS map API)
var mapBoxN = initMapBoxN;	// integer: northern bound of map image (per IMS map API)
var mapBoxS = initMapBoxS;	// integer: southern bound of map image (per IMS map API)
var mapBoxE = initMapBoxE;	// integer: eastern bound of map image (per IMS map API)
var hasMoved = false;	// boolean: has the map been scrolled or zoomed?
var maxZoom = 2;	// integer: max zoom-in level
var minZoom = -8;	// integer: max zoom-out level
var detailBaseURL = "detail.php?";	// base URL for the normal map detail screen
var fullscreenBaseURL = "detail-fullscreen.php?";	// base URL for the fullscreen map detail screen

function jumpbrowse(objSelect) {
// Use the value of the 'browse by' select control to jump to a different browse page
	if(objSelect) {
		switch(objSelect.value) {
			case "number":
				document.location.href="building-number.html";
				break;
			case "name":
				document.location.href="building-name.html";
				break;
			case "residences":
				document.location.href="residences.html";
				break;
			case "rooms":
				document.location.href="rooms.html";
				break;
			case "streets":
				document.location.href="streets.html";
				break;
			case "courts":
				document.location.href="courts.html";
				break;
			case "food":
				document.location.href="food.html";
				break;
			case "parking":
				document.location.href="parking.html";
				break;
		}
	}
}

function loadImage(imageURL,imageID) {
// Loads an image from the given URL into the image with the specified ID
	var objMap = document.getElementById(imageID);
	show("loadingimage");
	if(objMap) {
		if(imageURL!="") {
			objMap.src = imageURL;
		} else {
			objMap.src = "../Webkit/images/blank.png";
		}
	}
	// Since we're loading a new map image, update the link(s) to switch between fullscreen and smallscreen modes
	var objFullscreen = document.getElementById("fullscreen");
	if(objFullscreen) {
		objFullscreen.href = getMapURL(fullscreenBaseURL, true);
	}
	var objSmallscreen = document.getElementById("smallscreen");
	if(objSmallscreen) {
		objSmallscreen.href = getMapURL(detailBaseURL, true);
	}
}

function getMapURL(strBaseURL, includeSelect) {
	// Returns a full URL for a map page or map image, using strBaseURL as the base
	var newURL = strBaseURL + "&width=" + mapW + "&height=" + mapH + "&bbox=" + mapBoxW + "," + mapBoxS + "," + mapBoxE + "," + mapBoxN + mapOptions;

        // Add parameters for the original bounding box, so Image can be recentered
        if(includeSelect) {
        	newURL += "&bboxSelect=" + selectMapBoxW + "," + selectMapBoxS + "," + selectMapBoxE + "," + selectMapBoxN;
        }
	return(newURL);
}

function scroll(dir) {
// Scrolls the map image in the cardinal direction given by dir; amount of scrolling is scaled to zoom level and the pixel dimensions of the map image
	var objMap = document.getElementById("mapimage");
	if(objMap) {
		var mapDX, mapDY;
		if(zoom<maxZoom) {
			mapDX = mapW*(1-(zoom/2));
			mapDY = mapH*(1-(zoom/2));
		} else {
			mapDX = mapW/2.3;
			mapDY = mapH/2.3;
		}
		switch(dir) {
			case "n":
				mapBoxN = mapBoxN + mapDY;
				mapBoxS = mapBoxS + mapDY;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "s":
				mapBoxN = mapBoxN - mapDY;
				mapBoxS = mapBoxS - mapDY;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "e":
				mapBoxE = mapBoxE + mapDX;
				mapBoxW = mapBoxW + mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "w":
				mapBoxE = mapBoxE - mapDX;
				mapBoxW = mapBoxW - mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "ne":
				mapBoxN = mapBoxN + mapDY;
				mapBoxS = mapBoxS + mapDY;
				mapBoxE = mapBoxE + mapDX;
				mapBoxW = mapBoxW + mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "nw":
				mapBoxN = mapBoxN + mapDY;
				mapBoxS = mapBoxS + mapDY;
				mapBoxE = mapBoxE - mapDX;
				mapBoxW = mapBoxW - mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "se":
				mapBoxN = mapBoxN - mapDY;
				mapBoxS = mapBoxS - mapDY;
				mapBoxE = mapBoxE + mapDX;
				mapBoxW = mapBoxW + mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "sw":
				mapBoxN = mapBoxN - mapDY;
				mapBoxS = mapBoxS - mapDY;
				mapBoxE = mapBoxE - mapDX;
				mapBoxW = mapBoxW - mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
		}
		checkIfMoved();
	}
}

function recenter() {
// Reset the map image to its initially selected coordinates -- only if it's not already there
	if(hasMoved) {
		hasMoved = false;
		mapBoxW = selectMapBoxW;
		mapBoxN = selectMapBoxN;
		mapBoxS = selectMapBoxS;
		mapBoxE = selectMapBoxE;
		zoom = 0;	// reset zoom level
		loadImage(getMapURL(mapBaseURL),'mapimage');
		enable('zoomin');
		enable('zoomout');
		disable('recenter');
	}
}

function zoomout() {
// Zoom the map out by an amount scaled to the pixel dimensions of the map image
	enable('zoomin');
	if(zoom > minZoom) {
		mapBoxN = mapBoxN + (mapH/2);
		mapBoxS = mapBoxS - (mapH/2);
		mapBoxE = mapBoxE + (mapW/2);
		mapBoxW = mapBoxW - (mapW/2);
		loadImage(getMapURL(mapBaseURL),'mapimage');
		zoom--;
	}
	if(zoom <= minZoom) {	// If we've reached the min zoom level
		disable('zoomout');
	}
	checkIfMoved();
}

function zoomin() {
// Zoom the map in by an amount scaled to the pixel dimensions of the map image
	enable('zoomout');
	if(zoom < maxZoom) {
		mapBoxN = mapBoxN - (mapH/2);
		mapBoxS = mapBoxS + (mapH/2);
		mapBoxE = mapBoxE - (mapW/2);
		mapBoxW = mapBoxW + (mapW/2);
		loadImage(getMapURL(mapBaseURL),'mapimage');
		zoom++;
	}
	if(zoom >= maxZoom) {	// If we've reached the max zoom level
		disable('zoomin');
	}
	checkIfMoved();
}

function rotateMap() {
// Load a rotated map image
	var objMap = document.getElementById("mapimage");
	var objContainer = document.getElementById("container");
	var objScrollers = document.getElementById("mapscrollers");
	if(objMap) {
		show("loadingimage");
		mapW = window.innerWidth;
		mapH = window.innerHeight;
		loadImage(getMapURL(mapBaseURL),'mapimage');
	}
	if(objContainer) {
		objContainer.style.width=mapW+"px";
		objContainer.style.height=mapH+"px";
		objMap.style.width=mapW+"px";
		objMap.style.height=mapH+"px";
	}
	if(objScrollers) {
		switch(window.orientation)
		{
			case 0:
			case 180:
				objScrollers.style.height=(mapH-42)+"px";
			break;

			case -90:
			case 90:
				objScrollers.style.height=mapH+"px";
			break;

		}
	}
}

function rotateMapAlternate() {
// Load a rotated map image - needs work to get innerWidth and innerHeight working correctly -- will be required once firmware 2.0 is released enabling full-screen chromeless browsing
	var objMap = document.getElementById("mapimage");
	if(objMap) {
		show("loadingimage");
		mapW = window.innerWidth;
		mapH = window.innerHeight;
		loadImage(getMapURL(mapBaseURL),'mapimage');
	}
}

function checkIfMoved() {
// Check to see if the map has been moved (zoomed or scrolled) away from its initial position, and disable/enable the 'recenter' button accordingly
	hasMoved = !((mapBoxW == selectMapBoxW) && (mapBoxN == selectMapBoxN) && (mapBoxS == selectMapBoxS) && (mapBoxE == selectMapBoxE));
	if(hasMoved) {
		enable('recenter');
	} else {
		disable('recenter');
	}

}

function disable(strID) {
// Visually dims and disables the anchor whose id is strID
	var objA = document.getElementById(strID);
	if(objA) {
		if(objA.className.indexOf("disabled") == -1) { // only disable if it's not already disabled!
			objA.className = objA.className + " disabled";
		}
	}
}

function enable(strID) {
// Visually undims and re-enables the anchor whose id is strID
	var objA = document.getElementById(strID);
	if(objA) {
		objA.className = objA.className.replace("disabled","");
	}
}

function saveOptions(strFormID) {
// Applies full-screen map-option changes and hides the form
	var newLayers = "Towns,Hydro,Greenspace,Sport,Courtyards,Roads,Rail,Landmarks,Parking,Other+Buildings,Buildings,";

	// Code to manipulate the string newLayers should go here, based on what the user toggled in the form

	if(document.mapform.chkLabelBuildings.checked) { newLayers = newLayers + "," + document.mapform.chkLabelBuildings.value; }
	if(document.mapform.chkLabelRoads.checked) { newLayers = newLayers + "," + document.mapform.chkLabelRoads.value; }
	if(document.mapform.chkLabelCourts.checked) { newLayers = newLayers + "," + document.mapform.chkLabelCourts.value; }
	if(document.mapform.chkLabelLandmarks.checked) { newLayers = newLayers + "," + document.mapform.chkLabelLandmarks.value; }
	if(document.mapform.chkLabelParking.checked) { newLayers = newLayers + "," + document.mapform.chkLabelParking.value; }

	if(newLayers!=mapLayers) { 	// Only load a new map image if the user actually changed some options
		mapLayers = newLayers;
		loadImage(getMapURL(mapBaseURL),'mapimage');
	}

	hide("options");
}

function cancelOptions(strFormID) {
// Should cancel map-option changes and hide the form; this is just a stub for future real function
	var objForm = document.getElementById(strFormID);
	if(objForm) { objForm.reset() }
	hide("options");
}

<commit_msg>[mw] make sure Webkit fullscreen map is correct ratio<commit_after>// Set initial values for drawing the map image
var mapW, mapH;	// integers: width and height of map image
var zoom = 0; // integer: zoom level -- should always default to 0
var mapBoxW = initMapBoxW;	// integer: western bound of map image (per IMS map API)
var mapBoxN = initMapBoxN;	// integer: northern bound of map image (per IMS map API)
var mapBoxS = initMapBoxS;	// integer: southern bound of map image (per IMS map API)
var mapBoxE = initMapBoxE;	// integer: eastern bound of map image (per IMS map API)
var hasMoved = false;	// boolean: has the map been scrolled or zoomed?
var maxZoom = 2;	// integer: max zoom-in level
var minZoom = -8;	// integer: max zoom-out level
var detailBaseURL = "detail.php?";	// base URL for the normal map detail screen
var fullscreenBaseURL = "detail-fullscreen.php?";	// base URL for the fullscreen map detail screen

function jumpbrowse(objSelect) {
// Use the value of the 'browse by' select control to jump to a different browse page
	if(objSelect) {
		switch(objSelect.value) {
			case "number":
				document.location.href="building-number.html";
				break;
			case "name":
				document.location.href="building-name.html";
				break;
			case "residences":
				document.location.href="residences.html";
				break;
			case "rooms":
				document.location.href="rooms.html";
				break;
			case "streets":
				document.location.href="streets.html";
				break;
			case "courts":
				document.location.href="courts.html";
				break;
			case "food":
				document.location.href="food.html";
				break;
			case "parking":
				document.location.href="parking.html";
				break;
		}
	}
}

function loadImage(imageURL,imageID) {
// Loads an image from the given URL into the image with the specified ID
	var objMap = document.getElementById(imageID);
	show("loadingimage");
	if(objMap) {
		if(imageURL!="") {
			objMap.src = imageURL;
		} else {
			objMap.src = "../Webkit/images/blank.png";
		}
	}
	// Since we're loading a new map image, update the link(s) to switch between fullscreen and smallscreen modes
	var objFullscreen = document.getElementById("fullscreen");
	if(objFullscreen) {
		objFullscreen.href = getMapURL(fullscreenBaseURL, true);
	}
	var objSmallscreen = document.getElementById("smallscreen");
	if(objSmallscreen) {
		objSmallscreen.href = getMapURL(detailBaseURL, true);
	}
}

function getMapURL(strBaseURL, includeSelect) {
	// Returns a full URL for a map page or map image, using strBaseURL as the base
	var newURL = strBaseURL + "&width=" + mapW + "&height=" + mapH + "&bbox=" + mapBoxW + "," + mapBoxS + "," + mapBoxE + "," + mapBoxN + mapOptions;

        // Add parameters for the original bounding box, so Image can be recentered
        if(includeSelect) {
        	newURL += "&bboxSelect=" + selectMapBoxW + "," + selectMapBoxS + "," + selectMapBoxE + "," + selectMapBoxN;
        }
	return(newURL);
}

function scroll(dir) {
// Scrolls the map image in the cardinal direction given by dir; amount of scrolling is scaled to zoom level and the pixel dimensions of the map image
	var objMap = document.getElementById("mapimage");
	if(objMap) {
		var mapDX, mapDY;
		if(zoom<maxZoom) {
			mapDX = mapW*(1-(zoom/2));
			mapDY = mapH*(1-(zoom/2));
		} else {
			mapDX = mapW/2.3;
			mapDY = mapH/2.3;
		}
		switch(dir) {
			case "n":
				mapBoxN = mapBoxN + mapDY;
				mapBoxS = mapBoxS + mapDY;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "s":
				mapBoxN = mapBoxN - mapDY;
				mapBoxS = mapBoxS - mapDY;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "e":
				mapBoxE = mapBoxE + mapDX;
				mapBoxW = mapBoxW + mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "w":
				mapBoxE = mapBoxE - mapDX;
				mapBoxW = mapBoxW - mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "ne":
				mapBoxN = mapBoxN + mapDY;
				mapBoxS = mapBoxS + mapDY;
				mapBoxE = mapBoxE + mapDX;
				mapBoxW = mapBoxW + mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "nw":
				mapBoxN = mapBoxN + mapDY;
				mapBoxS = mapBoxS + mapDY;
				mapBoxE = mapBoxE - mapDX;
				mapBoxW = mapBoxW - mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "se":
				mapBoxN = mapBoxN - mapDY;
				mapBoxS = mapBoxS - mapDY;
				mapBoxE = mapBoxE + mapDX;
				mapBoxW = mapBoxW + mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
			case "sw":
				mapBoxN = mapBoxN - mapDY;
				mapBoxS = mapBoxS - mapDY;
				mapBoxE = mapBoxE - mapDX;
				mapBoxW = mapBoxW - mapDX;
				loadImage(getMapURL(mapBaseURL),'mapimage');
				break;
		}
		checkIfMoved();
	}
}

function recenter() {
// Reset the map image to its initially selected coordinates -- only if it's not already there
	if(hasMoved) {
		hasMoved = false;
		mapBoxW = selectMapBoxW;
		mapBoxN = selectMapBoxN;
		mapBoxS = selectMapBoxS;
		mapBoxE = selectMapBoxE;
		zoom = 0;	// reset zoom level
		loadImage(getMapURL(mapBaseURL),'mapimage');
		enable('zoomin');
		enable('zoomout');
		disable('recenter');
	}
}

function zoomout() {
// Zoom the map out by an amount scaled to the pixel dimensions of the map image
	enable('zoomin');
	if(zoom > minZoom) {
		mapBoxN = mapBoxN + (mapH/2);
		mapBoxS = mapBoxS - (mapH/2);
		mapBoxE = mapBoxE + (mapW/2);
		mapBoxW = mapBoxW - (mapW/2);
		loadImage(getMapURL(mapBaseURL),'mapimage');
		zoom--;
	}
	if(zoom <= minZoom) {	// If we've reached the min zoom level
		disable('zoomout');
	}
	checkIfMoved();
}

function zoomin() {
// Zoom the map in by an amount scaled to the pixel dimensions of the map image
	enable('zoomout');
	if(zoom < maxZoom) {
		mapBoxN = mapBoxN - (mapH/2);
		mapBoxS = mapBoxS + (mapH/2);
		mapBoxE = mapBoxE - (mapW/2);
		mapBoxW = mapBoxW + (mapW/2);
		loadImage(getMapURL(mapBaseURL),'mapimage');
		zoom++;
	}
	if(zoom >= maxZoom) {	// If we've reached the max zoom level
		disable('zoomin');
	}
	checkIfMoved();
}

function rotateMap() {
// Load a rotated map image
	var objMap = document.getElementById("mapimage");
	var objContainer = document.getElementById("container");
	var objScrollers = document.getElementById("mapscrollers");
	if(objMap) {
		show("loadingimage");
		mapW = window.innerWidth;
		mapH = window.innerHeight;
		var bboxW = mapBoxE - mapBoxW;
		var bboxH = mapBoxN - mapBoxS;
		if (mapH / mapW != bboxH / bboxW) { // need taller image
			var newBBoxH = mapH * bboxW / mapW;
			mapBoxN = mapBoxN + (newBBoxH - bboxH) / 2;
			mapBoxS = mapBoxS - (newBBoxH - bboxH) / 2;
		}

		loadImage(getMapURL(mapBaseURL),'mapimage');
	}
	if(objContainer) {
		objContainer.style.width=mapW+"px";
		objContainer.style.height=mapH+"px";
		objMap.style.width=mapW+"px";
		objMap.style.height=mapH+"px";
	}
	if(objScrollers) {
		switch(window.orientation)
		{
			case 0:
			case 180:
				objScrollers.style.height=(mapH-42)+"px";
			break;

			case -90:
			case 90:
				objScrollers.style.height=mapH+"px";
			break;

		}
	}
}

function rotateMapAlternate() {
// Load a rotated map image - needs work to get innerWidth and innerHeight working correctly -- will be required once firmware 2.0 is released enabling full-screen chromeless browsing
	var objMap = document.getElementById("mapimage");
	if(objMap) {
		show("loadingimage");
		mapW = window.innerWidth;
		mapH = window.innerHeight;
		loadImage(getMapURL(mapBaseURL),'mapimage');
	}
}

function checkIfMoved() {
// Check to see if the map has been moved (zoomed or scrolled) away from its initial position, and disable/enable the 'recenter' button accordingly
	hasMoved = !((mapBoxW == selectMapBoxW) && (mapBoxN == selectMapBoxN) && (mapBoxS == selectMapBoxS) && (mapBoxE == selectMapBoxE));
	if(hasMoved) {
		enable('recenter');
	} else {
		disable('recenter');
	}

}

function disable(strID) {
// Visually dims and disables the anchor whose id is strID
	var objA = document.getElementById(strID);
	if(objA) {
		if(objA.className.indexOf("disabled") == -1) { // only disable if it's not already disabled!
			objA.className = objA.className + " disabled";
		}
	}
}

function enable(strID) {
// Visually undims and re-enables the anchor whose id is strID
	var objA = document.getElementById(strID);
	if(objA) {
		objA.className = objA.className.replace("disabled","");
	}
}

function saveOptions(strFormID) {
// Applies full-screen map-option changes and hides the form
	var newLayers = "Towns,Hydro,Greenspace,Sport,Courtyards,Roads,Rail,Landmarks,Parking,Other+Buildings,Buildings,";

	// Code to manipulate the string newLayers should go here, based on what the user toggled in the form

	if(document.mapform.chkLabelBuildings.checked) { newLayers = newLayers + "," + document.mapform.chkLabelBuildings.value; }
	if(document.mapform.chkLabelRoads.checked) { newLayers = newLayers + "," + document.mapform.chkLabelRoads.value; }
	if(document.mapform.chkLabelCourts.checked) { newLayers = newLayers + "," + document.mapform.chkLabelCourts.value; }
	if(document.mapform.chkLabelLandmarks.checked) { newLayers = newLayers + "," + document.mapform.chkLabelLandmarks.value; }
	if(document.mapform.chkLabelParking.checked) { newLayers = newLayers + "," + document.mapform.chkLabelParking.value; }

	if(newLayers!=mapLayers) { 	// Only load a new map image if the user actually changed some options
		mapLayers = newLayers;
		loadImage(getMapURL(mapBaseURL),'mapimage');
	}

	hide("options");
}

function cancelOptions(strFormID) {
// Should cancel map-option changes and hide the form; this is just a stub for future real function
	var objForm = document.getElementById(strFormID);
	if(objForm) { objForm.reset() }
	hide("options");
}

<|endoftext|>


<commit_before>define([
	"dojo/_base/array",
	"dojo/_base/declare",
	"dojo/_base/lang",
	"dojo/date",
	"dojo/date/locale",
	"dojo/date/stamp"
], function(array, declare, lang, ddate, datelocale, datestamp){

	// module:
	//		dojox/mobile/_DatePickerMixin
	// summary:
	//		A mixin for date picker widget.

	var slotMixin = {
		format: function(/*Date*/d){
			return datelocale.format(d, {datePattern:this.pattern, selector:"date"});
		}
	};

	var yearSlotMixin = lang.mixin({
		initLabels: function(){
			this.labels = [];
			if(this.labelFrom !== this.labelTo){
				var d = new Date(this.labelFrom, 0, 1);
				var i, idx;
				for(i = this.labelFrom, idx = 0; i <= this.labelTo; i++, idx++){
					d.setFullYear(i);
					this.labels.push(this.format(d));
				}
			}
		}
	}, slotMixin);

	var monthSlotMixin = lang.mixin({
		initLabels: function(){
			this.labels = [];
			var d = new Date(2000, 0, 1);
			for(var i = 0; i < 12; i++){
				d.setMonth(i);
				this.labels.push(this.format(d));
			}
		}
	}, slotMixin);

	var daySlotMixin = lang.mixin({
		initLabels: function(){
			this.labels = [];
			var d = new Date(2000, 0, 1);
			for(var i = 1; i <= 31; i++){
				d.setDate(i);
				this.labels.push(this.format(d));
			}
		}
	}, slotMixin);

	return declare("dojox.mobile._DatePickerMixin", null, {
		// summary:
		//		A mixin for date picker widget.

		// yearPattern: String
		//		A pattern to be used to format year.
		yearPattern: "yyyy",

		// monthPattern: String
		//		A pattern to be used to format month.
		monthPattern: "MMM",

		// dayPattern: String
		//		A pattern to be used to format day.
		dayPattern: "d",

		initSlots: function(){
			var c = this.slotClasses, p = this.slotProps;
			c[0] = declare(c[0], yearSlotMixin);
			c[1] = declare(c[1], monthSlotMixin);
			c[2] = declare(c[2], daySlotMixin);
			p[0].pattern = this.yearPattern;
			p[1].pattern = this.monthPattern;
			p[2].pattern = this.dayPattern;
			this.reorderSlots();
		},

		reorderSlots: function(){
			if(this.slotOrder.length){ return; }
			var a = datelocale._parseInfo().bundle["dateFormat-short"].toLowerCase().split(/[^ymd]+/, 3);
			this.slotOrder = array.map(a, function(pat){
				return {y:0, m:1, d:2}[pat.charAt(0)];
			});
		},

		reset: function(){
			// summary:
			//		Goes to today.
			var now = new Date();
			var v = array.map(this.slots, function(w){ return w.format(now); });
			this.set("values", v);
			this.set("colors", v);
			this.disableValues(this.onDaySet());
		},

		onYearSet: function(){
			// summary:
			//		A handler called when the year value is changed.
			this.disableValues(this.onDaySet());
		},

		onMonthSet: function(){
			// summary:
			//		A handler called when the month value is changed.
			this.disableValues(this.onDaySet());
		},

		onDaySet: function(){
			// summary:
			//		A handler called when the day value is changed.
			var v = this.get("values"), // [year, month, day]
				pat = this.slots[0].pattern + "/" + this.slots[1].pattern,
				date = datelocale.parse(v[0] + "/" + v[1], {datePattern:pat, selector:"date"}),
				daysInMonth = ddate.getDaysInMonth(date);
			if(daysInMonth < v[2]){
				this.slots[2].set("value", daysInMonth);
			}
			return daysInMonth;
		},

		_getDateAttr: function(){
			// summary:
			//		Returns a Date object for the current values
			var v = this.get("values"), // [year, month, day]
				s = this.slots,
				pat = s[0].pattern + "/" + s[1].pattern + "/" + s[2].pattern;
				return datelocale.parse(v[0] + "/" + v[1] + "/" + v[2], {datePattern:pat, selector:"date"});
		},

		_setValuesAttr: function(/*Array*/a){
			// summary:
			//		Sets the slot values.
			array.forEach(this.getSlots(), function(w, i){
				var v = a[i];
				if(!isNaN(v)){
					var arr = [1970, 1, 1];
					arr.splice(i, 1, v - 0);
					v = w.format(new Date(arr[0], arr[1], arr[2]));
				}
				w.set("value", v);
			});
		},

		_setValueAttr: function(/*String*/value){
			// summary:
			//		Sets the current date as an String formatted according to a subset of the ISO-8601 standard.
			// description:
			//		This method first converts the value argument by calling the fromISOString method of
			//		the dojo/date/stamp module, then sets the values of the picker according to the resulting
			//		Date object. If the string cannot be parsed by fromISOString, the method does nothing.
			// value:
			//		A string formatted as described in the dojo/date/stamp module.
			var date = datestamp.fromISOString(value);
			this.set("values", array.map(this.slots, function(w){ return w.format(date); }));
		},

		_getValueAttr: function(){
			// summary:
			//		Gets the current date as a String formatted according to a subset of the ISO-8601 standard.
			// returns:
			//		A string formatted as described in the dojo/date/stamp module.
			return datestamp.toISOString(this.get("date"), { selector: "date" });
		}
	});
});
<commit_msg>Refs #15081 It turned out that [28297] works only in locales that have month names (e.g. English). For other locales (e.g. Japanese), month is a number, and it is converted again in _setValuesAttr, and that results in n+1 month. Fixed _setValuesAttr so that users can specify month that starts from 1, not zero. !strict<commit_after>define([
	"dojo/_base/array",
	"dojo/_base/declare",
	"dojo/_base/lang",
	"dojo/date",
	"dojo/date/locale",
	"dojo/date/stamp"
], function(array, declare, lang, ddate, datelocale, datestamp){

	// module:
	//		dojox/mobile/_DatePickerMixin
	// summary:
	//		A mixin for date picker widget.

	var slotMixin = {
		format: function(/*Date*/d){
			return datelocale.format(d, {datePattern:this.pattern, selector:"date"});
		}
	};

	var yearSlotMixin = lang.mixin({
		initLabels: function(){
			this.labels = [];
			if(this.labelFrom !== this.labelTo){
				var d = new Date(this.labelFrom, 0, 1);
				var i, idx;
				for(i = this.labelFrom, idx = 0; i <= this.labelTo; i++, idx++){
					d.setFullYear(i);
					this.labels.push(this.format(d));
				}
			}
		}
	}, slotMixin);

	var monthSlotMixin = lang.mixin({
		initLabels: function(){
			this.labels = [];
			var d = new Date(2000, 0, 1);
			for(var i = 0; i < 12; i++){
				d.setMonth(i);
				this.labels.push(this.format(d));
			}
		}
	}, slotMixin);

	var daySlotMixin = lang.mixin({
		initLabels: function(){
			this.labels = [];
			var d = new Date(2000, 0, 1);
			for(var i = 1; i <= 31; i++){
				d.setDate(i);
				this.labels.push(this.format(d));
			}
		}
	}, slotMixin);

	return declare("dojox.mobile._DatePickerMixin", null, {
		// summary:
		//		A mixin for date picker widget.

		// yearPattern: String
		//		A pattern to be used to format year.
		yearPattern: "yyyy",

		// monthPattern: String
		//		A pattern to be used to format month.
		monthPattern: "MMM",

		// dayPattern: String
		//		A pattern to be used to format day.
		dayPattern: "d",

		initSlots: function(){
			var c = this.slotClasses, p = this.slotProps;
			c[0] = declare(c[0], yearSlotMixin);
			c[1] = declare(c[1], monthSlotMixin);
			c[2] = declare(c[2], daySlotMixin);
			p[0].pattern = this.yearPattern;
			p[1].pattern = this.monthPattern;
			p[2].pattern = this.dayPattern;
			this.reorderSlots();
		},

		reorderSlots: function(){
			if(this.slotOrder.length){ return; }
			var a = datelocale._parseInfo().bundle["dateFormat-short"].toLowerCase().split(/[^ymd]+/, 3);
			this.slotOrder = array.map(a, function(pat){
				return {y:0, m:1, d:2}[pat.charAt(0)];
			});
		},

		reset: function(){
			// summary:
			//		Goes to today.
			var now = new Date();
			var v = array.map(this.slots, function(w){ return w.format(now); });
			this.set("values", v);
			this.set("colors", v);
			this.disableValues(this.onDaySet());
		},

		onYearSet: function(){
			// summary:
			//		A handler called when the year value is changed.
			this.disableValues(this.onDaySet());
		},

		onMonthSet: function(){
			// summary:
			//		A handler called when the month value is changed.
			this.disableValues(this.onDaySet());
		},

		onDaySet: function(){
			// summary:
			//		A handler called when the day value is changed.
			var v = this.get("values"), // [year, month, day]
				pat = this.slots[0].pattern + "/" + this.slots[1].pattern,
				date = datelocale.parse(v[0] + "/" + v[1], {datePattern:pat, selector:"date"}),
				daysInMonth = ddate.getDaysInMonth(date);
			if(daysInMonth < v[2]){
				this.slots[2].set("value", daysInMonth);
			}
			return daysInMonth;
		},

		_getDateAttr: function(){
			// summary:
			//		Returns a Date object for the current values
			var v = this.get("values"), // [year, month, day]
				s = this.slots,
				pat = s[0].pattern + "/" + s[1].pattern + "/" + s[2].pattern;
				return datelocale.parse(v[0] + "/" + v[1] + "/" + v[2], {datePattern:pat, selector:"date"});
		},

		_setValuesAttr: function(/*Array*/values){
			// summary:
			//		Sets the current date as an array of values.
			// description:
			//		This method takes an array that consists of three values,
			//		year, month, and day. If the values are integer, they are
			//		formatted to locale-specific strings before setting them to
			//		the slots. Month starts from 1 to 12 (Ex. 1 - Jan, 2 - Feb, etc.)
			//		If the values are NOT integer, they are directly
			//		passed to the setter of the slots without formatting.
			//
			// example:
			//	|	set("values", [2012, 1, 20]); // January 20, 2012
			array.forEach(this.getSlots(), function(w, i){
				var v = values[i];
				if(typeof v == "number"){
					var arr = [1970, 1, 1];
					arr.splice(i, 1, v - 0);
					v = w.format(new Date(arr[0], arr[1] - 1, arr[2]));
				}
				w.set("value", v);
			});
		},

		_setValueAttr: function(/*String*/value){
			// summary:
			//		Sets the current date as an String formatted according to a subset of the ISO-8601 standard.
			// description:
			//		This method first converts the value argument by calling the fromISOString method of
			//		the dojo/date/stamp module, then sets the values of the picker according to the resulting
			//		Date object. If the string cannot be parsed by fromISOString, the method does nothing.
			// value:
			//		A string formatted as described in the dojo/date/stamp module.
			//
			// example:
			//	|	set("value", "2012-1-20"); // January 20, 2012
			var date = datestamp.fromISOString(value);
			this.set("values", array.map(this.slots, function(w){ return w.format(date); }));
		},

		_getValueAttr: function(){
			// summary:
			//		Gets the current date as a String formatted according to a subset of the ISO-8601 standard.
			// returns:
			//		A string formatted as described in the dojo/date/stamp module.
			return datestamp.toISOString(this.get("date"), { selector: "date" });
		}
	});
});
<|endoftext|>


<commit_before>$(document).ready(function () {
  var GAMEON = 1;
  var GAMEOVER = 2;
  var state = GAMEON;
  var gameDB = PouchDB(gameDBName);
  var api = '/keygen?user=' + gameDBName;
  $.get(api, function (data) {
    gameDB.sync(data.url, { live: true, retry: true });
    gameDB.allDocs({ include_docs: true }, function (err, data) {
      $.each(data.rows, function (index, change) {
        addGameItem(change);
      });
    });

    var winner = function () {

      var mapRed = {
        map: function (doc) {
          if (doc.status) {
            emit([doc.status, doc.twitter], doc);
          }
        },
        reduce: '_count',
      };
      gameDB.query(mapRed, {
        reduce: true,
        inclusive_end: true,
        startkey: ['join'],
        endkey: ['join', {}],
        group: true,
        group_level: 1
      }, function (err, data) {
        var playersJoined = data.rows[0].value;
        gameDB.query(mapRed, {
          reduce: true,
          inclusive_end: true,
          startkey: ['lost'],
          endkey: ['lost', {}],
          group: true,
          group_level: 1
        }, function (err, data) {
          var playersLost = data.rows[0].value;
          $('#playersLeft').html(' ' + (playersJoined - playersLost));

          if ((playersJoined - playersLost) === 1 &&
            state === GAMEON) {
            var api = '/gameover/' + gameDBName;
            $.post(api, function (data) {
              console.log('later loser');
              gameDB.allDocs({include_docs: true}, function (err, data) {
                if (err) console.log(err);
                var winnerArray = [];
                $.each(data.rows, function (index, row) {
                  if (row.doc.status === 'join') {
                    winnerArray.push(row.doc.twitter);
                  } else if (row.doc.status === 'lost') {
                    winnerArray.splice(winnerArray.indexOf(row.doc.twitter), 1);
                  }
                });
                gameDB.put({
                  _id: winnerArray[0] + '_win',
                  status: 'win',
                  twitter: winnerArray[0],
                  timestamp: Date.now(),
                }).then(function (response) {
                  // handle response
                  console.log('Everyone Informed of loss');
                }).catch(function (err) {
                  console.log(err);
                });
                state = GAMEOVER;
                alert('Winner is ' + winnerArray[0]);
              });
            });
          }
        });
      });
    };

    var changes = gameDB.changes({
      live: true,
      retry: true,
      include_docs: true,
    }).on('change', function (change) {
      // handle change
      addGameItem(change);
      winner();
    }).on('complete', function (info) {
      // changes() was canceled
      console.log('Change Cancelled');
    }).on('error', function (err) {
      console.log(err);
    });
  });
});

var addGameItem = function (change) {
  var username = change.doc.twitter;
  if (username) {
    var status   = change.doc.status;
    var $userItem = $('li[data-twitter="' + username + '"]');
    if ($userItem.length) {
      if (status !== 'join') {
        if (!$userItem.hasClass(status)) {
          $userItem.addClass(status);
          $userItem.removeClass('join');
        }
      }
    } else {
      var li = '
';
      li += '';
      li += '' + username + '';
      li += '
';
      $('ul#players').append(li);
    }
  }
};
<commit_msg>Change the game end a little<commit_after>$(document).ready(function () {
  var GAMEON = 1;
  var GAMEOVER = 2;
  var state = GAMEON;
  var gameDB = PouchDB(gameDBName);
  var api = '/keygen?user=' + gameDBName;
  $.get(api, function (data) {
    gameDB.sync(data.url, { live: true, retry: true });
    gameDB.allDocs({ include_docs: true }, function (err, data) {
      $.each(data.rows, function (index, change) {
        addGameItem(change);
      });
    });

    var winner = function () {

      var mapRed = {
        map: function (doc) {
          if (doc.status) {
            emit([doc.status, doc.twitter], doc);
          }
        },
        reduce: '_count',
      };
      gameDB.query(mapRed, {
        reduce: true,
        inclusive_end: true,
        startkey: ['join'],
        endkey: ['join', {}],
        group: true,
        group_level: 1
      }, function (err, data) {
        var playersJoined = data.rows[0].value;
        gameDB.query(mapRed, {
          reduce: true,
          inclusive_end: true,
          startkey: ['lost'],
          endkey: ['lost', {}],
          group: true,
          group_level: 1
        }, function (err, data) {
          var playersLost = data.rows[0].value;
          $('#playersLeft').html(' ' + (playersJoined - playersLost));

          if ((playersJoined - playersLost) === 1 &&
            state === GAMEON) {
            var api = '/gameover/' + gameDBName;
            $.post(api, function (data) {
              console.log('later loser');
              gameDB.allDocs({include_docs: true}, function (err, data) {
                if (err) console.log(err);
                var winnerArray = [];
                $.each(data.rows, function (index, row) {
                  if (row.doc.status === 'join') {
                    winnerArray.push(row.doc.twitter);
                  } else if (row.doc.status === 'lost') {
                    winnerArray.splice(winnerArray.indexOf(row.doc.twitter), 1);
                  }
                });
                gameDB.put({
                  _id: winnerArray[0] + '_win',
                  status: 'win',
                  twitter: winnerArray[0],
                  timestamp: Date.now(),
                }).then(function (response) {
                  // handle response
                  console.log('Everyone Informed of loss');
                }).catch(function (err) {
                  console.log(err);
                });
                state = GAMEOVER;
                $('h1').html('Winner is ' + winnerArray[0]);

              });
            });
          }
        });
      });
    };

    var changes = gameDB.changes({
      live: true,
      retry: true,
      include_docs: true,
    }).on('change', function (change) {
      // handle change
      addGameItem(change);
      winner();
    }).on('complete', function (info) {
      // changes() was canceled
      console.log('Change Cancelled');
    }).on('error', function (err) {
      console.log(err);
    });
  });
});

var addGameItem = function (change) {
  var username = change.doc.twitter;
  if (username) {
    var status   = change.doc.status;
    var $userItem = $('li[data-twitter="' + username + '"]');
    if ($userItem.length) {
      if (status !== 'join') {
        if (!$userItem.hasClass(status)) {
          $userItem.addClass(status);
          $userItem.removeClass('join');
        }
      }
    } else {
      var li = '
';
      li += '';
      li += '' + username + '';
      li += '
';
      $('ul#players').append(li);
    }
  }
};
<|endoftext|>


<commit_before>// Variables
var chart = null;
var reload = false;
var UVData = [{
		"type": "UV Index",
		"value": 0
}];
var tempData = [{
		"type": "Temperature",
		"value": 0.0
}];
var chartConfig = {
	uv: {
		title: "UV Index",
		balloonText: "UV Index: [[value]]",
		div: "UVDiv",
		color: "#ADD981"
	},
	temp: {
		title: "Temperature",
		balloonText: "Temperature: [[value]] °C",
		div: "tempDiv",
		color: "tomato"
	}
};

/**
 * Updates the chart with the processed data from the socket event.
 * @param type String: The type of the chart that's going to be updated.
 * @param dataProvider Object: The data that will be represented on the chart
 */
function updateChart(type, dataProvider) {
	// Serial chart basic data
	chart = new AmCharts.AmSerialChart();
	chart.dataProvider = dataProvider;
	chart.categoryField = "type";
	if (reload === false) {
		chart.startDuration = 1;
	}

	// Visual settings for the chart
	chart.plotAreaBorderColor = "#DADADA";
	chart.plotAreaBorderAlpha = 1;
	chart.rotate = false;

	// Axes
	// Category
	var categoryAxis = chart.categoryAxis;
	categoryAxis.gridPosition = "start";
	categoryAxis.gridAlpha = 0.1;
	categoryAxis.axisAlpha = 0;

	// Values
	var valueAxis = new AmCharts.ValueAxis();
	valueAxis.title = "Current " + chartConfig[type].title;
	valueAxis.axisAlpha = 0;
	valueAxis.gridAlpha = 0.1;
	chart.addValueAxis(valueAxis);

	// Graphs
	var graph = new AmCharts.AmGraph();
	graph.type = "column";
	graph.title = chartConfig[type].title;
	graph.valueField = "value";
	graph.balloonText = chartConfig[type].balloonText;
	graph.lineAlpha = 0;
	graph.fillColors = chartConfig[type].color;
	graph.fillAlphas = 1;
	chart.addGraph(graph);

	// Legends
	var legend = new AmCharts.AmLegend();
	chart.addLegend(legend);
	chart.creditsPosition = "top-right";
	chart.write(chartConfig[type].div);
	$('#' + type).text(dataProvider[0].value);
}

/**
 * Render the charts whenever the DOM is ready.
 */
AmCharts.ready(function () {
	$.get("http://mswmqtt.cloudapp.net/data")
		.done(function (response) {
			if (response.success) {
				UVData[0].value = response.data[0].value;
				tempData[0].value = response.data[1].value;
				updateChart("uv", UVData);
				updateChart("temp", tempData);
			}
		});
	setInterval(function (){
		$.get("http://mswmqtt.cloudapp.net/data")
		.done(function (response) {
			if (response.success) {
				UVData[0].value = response.data[0].value;
				tempData[0].value = response.data[1].value;
				updateChart("uv", UVData);
				updateChart("temp", tempData);
			}
		});
	}, 15000);
	reload = true;
});<commit_msg>Added timestamp.<commit_after>// Variables
var chart = null;
var reload = false;
var UVData = [{
		"type": "UV Index",
		"value": 0
}];
var tempData = [{
		"type": "Temperature",
		"value": 0.0
}];
var chartConfig = {
	uv: {
		title: "UV Index",
		balloonText: "UV Index: [[value]]",
		div: "UVDiv",
		color: "#ADD981"
	},
	temp: {
		title: "Temperature",
		balloonText: "Temperature: [[value]] °C",
		div: "tempDiv",
		color: "tomato"
	}
};

/**
 * Updates the chart with the processed data from the socket event.
 * @param type String: The type of the chart that's going to be updated.
 * @param dataProvider Object: The data that will be represented on the chart
 */
function updateChart(type, dataProvider) {
	// Serial chart basic data
	chart = new AmCharts.AmSerialChart();
	chart.dataProvider = dataProvider;
	chart.categoryField = "type";
	if (reload === false) {
		chart.startDuration = 1;
	}

	// Visual settings for the chart
	chart.plotAreaBorderColor = "#DADADA";
	chart.plotAreaBorderAlpha = 1;
	chart.rotate = false;

	// Axes
	// Category
	var categoryAxis = chart.categoryAxis;
	categoryAxis.gridPosition = "start";
	categoryAxis.gridAlpha = 0.1;
	categoryAxis.axisAlpha = 0;

	// Values
	var valueAxis = new AmCharts.ValueAxis();
	valueAxis.title = "Current " + chartConfig[type].title;
	valueAxis.axisAlpha = 0;
	valueAxis.gridAlpha = 0.1;
	chart.addValueAxis(valueAxis);

	// Graphs
	var graph = new AmCharts.AmGraph();
	graph.type = "column";
	graph.title = chartConfig[type].title;
	graph.valueField = "value";
	graph.balloonText = chartConfig[type].balloonText + dataProvider.timestamp;
	graph.lineAlpha = 0;
	graph.fillColors = chartConfig[type].color;
	graph.fillAlphas = 1;
	chart.addGraph(graph);

	// Legends
	var legend = new AmCharts.AmLegend();
	chart.addLegend(legend);
	chart.creditsPosition = "top-right";
	chart.write(chartConfig[type].div);
	$('#' + type).text(dataProvider[0].value);
}

/**
 * Render the charts whenever the DOM is ready.
 */
AmCharts.ready(function () {
	$.get("http://mswmqtt.cloudapp.net/data")
		.done(function (response) {
			if (response.success) {
				UVData[0].value = response.data[0].value;
				tempData[0].value = response.data[1].value;
				updateChart("uv", UVData);
				updateChart("temp", tempData);
			}
		});
	setInterval(function (){
		$.get("http://mswmqtt.cloudapp.net/data")
		.done(function (response) {
			if (response.success) {
				UVData[0].value = response.data[0].value;
				tempData[0].value = response.data[1].value;
				UVData[0].timestamp = response.data[0].timestamp;
				tempData[0].timestamp = response.data[1].timestamp;
				updateChart("uv", UVData);
				updateChart("temp", tempData);
			}
		});
	}, 15000);
	reload = true;
});<|endoftext|>


<commit_before>const purgecss = require('@fullhuman/postcss-purgecss')({
  content: ['./**/*.erb', './**/*.rb'],
  defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [],
  whitelist: ['blockquote', 'li', 'pre', 'code', 'figcaption'],
  whitelistPatterns: [/hljs/],
})

module.exports = {
  plugins: [
    require('postcss-import'),
    require('tailwindcss'),
    require('autoprefixer'),
    ...process.env.NODE_ENV === 'production'
      ? [purgecss]
      : []
  ]
}
<commit_msg>Update purgecss settings<commit_after>const purgecss = require('@fullhuman/postcss-purgecss')({
  content: ['./**/*.erb', './**/*.rb'],
  defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [],
  whitelist: ['blockquote', 'li', 'pre', 'code', 'figcaption'],
  whitelistPatterns: [/hljs/, /formkit/],
})

module.exports = {
  plugins: [
    require('postcss-import'),
    require('tailwindcss'),
    require('autoprefixer'),
    ...process.env.NODE_ENV === 'production'
      ? [purgecss]
      : []
  ]
}
<|endoftext|>


<commit_before>
var hundo = {}

hundo.PieceTypeEnum = {
    BALL: "BALL",
    BLOCK: "BLOCK"
}

hundo.DirectionEnum = {
    UP: 0,
    DOWN: 1,
    LEFT: 2,
    RIGHT: 3,
    NODIR: 4
}

// every piece has unique id
hundo.Block = function(id, row, col) {
    this.id = id;
    this.type = hundo.PieceTypeEnum.BLOCK;
    this.row = row;
    this.col = col;
}

hundo.Ball = function(id, row, col, dir) {
    this.id = id;
    this.type = hundo.PieceTypeEnum.BALL;
    this.row = row;
    this.col = col;
    this.dir = dir;
}

// TODO: Assume boardConfig is untrusted
hundo.Board = function(boardConfig) {

    this.done = true;

    this.numRows = boardConfig.numRows;
    this.numCols = boardConfig.numCols;

    // this.matrix[row][call] == array of piece objects
    this.matrix = new Array(this.numRows);
    for (var i = 0; i < this.numRows; i++) {
      this.matrix[i] = new Array(this.numCols);
      for (var j = 0; j < this.numCols; j++) {
        this.matrix[i][j] = new Array();
      }
    }

    var nextId = 0;

    var THIS = this;

    // Add blocks to the matrix
    $.each(boardConfig.blocks, function(index, block) {
        var row = block.row;
        var col = block.col;
        THIS.matrix[row][col].push(new hundo.Block(nextId++, row, col));
    })

    // Add the ball to the matrix
    var row = boardConfig.ball.row;
    var col = boardConfig.ball.col;
    this.ball = new hundo.Ball(nextId++, row, col, hundo.DirectionEnum.NODIR);
    this.matrix[row][col].push(this.ball);

}

hundo.Board.prototype.setDir = function(direction) {
    this.ball.dir = direction;
    this.done = false;
}

// func(piece) should return true iff the piece is of the type being gotten
hundo.Board.prototype.getPieces = function(func) {

    var pieces = [];

    $.each(this.matrix, function(i, row) {
        $.each(row, function(j, col) {
            $.each(col, function(k, piece) {
                if (func(piece)) {
                    pieces.push(piece);
                }
            })
        })
    });

    return pieces;
}

hundo.Board.prototype.getBlocks = function() {
    return this.getPieces(function(piece){
        return piece.type == hundo.PieceTypeEnum.BLOCK;
    });
};

hundo.Board.prototype.getBalls = function() {
    return this.getPieces(function(piece){
        return piece.type == hundo.PieceTypeEnum.BALL;
    });
};

// removes the first element in array for which func(element) is true
// if an element is removed, returns the index of the element removed
// otherwise, returns -1
hundo.arrayRemove = function(array, func) {

    var i;
    for (i = 0; i < array.length; i++) {
        if (func(array[i])) {
            break;
        }
    }

    if (i == array.length) {
        return -1;
    }

    array.splice(i, 1);

    return i;
}

hundo.Board.prototype.movePiece = function(piece, row, col) {

    var pieces = this.matrix[piece.row][piece.col];

    var i = hundo.arrayRemove(pieces, function(p) {
        return p.id == piece.id;
    })

    if (i == -1) {
        console.error("Could not remove piece");
        return;
    }

    // add the piece to its new location
    this.matrix[row][col].push(piece);

    piece.row = row;
    piece.col = col;

}

// returns null on fatal error
// else, returns an animation object, which describes how the
// the step should be animated
hundo.Board.prototype.step = function() {

    var direction = this.ball.dir;

    if (direction == hundo.DirectionEnum.NODIR) {
        console.error("Ball must have a direction to step");
        return null;
    }

    var dr = 0, dc = 0;
    if (direction == hundo.DirectionEnum.UP) {
        dr = -1;
    } else if (direction == hundo.DirectionEnum.DOWN) {
        dr = 1;
    } else if (direction == hundo.DirectionEnum.LEFT) {
        dc = -1;
    } else if (direction == hundo.DirectionEnum.RIGHT) {
        dc = 1;
    } else {
        console.error("Ball must have a direction to step");
        return null;
    }

    var newRow = this.ball.row + dr;
    var newCol = this.ball.col + dc;

    // Check for out of bounds
    if (newRow < 0 || newRow > this.numRows ||
        newCol < 0 || newCol > this.numCols) {

        this.done = true;
        this.ball.dir = hundo.DirectionEnum.NODIR;

        return {
            "move": {
                "dir": direction
            },
            "oob": true
        };
    }

    if (this.matrix[newRow][newCol].length > 0) {
        this.ball.dir = hundo.DirectionEnum.NODIR;
        this.done = true;
        return {
            "collide": {
                "dir": direction,
                "recipients": this.matrix[newRow][newCol]
            }
        };
    } else {
        this.movePiece(this.ball, newRow, newCol);
        return {
            "move": {
                "ball": this.ball,
                "dir": direction
            }
        }
    }
}

var boardConfig = {
    numRows: 5,
    numCols: 10,
    blocks : [
        {
            row: 2,
            col: 1
        },
        {
            row: 2,
            col: 2
        },
        {
            row: 2,
            col: 8
        }
    ],
    ball: {
        row: 2,
        col: 3,
    }
}

var vizConfig = {
    cellSize: 32,
    stepDuration: 1000
}

hundo.board = new hundo.Board(boardConfig);

hundo.boardSvg = d3.select("#boardSvg")
    .attr("width", boardConfig.numCols * vizConfig.cellSize)
    .attr("height", boardConfig.numRows * vizConfig.cellSize);

hundo.boardSvg.select("#background")
    .attr("width", boardConfig.numCols * vizConfig.cellSize)
    .attr("height", boardConfig.numRows * vizConfig.cellSize)
    .attr("style", "fill:black");

hundo.viz = {}

hundo.viz.blockId = function(block) {
    return "block" + block.id;
}

hundo.viz.ballId = function(ball) {
    return "ball" + ball.id;
}

hundo.boardSvg.selectAll(".block")
    .data(hundo.board.getBlocks())
    .enter()
    .append("svg:use")
    .attr("class", "block")
    .attr("id", hundo.viz.blockId)
    .attr("xlink:href", "#blockTemplate")
    .attr("transform", function(block) {
      var x = block.col * vizConfig.cellSize;
      var y = block.row * vizConfig.cellSize;
      return "translate(" + x + ", " + y + ") "
    })

hundo.boardSvg.selectAll(".ball")
    .data(hundo.board.getBalls())
    .enter()
    .append("svg:use")
    .attr("class", "ball")
    .attr("id", hundo.viz.ballId)
    .attr("xlink:href", "#ballTemplate")
    .attr("transform", function(ball) {
      var x = ball.col * vizConfig.cellSize;
      var y = ball.row * vizConfig.cellSize;
      return "translate(" + x + ", " + y + ") "
    })

hundo.stepAnimate = function() {
    var animate = hundo.board.step();

    if (hundo.board.done) {
        clearInterval(hundo.viz.animateInterval);
    }

    if ("move" in animate) {
        console.log("move");
        ball = animate.move.ball;
        ballId = "#" + hundo.viz.ballId(ball);
        hundo.boardSvg.select(ballId)
            .transition()
            .ease("linear")
            .attr("transform", function(ball) {
                var x = ball.col * vizConfig.cellSize;
                var y = ball.row * vizConfig.cellSize;
                return "translate(" + x + ", " + y + ") "
            })
            .duration(vizConfig.stepDuration);

    } else if ("collide" in animate) {
        console.log("collide");
    }
}

hundo.checkKey = function(e) {

    if (!hundo.board.done) {
        return;
    }

    var e = e || window.event;

    var direction;

    if (e.keyCode == '38') {
        console.log("up");
        direction = hundo.DirectionEnum.UP;
    } else if (e.keyCode == '40') {
        console.log("down");
        direction = hundo.DirectionEnum.DOWN;
    } else if (e.keyCode == '37') {
        console.log("left");
        direction = hundo.DirectionEnum.LEFT;
    } else if (e.keyCode == '39') {
        console.log("right");
        direction = hundo.DirectionEnum.RIGHT;
    } else {
        return;
    }

    hundo.board.setDir(direction);

    hundo.stepAnimate();

    hundo.viz.animateInterval =
        setInterval(hundo.stepAnimate, vizConfig.stepDuration);

}

document.onkeydown = hundo.checkKey;
<commit_msg>bug fix in Board.step<commit_after>
var hundo = {}

hundo.PieceTypeEnum = {
    BALL: "BALL",
    BLOCK: "BLOCK"
}

hundo.DirectionEnum = {
    UP: 0,
    DOWN: 1,
    LEFT: 2,
    RIGHT: 3,
    NODIR: 4
}

// every piece has unique id
hundo.Block = function(id, row, col) {
    this.id = id;
    this.type = hundo.PieceTypeEnum.BLOCK;
    this.row = row;
    this.col = col;
}

hundo.Ball = function(id, row, col, dir) {
    this.id = id;
    this.type = hundo.PieceTypeEnum.BALL;
    this.row = row;
    this.col = col;
    this.dir = dir;
}

// TODO: Assume boardConfig is untrusted
hundo.Board = function(boardConfig) {

    this.done = true;

    this.numRows = boardConfig.numRows;
    this.numCols = boardConfig.numCols;

    // this.matrix[row][call] == array of piece objects
    this.matrix = new Array(this.numRows);
    for (var i = 0; i < this.numRows; i++) {
      this.matrix[i] = new Array(this.numCols);
      for (var j = 0; j < this.numCols; j++) {
        this.matrix[i][j] = new Array();
      }
    }

    var nextId = 0;

    var THIS = this;

    // Add blocks to the matrix
    $.each(boardConfig.blocks, function(index, block) {
        var row = block.row;
        var col = block.col;
        THIS.matrix[row][col].push(new hundo.Block(nextId++, row, col));
    })

    // Add the ball to the matrix
    var row = boardConfig.ball.row;
    var col = boardConfig.ball.col;
    this.ball = new hundo.Ball(nextId++, row, col, hundo.DirectionEnum.NODIR);
    this.matrix[row][col].push(this.ball);

}

hundo.Board.prototype.setDir = function(direction) {
    this.ball.dir = direction;
    this.done = false;
}

// func(piece) should return true iff the piece is of the type being gotten
hundo.Board.prototype.getPieces = function(func) {

    var pieces = [];

    $.each(this.matrix, function(i, row) {
        $.each(row, function(j, col) {
            $.each(col, function(k, piece) {
                if (func(piece)) {
                    pieces.push(piece);
                }
            })
        })
    });

    return pieces;
}

hundo.Board.prototype.getBlocks = function() {
    return this.getPieces(function(piece){
        return piece.type == hundo.PieceTypeEnum.BLOCK;
    });
};

hundo.Board.prototype.getBalls = function() {
    return this.getPieces(function(piece){
        return piece.type == hundo.PieceTypeEnum.BALL;
    });
};

// removes the first element in array for which func(element) is true
// if an element is removed, returns the index of the element removed
// otherwise, returns -1
hundo.arrayRemove = function(array, func) {

    var i;
    for (i = 0; i < array.length; i++) {
        if (func(array[i])) {
            break;
        }
    }

    if (i == array.length) {
        return -1;
    }

    array.splice(i, 1);

    return i;
}

hundo.Board.prototype.movePiece = function(piece, row, col) {

    var pieces = this.matrix[piece.row][piece.col];

    var i = hundo.arrayRemove(pieces, function(p) {
        return p.id == piece.id;
    })

    if (i == -1) {
        console.error("Could not remove piece");
        return;
    }

    // add the piece to its new location
    this.matrix[row][col].push(piece);

    piece.row = row;
    piece.col = col;

}

// returns null on fatal error
// else, returns an animation object, which describes how the
// the step should be animated
hundo.Board.prototype.step = function() {

    var direction = this.ball.dir;

    if (direction == hundo.DirectionEnum.NODIR) {
        console.error("Ball must have a direction to step");
        return null;
    }

    var dr = 0, dc = 0;
    if (direction == hundo.DirectionEnum.UP) {
        dr = -1;
    } else if (direction == hundo.DirectionEnum.DOWN) {
        dr = 1;
    } else if (direction == hundo.DirectionEnum.LEFT) {
        dc = -1;
    } else if (direction == hundo.DirectionEnum.RIGHT) {
        dc = 1;
    } else {
        console.error("Ball must have a direction to step");
        return null;
    }

    var newRow = this.ball.row + dr;
    var newCol = this.ball.col + dc;

    // Check for out of bounds
    if (newRow < 0 || newRow >= this.numRows ||
        newCol < 0 || newCol >= this.numCols) {

        this.done = true;
        this.ball.dir = hundo.DirectionEnum.NODIR;

        return {
            "move": {
                "ball": this.ball,
                "dir": direction
            },
            "oob": true
        };
    }

    if (this.matrix[newRow][newCol].length > 0) {
        this.ball.dir = hundo.DirectionEnum.NODIR;
        this.done = true;
        return {
            "collide": {
                "dir": direction,
                "recipients": this.matrix[newRow][newCol]
            }
        };
    } else {
        this.movePiece(this.ball, newRow, newCol);
        return {
            "move": {
                "ball": this.ball,
                "dir": direction
            }
        }
    }
}

var boardConfig = {
    numRows: 5,
    numCols: 10,
    blocks : [
        {
            row: 2,
            col: 1
        },
        {
            row: 2,
            col: 2
        },
        {
            row: 2,
            col: 8
        }
    ],
    ball: {
        row: 2,
        col: 3,
    }
}

var vizConfig = {
    cellSize: 32,
    stepDuration: 1000
}

hundo.board = new hundo.Board(boardConfig);

hundo.boardSvg = d3.select("#boardSvg")
    .attr("width", boardConfig.numCols * vizConfig.cellSize)
    .attr("height", boardConfig.numRows * vizConfig.cellSize);

hundo.boardSvg.select("#background")
    .attr("width", boardConfig.numCols * vizConfig.cellSize)
    .attr("height", boardConfig.numRows * vizConfig.cellSize)
    .attr("style", "fill:black");

hundo.viz = {}

hundo.viz.blockId = function(block) {
    return "block" + block.id;
}

hundo.viz.ballId = function(ball) {
    return "ball" + ball.id;
}

hundo.boardSvg.selectAll(".block")
    .data(hundo.board.getBlocks())
    .enter()
    .append("svg:use")
    .attr("class", "block")
    .attr("id", hundo.viz.blockId)
    .attr("xlink:href", "#blockTemplate")
    .attr("transform", function(block) {
      var x = block.col * vizConfig.cellSize;
      var y = block.row * vizConfig.cellSize;
      return "translate(" + x + ", " + y + ") "
    })

hundo.boardSvg.selectAll(".ball")
    .data(hundo.board.getBalls())
    .enter()
    .append("svg:use")
    .attr("class", "ball")
    .attr("id", hundo.viz.ballId)
    .attr("xlink:href", "#ballTemplate")
    .attr("transform", function(ball) {
      var x = ball.col * vizConfig.cellSize;
      var y = ball.row * vizConfig.cellSize;
      return "translate(" + x + ", " + y + ") "
    })

hundo.stepAnimate = function() {
    var animate = hundo.board.step();

    if (hundo.board.done) {
        clearInterval(hundo.viz.animateInterval);
    }

    if ("move" in animate) {
        console.log("move");
        ball = animate.move.ball;
        ballId = "#" + hundo.viz.ballId(ball);
        hundo.boardSvg.select(ballId)
            .transition()
            .ease("linear")
            .attr("transform", function(ball) {
                var x = ball.col * vizConfig.cellSize;
                var y = ball.row * vizConfig.cellSize;
                return "translate(" + x + ", " + y + ") "
            })
            .duration(vizConfig.stepDuration);

    } else if ("collide" in animate) {
        console.log("collide");
    }
}

hundo.checkKey = function(e) {

    if (!hundo.board.done) {
        return;
    }

    var e = e || window.event;

    var direction;

    if (e.keyCode == '38') {
        console.log("up");
        direction = hundo.DirectionEnum.UP;
    } else if (e.keyCode == '40') {
        console.log("down");
        direction = hundo.DirectionEnum.DOWN;
    } else if (e.keyCode == '37') {
        console.log("left");
        direction = hundo.DirectionEnum.LEFT;
    } else if (e.keyCode == '39') {
        console.log("right");
        direction = hundo.DirectionEnum.RIGHT;
    } else {
        return;
    }

    hundo.board.setDir(direction);

    hundo.stepAnimate();

    hundo.viz.animateInterval =
        setInterval(hundo.stepAnimate, vizConfig.stepDuration);

}

document.onkeydown = hundo.checkKey;
<|endoftext|>