<commit_before>

function View(element, calendar, viewName) {
	var t = this;

	// exports
	t.element = element;
	t.calendar = calendar;
	t.name = viewName;
	t.opt = opt;
	t.trigger = trigger;
	//t.setOverflowHidden = setOverflowHidden;
	t.isEventDraggable = isEventDraggable;
	t.isEventResizable = isEventResizable;
	t.reportEvents = reportEvents;
	t.eventEnd = eventEnd;
	t.reportEventElement = reportEventElement;
	t.reportEventClear = reportEventClear;
	t.eventElementHandlers = eventElementHandlers;
	t.showEvents = showEvents;
	t.hideEvents = hideEvents;
	t.eventDrop = eventDrop;
	t.eventResize = eventResize;
	// t.title
	// t.start, t.end
	// t.visStart, t.visEnd

	// imports
	var defaultEventEnd = t.defaultEventEnd;
	var normalizeEvent = calendar.normalizeEvent; // in EventManager
	var reportEventChange = calendar.reportEventChange;

	// locals
	var eventsByID = {};
	var eventElements = [];
	var eventElementsByID = {};
	var options = calendar.options;

	function opt(name, viewNameOverride) {
		var v = options[name];
		if (typeof v == 'object') {
			return smartProperty(v, viewNameOverride || viewName);
		}
		return v;
	}

	function trigger(name, thisObj) {
		return calendar.trigger.apply(
			calendar,
			[name, thisObj || t].concat(Array.prototype.slice.call(arguments, 2), [t])
		);
	}

	/*
	function setOverflowHidden(bool) {
		element.css('overflow', bool ? 'hidden' : '');
	}
	*/

	function isEventDraggable(event) {
		return isEventEditable(event) && !opt('disableDragging');
	}

	function isEventResizable(event) { // but also need to make sure the seg.isEnd == true
		return isEventEditable(event) && !opt('disableResizing');
	}

	function isEventEditable(event) {
		return firstDefined(event.editable, (event.source || {}).editable, opt('editable'));
	}

	/* Event Data
	------------------------------------------------------------------------------*/

	// report when view receives new events
	function reportEvents(events) { // events are already normalized at this point
		eventsByID = {};
		var i, len=events.length, event;
		for (i=0; i<len; i++) {
			event = events[i];
			if (eventsByID[event._id]) {
				eventsByID[event._id].push(event);
			}else{
				eventsByID[event._id] = [event];
			}
		}
	}

	// returns a Date object for an event's end
	function eventEnd(event) {
		return event.end ? cloneDate(event.end) : defaultEventEnd(event);
	}

	/* Event Elements
	------------------------------------------------------------------------------*/

	// report when view creates an element for an event
	function reportEventElement(event, element) {
		eventElements.push(element);
		if (eventElementsByID[event._id]) {
			eventElementsByID[event._id].push(element);
		}else{
			eventElementsByID[event._id] = [element];
		}
	}

	function reportEventClear() {
		eventElements = [];
		eventElementsByID = {};
	}

	// attaches eventClick, eventMouseover, eventMouseout
	function eventElementHandlers(event, eventElement) {
		eventElement
			.click(function(ev) {
				if (!eventElement.hasClass('ui-draggable-dragging') &&
					!eventElement.hasClass('ui-resizable-resizing')) {
						return trigger('eventClick', this, event, ev);
					}
			})
			.hover(
				function(ev) {
					trigger('eventMouseover', this, event, ev);
				},
				function(ev) {
					trigger('eventMouseout', this, event, ev);
				}
			);
		// TODO: don't fire eventMouseover/eventMouseout *while* dragging is occuring (on subject element)
		// TODO: same for resizing
	}

	function showEvents(event, exceptElement) {
		eachEventElement(event, exceptElement, 'show');
	}

	function hideEvents(event, exceptElement) {
		eachEventElement(event, exceptElement, 'hide');
	}

	function eachEventElement(event, exceptElement, funcName) {
		var elements = eventElementsByID[event._id],
			i, len = elements.length;
		for (i=0; i<len; i++) {
			if (!exceptElement || elements[i][0] != exceptElement[0]) {
				elements[i][funcName]();
			}
		}
	}

	/* Event Modification Reporting
	---------------------------------------------------------------------------------*/

	function eventDrop(e, event, dayDelta, minuteDelta, allDay, ev, ui) {
		var oldAllDay = event.allDay;
		var eventId = event._id;
		moveEvents(eventsByID[eventId], dayDelta, minuteDelta, allDay);
		trigger(
			'eventDrop',
			e,
			event,
			dayDelta,
			minuteDelta,
			allDay,
			function() {
				// TODO: investigate cases where this inverse technique might not work
				moveEvents(eventsByID[eventId], -dayDelta, -minuteDelta, oldAllDay);
				reportEventChange(eventId);
			},
			ev,
			ui
		);
		reportEventChange(eventId);
	}

	function eventResize(e, event, dayDelta, minuteDelta, ev, ui) {
		var eventId = event._id;
		elongateEvents(eventsByID[eventId], dayDelta, minuteDelta);
		trigger(
			'eventResize',
			e,
			event,
			dayDelta,
			minuteDelta,
			function() {
				// TODO: investigate cases where this inverse technique might not work
				elongateEvents(eventsByID[eventId], -dayDelta, -minuteDelta);
				reportEventChange(eventId);
			},
			ev,
			ui
		);
		reportEventChange(eventId);
	}

	/* Event Modification Math
	---------------------------------------------------------------------------------*/

	function moveEvents(events, dayDelta, minuteDelta, allDay) {
		minuteDelta = minuteDelta || 0;
		for (var e, len=events.length, i=0; i<len; i++) {
			e = events[i];
			if (allDay !== undefined) {
				e.allDay = allDay;
			}
			addMinutes(addDays(e.start, dayDelta, true), minuteDelta);
			if (e.end) {
				e.end = addMinutes(addDays(e.end, dayDelta, true), minuteDelta);
			}
			normalizeEvent(e, options);
		}
	}

	function elongateEvents(events, dayDelta, minuteDelta) {
		minuteDelta = minuteDelta || 0;
		for (var e, len=events.length, i=0; i<len; i++) {
			e = events[i];
			e.end = addMinutes(addDays(eventEnd(e), dayDelta, true), minuteDelta);
			normalizeEvent(e, options);
		}
	}

}
<commit_msg>Fixed ussue 1206: Moving from "allDay" event to Day timeline should set end time/date<commit_after>

function View(element, calendar, viewName) {
	var t = this;

	// exports
	t.element = element;
	t.calendar = calendar;
	t.name = viewName;
	t.opt = opt;
	t.trigger = trigger;
	//t.setOverflowHidden = setOverflowHidden;
	t.isEventDraggable = isEventDraggable;
	t.isEventResizable = isEventResizable;
	t.reportEvents = reportEvents;
	t.eventEnd = eventEnd;
	t.reportEventElement = reportEventElement;
	t.reportEventClear = reportEventClear;
	t.eventElementHandlers = eventElementHandlers;
	t.showEvents = showEvents;
	t.hideEvents = hideEvents;
	t.eventDrop = eventDrop;
	t.eventResize = eventResize;
	// t.title
	// t.start, t.end
	// t.visStart, t.visEnd

	// imports
	var defaultEventEnd = t.defaultEventEnd;
	var normalizeEvent = calendar.normalizeEvent; // in EventManager
	var reportEventChange = calendar.reportEventChange;

	// locals
	var eventsByID = {};
	var eventElements = [];
	var eventElementsByID = {};
	var options = calendar.options;

	function opt(name, viewNameOverride) {
		var v = options[name];
		if (typeof v == 'object') {
			return smartProperty(v, viewNameOverride || viewName);
		}
		return v;
	}

	function trigger(name, thisObj) {
		return calendar.trigger.apply(
			calendar,
			[name, thisObj || t].concat(Array.prototype.slice.call(arguments, 2), [t])
		);
	}

	/*
	function setOverflowHidden(bool) {
		element.css('overflow', bool ? 'hidden' : '');
	}
	*/

	function isEventDraggable(event) {
		return isEventEditable(event) && !opt('disableDragging');
	}

	function isEventResizable(event) { // but also need to make sure the seg.isEnd == true
		return isEventEditable(event) && !opt('disableResizing');
	}

	function isEventEditable(event) {
		return firstDefined(event.editable, (event.source || {}).editable, opt('editable'));
	}

	/* Event Data
	------------------------------------------------------------------------------*/

	// report when view receives new events
	function reportEvents(events) { // events are already normalized at this point
		eventsByID = {};
		var i, len=events.length, event;
		for (i=0; i<len; i++) {
			event = events[i];
			if (eventsByID[event._id]) {
				eventsByID[event._id].push(event);
			}else{
				eventsByID[event._id] = [event];
			}
		}
	}

	// returns a Date object for an event's end
	function eventEnd(event) {
		return event.end ? cloneDate(event.end) : defaultEventEnd(event);
	}

	/* Event Elements
	------------------------------------------------------------------------------*/

	// report when view creates an element for an event
	function reportEventElement(event, element) {
		eventElements.push(element);
		if (eventElementsByID[event._id]) {
			eventElementsByID[event._id].push(element);
		}else{
			eventElementsByID[event._id] = [element];
		}
	}

	function reportEventClear() {
		eventElements = [];
		eventElementsByID = {};
	}

	// attaches eventClick, eventMouseover, eventMouseout
	function eventElementHandlers(event, eventElement) {
		eventElement
			.click(function(ev) {
				if (!eventElement.hasClass('ui-draggable-dragging') &&
					!eventElement.hasClass('ui-resizable-resizing')) {
						return trigger('eventClick', this, event, ev);
					}
			})
			.hover(
				function(ev) {
					trigger('eventMouseover', this, event, ev);
				},
				function(ev) {
					trigger('eventMouseout', this, event, ev);
				}
			);
		// TODO: don't fire eventMouseover/eventMouseout *while* dragging is occuring (on subject element)
		// TODO: same for resizing
	}

	function showEvents(event, exceptElement) {
		eachEventElement(event, exceptElement, 'show');
	}

	function hideEvents(event, exceptElement) {
		eachEventElement(event, exceptElement, 'hide');
	}

	function eachEventElement(event, exceptElement, funcName) {
		var elements = eventElementsByID[event._id],
			i, len = elements.length;
		for (i=0; i<len; i++) {
			if (!exceptElement || elements[i][0] != exceptElement[0]) {
				elements[i][funcName]();
			}
		}
	}

	/* Event Modification Reporting
	---------------------------------------------------------------------------------*/

	function eventDrop(e, event, dayDelta, minuteDelta, allDay, ev, ui) {
		var oldAllDay = event.allDay;
		var eventId = event._id;
		moveEvents(eventsByID[eventId], dayDelta, minuteDelta, allDay);
		trigger(
			'eventDrop',
			e,
			event,
			dayDelta,
			minuteDelta,
			allDay,
			function() {
				// TODO: investigate cases where this inverse technique might not work
				moveEvents(eventsByID[eventId], -dayDelta, -minuteDelta, oldAllDay);
				reportEventChange(eventId);
			},
			ev,
			ui
		);
		reportEventChange(eventId);
	}

	function eventResize(e, event, dayDelta, minuteDelta, ev, ui) {
		var eventId = event._id;
		elongateEvents(eventsByID[eventId], dayDelta, minuteDelta);
		trigger(
			'eventResize',
			e,
			event,
			dayDelta,
			minuteDelta,
			function() {
				// TODO: investigate cases where this inverse technique might not work
				elongateEvents(eventsByID[eventId], -dayDelta, -minuteDelta);
				reportEventChange(eventId);
			},
			ev,
			ui
		);
		reportEventChange(eventId);
	}

	/* Event Modification Math
	---------------------------------------------------------------------------------*/

	function moveEvents(events, dayDelta, minuteDelta, allDay) {
		minuteDelta = minuteDelta || 0;
		for (var e, len=events.length, i=0; i<len; i++) {
			e = events[i];
			if (allDay !== undefined) {
				e.allDay = allDay;
			}
			addMinutes(addDays(e.start, dayDelta, true), minuteDelta);
			if (e.end) {
				e.end = addMinutes(addDays(e.end, dayDelta, true), minuteDelta);
			} else {
				e.end = defaultEventEnd(e);
			}
			normalizeEvent(e, options);
		}
	}

	function elongateEvents(events, dayDelta, minuteDelta) {
		minuteDelta = minuteDelta || 0;
		for (var e, len=events.length, i=0; i<len; i++) {
			e = events[i];
			e.end = addMinutes(addDays(eventEnd(e), dayDelta, true), minuteDelta);
			normalizeEvent(e, options);
		}
	}

}
<|endoftext|>


<commit_before>'use strict';

const chalk = require('chalk');
const nodePlop = require('node-plop');
const fs = require('fs');

const defaultChoosingMessage = chalk.blue('[PLOP]') + ' Please choose a generator.';

module.exports = (function () {

	function chooseOptionFromList(plopList, message = defaultChoosingMessage) {
		const plop = nodePlop();
		const generator = plop.setGenerator('choose', {
			prompts: [{
				type: 'list',
				name: 'generator',
				message,
				choices: plopList.map(function (p) {
					return {
						name: p.name + chalk.gray(!!p.description ? ' - ' + p.description : ''),
						value: p.name
					};
				})
			}]
		});
		return generator.runPrompts().then(results => results.generator);
	}

	function displayHelpScreen() {
		console.log([
			'',
			chalk.bold('Usage:'),
			'  $ plop                 ' + chalk.dim('Select from a list of available generators'),
			'  $ plop <name>          ' + chalk.dim('Run a generator registered under that name'),
			'  $ plop <name> [input]  ' + chalk.dim('Run the generator with input data to bypass prompts'),
			'',
			chalk.bold('Options:'),
			'  -h, --help             ' + chalk.dim('Show this help display'),
			'  -i, --init             ' + chalk.dim('Generate a basic plopfile.js'),
			'  -v, --version          ' + chalk.dim('Print current version'),
			'  --plopfile             ' + chalk.dim('Path to the plopfile'),
			'  --completion           ' + chalk.dim('Method to handle bash/zsh/whatever completions'),
			'  --cwd                  ' + chalk.dim('Directory from which relative paths are calculated against'),
			'  --require              ' + chalk.dim('String or array of modules to require before running plop'),
			'',
			chalk.bold('Examples:'),
			'  $ ' + chalk.blue('plop'),
			'  $ ' + chalk.blue('plop component'),
			'  $ ' + chalk.blue('plop component "name of component"'),
			'',
		].join('\n'));
	}

	function createInitPlopfile(cwd, callback){
		var initString = 'module.exports = function (plop) {\n\n' +
			'\tplop.setGenerator(\'basics\', {\n' +
			'\t\tdescription: \'this is a skeleton plopfile\',\n' +
			'\t\tprompts: [],\n' +
			'\t\tactions: []\n' +
			'\t});\n\n' +
			'};';

		fs.writeFile(cwd + '/plopfile.js', initString, callback);
	}

	return {
		chooseOptionFromList: chooseOptionFromList,
		displayHelpScreen: displayHelpScreen,
		createInitPlopfile: createInitPlopfile
	};
})();
<commit_msg>Make Node 4 compatible<commit_after>'use strict';

const chalk = require('chalk');
const nodePlop = require('node-plop');
const fs = require('fs');

const defaultChoosingMessage = chalk.blue('[PLOP]') + ' Please choose a generator.';

module.exports = (function () {

	function chooseOptionFromList(plopList, message) {
		const plop = nodePlop();
		const generator = plop.setGenerator('choose', {
			prompts: [{
				type: 'list',
				name: 'generator',
				message: message || defaultChoosingMessage,
				choices: plopList.map(function (p) {
					return {
						name: p.name + chalk.gray(!!p.description ? ' - ' + p.description : ''),
						value: p.name
					};
				})
			}]
		});
		return generator.runPrompts().then(results => results.generator);
	}

	function displayHelpScreen() {
		console.log([
			'',
			chalk.bold('Usage:'),
			'  $ plop                 ' + chalk.dim('Select from a list of available generators'),
			'  $ plop <name>          ' + chalk.dim('Run a generator registered under that name'),
			'  $ plop <name> [input]  ' + chalk.dim('Run the generator with input data to bypass prompts'),
			'',
			chalk.bold('Options:'),
			'  -h, --help             ' + chalk.dim('Show this help display'),
			'  -i, --init             ' + chalk.dim('Generate a basic plopfile.js'),
			'  -v, --version          ' + chalk.dim('Print current version'),
			'  --plopfile             ' + chalk.dim('Path to the plopfile'),
			'  --completion           ' + chalk.dim('Method to handle bash/zsh/whatever completions'),
			'  --cwd                  ' + chalk.dim('Directory from which relative paths are calculated against'),
			'  --require              ' + chalk.dim('String or array of modules to require before running plop'),
			'',
			chalk.bold('Examples:'),
			'  $ ' + chalk.blue('plop'),
			'  $ ' + chalk.blue('plop component'),
			'  $ ' + chalk.blue('plop component "name of component"'),
			'',
		].join('\n'));
	}

	function createInitPlopfile(cwd, callback){
		var initString = 'module.exports = function (plop) {\n\n' +
			'\tplop.setGenerator(\'basics\', {\n' +
			'\t\tdescription: \'this is a skeleton plopfile\',\n' +
			'\t\tprompts: [],\n' +
			'\t\tactions: []\n' +
			'\t});\n\n' +
			'};';

		fs.writeFile(cwd + '/plopfile.js', initString, callback);
	}

	return {
		chooseOptionFromList: chooseOptionFromList,
		displayHelpScreen: displayHelpScreen,
		createInitPlopfile: createInitPlopfile
	};
})();
<|endoftext|>


<commit_before>if (!Array.prototype.forEach) {
  Array.prototype.forEach = function(fn, ctx) {
    'use strict';
    if (this === void 0 || this === null || typeof fn !== 'function') {
      throw new TypeError();
    }
    var t = this;
    var len = t.length;
    for (var i = 0; i < len; i++) {
      if (i in t) { fn.call(ctx, t[i], i, t); }
    }
  };
}
if (!Function.prototype.bind) {
  Function.prototype.bind = function (context) {
    'use strict';
    if (typeof this !== 'function') {
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }
    var curried = Array.prototype.slice.call(arguments, 1);
    var original = this;
    var NoOp = function () {};
    var bound = function () {
      var ctx = this instanceof NoOp && context ? this : context;
      var args = curried.concat(Array.prototype.slice.call(arguments));
      return original.apply(ctx, args);
    };
    NoOp.prototype = this.prototype;
    bound.prototype = new NoOp();
    return bound;
  };
}
if (!Object.keys) {
  Object.keys = function (o) {
    'use strict';
    var keys = [];
    for (var k in o) {
      if (o.hasOwnProperty(k)) {
        keys.push(k);
      }
    }
    return keys;
  };
}
<commit_msg>filter shim<commit_after>if (!Array.prototype.forEach) {
  Array.prototype.forEach = function(fn, ctx) {
    'use strict';
    if (this === void 0 || this === null || typeof fn !== 'function') {
      throw new TypeError();
    }
    var t = this;
    var len = t.length;
    for (var i = 0; i < len; i++) {
      if (i in t) { fn.call(ctx, t[i], i, t); }
    }
  };
}
if (!Array.prototype.filter) {
  Array.prototype.filter = function (fn, ctx) {
    'use strict';
    if (this === void 0 || this === null || typeof fn !== 'function') {
      throw new TypeError();
    }
    var t = this;
    var len = t.length;
    var f = [];
    for (var i = 0; i < len; i++) {
      if (i in t) {
        var val = t[i];
        if (fn.call(ctx, val, i, t)) { f.push(val); }
      }
    }
    return f;
  };
}
if (!Function.prototype.bind) {
  Function.prototype.bind = function (context) {
    'use strict';
    if (typeof this !== 'function') {
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }
    var curried = Array.prototype.slice.call(arguments, 1);
    var original = this;
    var NoOp = function () {};
    var bound = function () {
      var ctx = this instanceof NoOp && context ? this : context;
      var args = curried.concat(Array.prototype.slice.call(arguments));
      return original.apply(ctx, args);
    };
    NoOp.prototype = this.prototype;
    bound.prototype = new NoOp();
    return bound;
  };
}
if (!Object.keys) {
  Object.keys = function (o) {
    'use strict';
    var keys = [];
    for (var k in o) {
      if (o.hasOwnProperty(k)) {
        keys.push(k);
      }
    }
    return keys;
  };
}
<|endoftext|>


<commit_before>/**
 * @fileOverview Requirejs modifier for default XHR-based network operations
 *
 * @preserve Copyright (c) 2013 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

require.def(
	'antie/devices/net/default',
	['antie/devices/browserdevice'],
	function(Device) {
        'use strict';

		/**
		 * Loads an external script that calls a specified callback function.
		 * Used for loading data via JSON-P.
		 * @param {String} url The URL of the script.
		 * @param {RegExp} callbackFunctionRegExp Regular expression to replace matches with callback function name.
		 * @param {Object} callbacks Object containing onSuccess and onLoad callback functions.
		 * @param {Integer} timeout Timeout in milliseconds.
		 * @param {String} [callbackSuffix] Suffix to append to end of callback function name.
		 * @returns The script element that will load the script.
		 */
		Device.prototype.loadScript = function(url, callbackFunctionRegExp, callbacks, timeout, callbackSuffix) {
			var self = this;
			var script = null;
			var funcName = "_antie_callback_" + (callbackSuffix || ((new Date() * 1) + "_" + Math.floor(Math.random() * 10000000)));

			if (window[funcName])
				throw "A request with the name " + funcName + " is already in flight";

			var timeoutHandle = window.setTimeout(function() {
				if (window[funcName]) {
					if (script) {
						self.removeElement(script);
					}
					delete window[funcName];
					if (callbacks && callbacks.onError) {
						callbacks.onError('timeout');
					}
				}
			}, timeout || 5000);

			window[funcName] = function(obj) {
				if (timeout) {
					window.clearTimeout(timeoutHandle);
				}
				if (callbacks && callbacks.onSuccess) {
					callbacks.onSuccess(obj);
				}
				self.removeElement(script);
				delete window[funcName];
			};

			script = this._createElement("script");
			script.src = url.replace(callbackFunctionRegExp, funcName);
			var head = document.getElementsByTagName("head")[0];
			head.appendChild(script);
			return script;
		};

		/**
		 * Loads a resource from a URL protected by device authentication.
		 * @param {String} url The URL to load.
		 * @param {Object} opts Object containing onLoad and onError callback functions.
		 * @returns The request object used to load the resource.
		 */
		Device.prototype.loadAuthenticatedURL = function(url, opts) {
			// Simple implementation - assuming XHR in browser can perform client-authenticated SSL requests
			return this.loadURL(url, opts);
		};
		/**
		 * Loads a resource from a URL.
		 * @param {String} url The URL to load.
		 * @param {Object} opts Object containing onLoad and onError callback functions.
		 * @returns The request object used to load the resource.
		 */
		Device.prototype.loadURL = function(url, opts) {
			var xhr = new XMLHttpRequest();
			xhr.open(opts.method || 'GET', url, true);
			xhr.onreadystatechange = function() {
				if (this.readyState === 4) {
					this.onreadystatechange = null;
					if (this.status >= 200 && this.status < 300) {
						if (opts.onLoad) {
							opts.onLoad(this.responseText, this.status);
						}
					} else {
						if (opts.onError) {
							opts.onError(this.responseText, this.status);
						}
					}
				}
			};
			if (opts && opts.headers) {
				for (var header in opts.headers) {
					xhr.setRequestHeader(header, opts.headers[header]);
				}
			}

			try {
				xhr.send(opts.data || null);
			} catch(ex) {
				if (opts.onError) {
					opts.onError(ex);
				}
			}
			return xhr;
		};
		/**
		 * Performs a POST HTTP request to a URL on a different host/domain.
		 * @param {String} url The URL to post to.
		 * @param {Object} data Associative array of fields/values to post.
		 * @param {Object} opts Object containing onLoad and onError callback functions.
		 */
		Device.prototype.crossDomainPost = function(url, data, opts) {
			var iframe, form;
            var postRequestHasBeenSent = false;
            var blankPageToLoad = opts.blankUrl || "blank.html";
            var timeoutHandle;

			function iframeLoadTimeoutCallback() {
				iframe.onload = null;
				if(opts.onError) opts.onError("timeout");
			}

			function iframeLoadedCallback() {
				var urlLoadedIntoInvisibleIFrame, errorGettingIFrameLocation;
				try {
					urlLoadedIntoInvisibleIFrame = iframe.contentWindow.location.href;
				} catch (exception) {
                    errorGettingIFrameLocation = exception;
				}

				if(errorGettingIFrameLocation || !urlLoadedIntoInvisibleIFrame) {
					// we didn't load the page - give the browser a second chance to load the iframe
                    setTimeout(function() { iframe.src = blankPageToLoad+"#2"; }, 500);
                    return;
				}

                if (postRequestHasBeenSent === false) {
                    postRequestHasBeenSent = true;

                    createForm();
                    for(var name in data) {
                        createField(name, data[name]);
                    }
                    form.submit();
                }
                else {
                    if (timeoutHandle){
                        clearTimeout(timeoutHandle);
                    }

                    iframe.onload = null;
                    try {
                        var responseData = iframe.contentWindow.name;
                        iframe.parentNode.removeChild(iframe);
                        if (opts.onLoad) {
                            opts.onLoad(responseData);
                        }
                    } catch (exception) {
                        if(opts.onError) opts.onError(exception);
                    }
                }
            }

			function createForm() {
				var doc = iframe.contentWindow.document;
				form = doc.createElement('form');
				form.method = 'POST';
				form.action = url;
				doc.body.appendChild(form);
			}

			function createField(name, value) {
				var input = document.createElement('input');
				input.type = "hidden";
				input.name = name;
				input.value = value;
				form.appendChild(input);
			}

			function createIframe() {
				iframe = document.createElement('iframe');
				iframe.style.width = "0";
				iframe.style.height = "0";
				iframe.src = blankPageToLoad+"#1";
				iframe.onload = iframeLoadedCallback;
				document.body.appendChild(iframe);
			}

			timeoutHandle = setTimeout(iframeLoadTimeoutCallback, (opts.timeout || 10) * 1000); /* 10 second default */
			createIframe();
		};

        /**
         * Performs a cross domain GET for a decoded JSON object utilising CORS if supported by
         * the device, falling back to a JSON-P call otherwise.
         * @param {String} url The URL to load. A callback GET parameter will be appended if JSON-P is used.
         * @param {Object} opts Object containing onSuccess and onError callbacks. onSuccess will be called
         * with the decoded JSON object if the call is successful. This object may also include an optional token value,
         * used when making requests for resources that require authentication. For CORS requests, the token is used as
         * a Bearer token in an Authorization header (see RFC 6750, section 2.1), and for JSON-P requests the token is
         * included as a query string parameter. If not specified, no token is included in the request.
         * @param {Object} [jsonPOptions] Options for the JSON-P fallback behaviour. All optional with sensible defaults.
         * @param {Number} [jsonPOptions.timeout=5000] Timeout for the JSON-P call in ms. Default: 5000.
         * @param {String} [jsonPOptions.id] Used in the callback function name for the JSON-P call. Default: a random string.
         * @param {String} [jsonPOptions.callbackKey=callback] Key to use in query string when passing callback function name
         * for JSON-P call. Default: callback
         */
        Device.prototype.executeCrossDomainGet = function(url, opts, jsonPOptions) {
            var self, callbackKey, callbackQuery, modifiedOpts;
            self = this;
            jsonPOptions = jsonPOptions || {};
            if (configSupportsCORS(this.getConfig())) {
                modifiedOpts = {
                    onLoad: function(jsonResponse) {
                        opts.onSuccess(self.decodeJson(jsonResponse));
                    },
                    onError: opts.onError
                };

                if (opts.token) {
                    modifiedOpts.headers = {
                        Authorization : "Bearer " + opts.token
                    };
                }

                this.loadURL(url, modifiedOpts);
            } else {
                callbackKey = jsonPOptions.callbackKey || 'callback';
                callbackQuery = '?' + callbackKey + '=%callback%';
                if(url.indexOf('?') === -1) {
                    url = url + callbackQuery;
                } else {
                    url = url.replace('?', callbackQuery + '&');
                }

                if (opts.token) {
                    url = url + "&token=" + opts.token;
                }

                this.loadScript(url, /%callback%/, opts, jsonPOptions.timeout, jsonPOptions.id);
            }
        };

        /**
         * Performs a cross domain POST HTTP using CORS or the content delivered as a single form field value depending on device capability
         * @param {String} url The URL to post to.
         * @param {Object} data JavaScript object to be JSON encoded and delivered as payload.
         * @param {Object} opts Object containing onLoad and onError callback functions and a fieldName property to be
         * used for the name of the form filed if the iframe hack is used. This object may also include an optional token value,
         * used when making requests for resources that require authentication. For CORS requests, the token is used as
         * a Bearer token in an Authorization header (see RFC 6750, section 2.1), and for form requests the token is
         * included as a token form field value. If not specified, no token is included in the request.
         */
        Device.prototype.executeCrossDomainPost = function(url, data, opts) {
            var payload, modifiedOpts, formData, header;
            payload = this.encodeJson(data);
            if (configSupportsCORS(this.getConfig())) {
                modifiedOpts = {
                    onLoad: opts.onLoad,
                    onError: opts.onError,
                    headers: {
                        "Content-Type": "application/json"
                    },
                    data: payload,
                    method: "POST"
                };

                if (opts.token) {
                    modifiedOpts.headers.Authorization = "Bearer " + opts.token;
                }

                this.loadURL(url, modifiedOpts);
            } else {
                formData = {};
                formData[opts.fieldName] = payload;

                if (opts.token) {
                   formData.token = opts.token;
                }

                this.crossDomainPost(url, formData, {
                    onLoad: opts.onLoad,
                    onError: opts.onError,
                    blankUrl: opts.blankUrl
                });
            }
        };

        function configSupportsCORS(config) {
            return config && config.networking && config.networking.supportsCORS;
        }
	}
);

<commit_msg>Rename jsonPOptions parameter to jsonpOptions (case change)<commit_after>/**
 * @fileOverview Requirejs modifier for default XHR-based network operations
 *
 * @preserve Copyright (c) 2013 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

require.def(
	'antie/devices/net/default',
	['antie/devices/browserdevice'],
	function(Device) {
        'use strict';

		/**
		 * Loads an external script that calls a specified callback function.
		 * Used for loading data via JSON-P.
		 * @param {String} url The URL of the script.
		 * @param {RegExp} callbackFunctionRegExp Regular expression to replace matches with callback function name.
		 * @param {Object} callbacks Object containing onSuccess and onLoad callback functions.
		 * @param {Integer} timeout Timeout in milliseconds.
		 * @param {String} [callbackSuffix] Suffix to append to end of callback function name.
		 * @returns The script element that will load the script.
		 */
		Device.prototype.loadScript = function(url, callbackFunctionRegExp, callbacks, timeout, callbackSuffix) {
			var self = this;
			var script = null;
			var funcName = "_antie_callback_" + (callbackSuffix || ((new Date() * 1) + "_" + Math.floor(Math.random() * 10000000)));

			if (window[funcName])
				throw "A request with the name " + funcName + " is already in flight";

			var timeoutHandle = window.setTimeout(function() {
				if (window[funcName]) {
					if (script) {
						self.removeElement(script);
					}
					delete window[funcName];
					if (callbacks && callbacks.onError) {
						callbacks.onError('timeout');
					}
				}
			}, timeout || 5000);

			window[funcName] = function(obj) {
				if (timeout) {
					window.clearTimeout(timeoutHandle);
				}
				if (callbacks && callbacks.onSuccess) {
					callbacks.onSuccess(obj);
				}
				self.removeElement(script);
				delete window[funcName];
			};

			script = this._createElement("script");
			script.src = url.replace(callbackFunctionRegExp, funcName);
			var head = document.getElementsByTagName("head")[0];
			head.appendChild(script);
			return script;
		};

		/**
		 * Loads a resource from a URL protected by device authentication.
		 * @param {String} url The URL to load.
		 * @param {Object} opts Object containing onLoad and onError callback functions.
		 * @returns The request object used to load the resource.
		 */
		Device.prototype.loadAuthenticatedURL = function(url, opts) {
			// Simple implementation - assuming XHR in browser can perform client-authenticated SSL requests
			return this.loadURL(url, opts);
		};
		/**
		 * Loads a resource from a URL.
		 * @param {String} url The URL to load.
		 * @param {Object} opts Object containing onLoad and onError callback functions.
		 * @returns The request object used to load the resource.
		 */
		Device.prototype.loadURL = function(url, opts) {
			var xhr = new XMLHttpRequest();
			xhr.open(opts.method || 'GET', url, true);
			xhr.onreadystatechange = function() {
				if (this.readyState === 4) {
					this.onreadystatechange = null;
					if (this.status >= 200 && this.status < 300) {
						if (opts.onLoad) {
							opts.onLoad(this.responseText, this.status);
						}
					} else {
						if (opts.onError) {
							opts.onError(this.responseText, this.status);
						}
					}
				}
			};
			if (opts && opts.headers) {
				for (var header in opts.headers) {
					xhr.setRequestHeader(header, opts.headers[header]);
				}
			}

			try {
				xhr.send(opts.data || null);
			} catch(ex) {
				if (opts.onError) {
					opts.onError(ex);
				}
			}
			return xhr;
		};
		/**
		 * Performs a POST HTTP request to a URL on a different host/domain.
		 * @param {String} url The URL to post to.
		 * @param {Object} data Associative array of fields/values to post.
		 * @param {Object} opts Object containing onLoad and onError callback functions.
		 */
		Device.prototype.crossDomainPost = function(url, data, opts) {
			var iframe, form;
            var postRequestHasBeenSent = false;
            var blankPageToLoad = opts.blankUrl || "blank.html";
            var timeoutHandle;

			function iframeLoadTimeoutCallback() {
				iframe.onload = null;
				if(opts.onError) opts.onError("timeout");
			}

			function iframeLoadedCallback() {
				var urlLoadedIntoInvisibleIFrame, errorGettingIFrameLocation;
				try {
					urlLoadedIntoInvisibleIFrame = iframe.contentWindow.location.href;
				} catch (exception) {
                    errorGettingIFrameLocation = exception;
				}

				if(errorGettingIFrameLocation || !urlLoadedIntoInvisibleIFrame) {
					// we didn't load the page - give the browser a second chance to load the iframe
                    setTimeout(function() { iframe.src = blankPageToLoad+"#2"; }, 500);
                    return;
				}

                if (postRequestHasBeenSent === false) {
                    postRequestHasBeenSent = true;

                    createForm();
                    for(var name in data) {
                        createField(name, data[name]);
                    }
                    form.submit();
                }
                else {
                    if (timeoutHandle){
                        clearTimeout(timeoutHandle);
                    }

                    iframe.onload = null;
                    try {
                        var responseData = iframe.contentWindow.name;
                        iframe.parentNode.removeChild(iframe);
                        if (opts.onLoad) {
                            opts.onLoad(responseData);
                        }
                    } catch (exception) {
                        if(opts.onError) opts.onError(exception);
                    }
                }
            }

			function createForm() {
				var doc = iframe.contentWindow.document;
				form = doc.createElement('form');
				form.method = 'POST';
				form.action = url;
				doc.body.appendChild(form);
			}

			function createField(name, value) {
				var input = document.createElement('input');
				input.type = "hidden";
				input.name = name;
				input.value = value;
				form.appendChild(input);
			}

			function createIframe() {
				iframe = document.createElement('iframe');
				iframe.style.width = "0";
				iframe.style.height = "0";
				iframe.src = blankPageToLoad+"#1";
				iframe.onload = iframeLoadedCallback;
				document.body.appendChild(iframe);
			}

			timeoutHandle = setTimeout(iframeLoadTimeoutCallback, (opts.timeout || 10) * 1000); /* 10 second default */
			createIframe();
		};

        /**
         * Performs a cross domain GET for a decoded JSON object utilising CORS if supported by
         * the device, falling back to a JSON-P call otherwise.
         * @param {String} url The URL to load. A callback GET parameter will be appended if JSON-P is used.
         * @param {Object} opts Object containing onSuccess and onError callbacks. onSuccess will be called
         * with the decoded JSON object if the call is successful. This object may also include an optional token value,
         * used when making requests for resources that require authentication. For CORS requests, the token is used as
         * a Bearer token in an Authorization header (see RFC 6750, section 2.1), and for JSON-P requests the token is
         * included as a query string parameter. If not specified, no token is included in the request.
         * @param {Object} [jsonpOptions] Options for the JSON-P fallback behaviour. All optional with sensible defaults.
         * @param {Number} [jsonpOptions.timeout=5000] Timeout for the JSON-P call in ms. Default: 5000.
         * @param {String} [jsonpOptions.id] Used in the callback function name for the JSON-P call. Default: a random string.
         * @param {String} [jsonpOptions.callbackKey=callback] Key to use in query string when passing callback function name
         * for JSON-P call. Default: callback
         */
        Device.prototype.executeCrossDomainGet = function(url, opts, jsonpOptions) {
            var self, callbackKey, callbackQuery, modifiedOpts;
            self = this;
            jsonpOptions = jsonpOptions || {};
            if (configSupportsCORS(this.getConfig())) {
                modifiedOpts = {
                    onLoad: function(jsonResponse) {
                        opts.onSuccess(self.decodeJson(jsonResponse));
                    },
                    onError: opts.onError
                };

                if (opts.token) {
                    modifiedOpts.headers = {
                        Authorization : "Bearer " + opts.token
                    };
                }

                this.loadURL(url, modifiedOpts);
            } else {
                callbackKey = jsonpOptions.callbackKey || 'callback';
                callbackQuery = '?' + callbackKey + '=%callback%';
                if(url.indexOf('?') === -1) {
                    url = url + callbackQuery;
                } else {
                    url = url.replace('?', callbackQuery + '&');
                }

                if (opts.token) {
                    url = url + "&token=" + opts.token;
                }

                this.loadScript(url, /%callback%/, opts, jsonpOptions.timeout, jsonpOptions.id);
            }
        };

        /**
         * Performs a cross domain POST HTTP using CORS or the content delivered as a single form field value depending on device capability
         * @param {String} url The URL to post to.
         * @param {Object} data JavaScript object to be JSON encoded and delivered as payload.
         * @param {Object} opts Object containing onLoad and onError callback functions and a fieldName property to be
         * used for the name of the form filed if the iframe hack is used. This object may also include an optional token value,
         * used when making requests for resources that require authentication. For CORS requests, the token is used as
         * a Bearer token in an Authorization header (see RFC 6750, section 2.1), and for form requests the token is
         * included as a token form field value. If not specified, no token is included in the request.
         */
        Device.prototype.executeCrossDomainPost = function(url, data, opts) {
            var payload, modifiedOpts, formData, header;
            payload = this.encodeJson(data);
            if (configSupportsCORS(this.getConfig())) {
                modifiedOpts = {
                    onLoad: opts.onLoad,
                    onError: opts.onError,
                    headers: {
                        "Content-Type": "application/json"
                    },
                    data: payload,
                    method: "POST"
                };

                if (opts.token) {
                    modifiedOpts.headers.Authorization = "Bearer " + opts.token;
                }

                this.loadURL(url, modifiedOpts);
            } else {
                formData = {};
                formData[opts.fieldName] = payload;

                if (opts.token) {
                   formData.token = opts.token;
                }

                this.crossDomainPost(url, formData, {
                    onLoad: opts.onLoad,
                    onError: opts.onError,
                    blankUrl: opts.blankUrl
                });
            }
        };

        function configSupportsCORS(config) {
            return config && config.networking && config.networking.supportsCORS;
        }
	}
);

<|endoftext|>


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

  angular
    .module('crowdsource.routes', ['ngRoute'])
    .config(config);

  config.$inject = ['$routeProvider'];

  /**
  * @name config
  * @desc Define valid application routes
  */
  function config($routeProvider) {
    $routeProvider.when('/', {
      templateUrl: '/static/templates/intro.html',
    })

    .when('/home', {
      templateUrl: '/static/templates/home.html',
      controller: 'HomeController',
    })

    .when('/ranking', {
      templateUrl: '/static/templates/ranking/requesterrank.html',
      controller: 'RankingController',
    })

    //We will merge tasklistSearch and tasklist to one component, please keep it separate for now.
    .when('/tasklistSearch', {
    templateUrl: '/static/templates/tasksearches/tasklistSearch.html',
    controller: 'taskSearchGridController',
    })

    .when('/requester', {
      templateUrl: '/static/templates/requester/home.html',
      controller: 'HomeController',
    })

    .when('/tasklist', {
      templateUrl: '/static/templates/task/tasklist.html',
      controller: 'taskController',
    })

    .when('/ImageLabel', {
      templateUrl: '/static/templates/task/ImageLabel.html'
    })

    .when('/register', {
      controller: 'RegisterController',
      controllerAs: 'vm',
      templateUrl: '/static/templates/authentication/register.html'
    })

    .when('/login', {
      controller: 'LoginController',
      controllerAs: 'vm',
      templateUrl: '/static/templates/authentication/login.html'
    })

    .when('/profile', {
      templateUrl: '/static/templates/home.html'
    })

    .when('/terms', {
      templateUrl: '/static/templates/terms.html'
    })

    .when('/contributors', {
      templateUrl: '/static/templates/contributors/home.html'
    })

  /**
   * Location for contributor urls. Include your personal page url here.
   */
    .when('/contributors/rohit', {
      templateUrl: '/static/templates/contributors/rohit.html'
    })

    .when('/contributors/amx', {
      templateUrl: '/static/templates/contributors/amx.html'
    })

    .when('/contributors/aneesha', {
      templateUrl: '/static/templates/contributors/aneesha.html'
    })

    .when('/contributors/anirudh', {
      templateUrl: '/static/templates/contributors/anirudh.html'
    })

  	.when('/contributors/shirish', {

      templateUrl: '/static/templates/contributors/shirish.html'
    })

    .when('/contributors/ard', {
      templateUrl: '/static/templates/contributors/ard.html'
    })

    .when('/contributors/narwal', {
      templateUrl: '/static/templates/contributors/narwal.html'
    })

    .when('/contributors/sangm', {
      templateUrl: '/static/templates/contributors/sangm.html'
    })

    .when('/contributors/sean', {
      templateUrl: '/static/templates/contributors/sean.html'
    })

     .when('/contributors/leek', {
      templateUrl: '/static/templates/contributors/leek.html'
    })

    .when('/contributors/karan', {
      templateUrl: '/static/templates/contributors/karan.html'
    })

    .when('/contributors/vaidehi', {
      templateUrl: '/static/templates/contributors/vaidehi.html'
    })

    .when('/contributors/jason', {
      templateUrl: '/static/templates/contributors/jason.html'
    })

    .when('/contributors/lucamatsumoto', {
      templateUrl: '/static/templates/contributors/lucamatsumoto.html'
    })

    .when('/contributors/arcolife', {
      templateUrl: '/static/templates/contributors/arcolife.html'
    })

    .when('/contributors/AditiNath', {
      templateUrl: '/static/templates/contributors/aditinath.html'
    })

    .when('/contributors/Milstein', {
      templateUrl: '/static/templates/contributors/milstein.html'
    })

    .otherwise('/');
  }
})();
<commit_msg>updated the route file conflict<commit_after>(function () {
  'use strict';

  angular
    .module('crowdsource.routes', ['ngRoute'])
    .config(config);

  config.$inject = ['$routeProvider'];

  /**
  * @name config
  * @desc Define valid application routes
  */
  function config($routeProvider) {
    $routeProvider.when('/', {
      templateUrl: '/static/templates/intro.html',
    })

    .when('/home', {
      templateUrl: '/static/templates/home.html',
      controller: 'HomeController',
    })

    .when('/ranking', {
      templateUrl: '/static/templates/ranking/requesterrank.html',
      controller: 'RankingController',
    })

    //We will merge tasklistSearch and tasklist to one component, please keep it separate for now.
    .when('/tasklistSearch', {
    templateUrl: '/static/templates/tasksearches/tasklistSearch.html',
    controller: 'taskSearchGridController',
    })

    .when('/requester', {
      templateUrl: '/static/templates/requester/home.html',
      controller: 'HomeController',
    })

    .when('/tasklist', {
      templateUrl: '/static/templates/task/tasklist.html',
      controller: 'taskController',
    })

    .when('/ImageLabel', {
      templateUrl: '/static/templates/task/ImageLabel.html'
    })

    .when('/register', {
      controller: 'RegisterController',
      controllerAs: 'vm',
      templateUrl: '/static/templates/authentication/register.html'
    })

    .when('/login', {
      controller: 'LoginController',
      controllerAs: 'vm',
      templateUrl: '/static/templates/authentication/login.html'
    })

    .when('/profile', {
      templateUrl: '/static/templates/home.html'
    })

    .when('/terms', {
      templateUrl: '/static/templates/terms.html'
    })

    .when('/contributors', {
      templateUrl: '/static/templates/contributors/home.html'
    })

  /**
   * Location for contributor urls. Include your personal page url here.
   */
    .when('/contributors/rohit', {
      templateUrl: '/static/templates/contributors/rohit.html'
    })

    .when('/contributors/amx', {
      templateUrl: '/static/templates/contributors/amx.html'
    })

    .when('/contributors/aneesha', {
      templateUrl: '/static/templates/contributors/aneesha.html'
    })

    .when('/contributors/anirudh', {
      templateUrl: '/static/templates/contributors/anirudh.html'
    })

  	.when('/contributors/shirish', {

      templateUrl: '/static/templates/contributors/shirish.html'
    })

    .when('/contributors/ard', {
      templateUrl: '/static/templates/contributors/ard.html'
    })

    .when('/contributors/narwal', {
      templateUrl: '/static/templates/contributors/narwal.html'
    })

    .when('/contributors/sangm', {
      templateUrl: '/static/templates/contributors/sangm.html'
    })

    .when('/contributors/sean', {
      templateUrl: '/static/templates/contributors/sean.html'
    })

     .when('/contributors/leek', {
      templateUrl: '/static/templates/contributors/leek.html'
    })

    .when('/contributors/karan', {
      templateUrl: '/static/templates/contributors/karan.html'
    })

    .when('/contributors/vaidehi', {
      templateUrl: '/static/templates/contributors/vaidehi.html'
    })

    .when('/contributors/jason', {
      templateUrl: '/static/templates/contributors/jason.html'
    })

    .when('/contributors/lucamatsumoto', {
      templateUrl: '/static/templates/contributors/lucamatsumoto.html'
    })

    .when('/contributors/arcolife', {
      templateUrl: '/static/templates/contributors/arcolife.html'
    })

    .when('/contributors/AditiNath', {
      templateUrl: '/static/templates/contributors/aditinath.html'
    })

    .when('/contributors/AmitRakesh', {
		templateUrl: '/static/templates/contributors/amitrakesh.html'
    })

    .when('/contributors/Milstein', {
      templateUrl: '/static/templates/contributors/milstein.html'
    })

    .otherwise('/');
  }
})();
<|endoftext|>


<commit_before> // Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Offline message screen implementation.
 */

cr.define('login', function() {
  // Screens that should have offline message overlay.
  /** @const */ var MANAGED_SCREENS = ['gaia-signin'];

  // Network state constants.
  var NET_STATE = {
    OFFLINE: 0,
    ONLINE: 1,
    PORTAL: 2
  };

  // Error reasons which are passed to updateState_() method.
  /** @const */ var ERROR_REASONS = {
    PROXY_AUTH_CANCELLED: 'frame error:111',
    PROXY_CONNECTION_FAILED: 'frame error:130',
    PROXY_CONFIG_CHANGED: 'proxy changed',
    LOADING_TIMEOUT: 'loading timeout',
    PORTAL_DETECTED: 'portal detected'
  };

  // Frame loading errors.
  var NET_ERROR = {
    ABORTED_BY_USER: 3
  };

  // Link which starts guest session for captive portal fixing.
  /** @const */ var FIX_CAPTIVE_PORTAL_ID = 'captive-portal-fix-link';

  /** @const */ var FIX_PROXY_SETTINGS_ID = 'proxy-settings-fix-link';

  // Id of the element which holds current network name.
  /** @const */ var CURRENT_NETWORK_NAME_ID = 'captive-portal-network-name';

  // Link which triggers frame reload.
  /** @const */ var RELOAD_PAGE_ID = 'proxy-error-retry-link';

  /**
   * Creates a new offline message screen div.
   * @constructor
   * @extends {HTMLDivElement}
   */
  var ErrorMessageScreen = cr.ui.define('div');

  /**
   * Registers with Oobe.
   */
  ErrorMessageScreen.register = function() {
    var screen = $('error-message');
    ErrorMessageScreen.decorate(screen);

    // Note that ErrorMessageScreen is not registered with Oobe because
    // it is shown on top of sign-in screen instead of as an independent screen.
  };

  ErrorMessageScreen.prototype = {
    __proto__: HTMLDivElement.prototype,

    /** @inheritDoc */
    decorate: function() {
      chrome.send('loginAddNetworkStateObserver',
                  ['login.ErrorMessageScreen.updateState']);

      cr.ui.DropDown.decorate($('offline-networks-list'));
      this.updateLocalizedContent_();
    },

    /**
     * Updates localized content of the screen that is not updated via template.
     */
    updateLocalizedContent_: function() {
      $('captive-portal-message-text').innerHTML = localStrings.getStringF(
        'captivePortalMessage',
        '',
        '',
        '');
      $(FIX_CAPTIVE_PORTAL_ID).onclick = function() {
        chrome.send('showCaptivePortal');
      };

      $('captive-portal-proxy-message-text').innerHTML =
        localStrings.getStringF(
          'captivePortalProxyMessage',
          '',
          '');
      $(FIX_PROXY_SETTINGS_ID).onclick = function() {
        chrome.send('openProxySettings');
      };

      $('proxy-message-text').innerHTML = localStrings.getStringF(
          'proxyMessageText',
          '',
          '');
      $(RELOAD_PAGE_ID).onclick = function() {
        var currentScreen = Oobe.getInstance().currentScreen;
        // Schedules a immediate retry.
        currentScreen.doReload();
      };

      $('error-guest-signin').innerHTML = localStrings.getStringF(
          'guestSignin',
          '',
          '');
      $('error-guest-signin-link').onclick = function() {
        chrome.send('launchIncognito');
      };

      $('error-offline-login').innerHTML = localStrings.getStringF(
          'offlineLogin',
          '',
          '');
      $('error-offline-login-link').onclick = function() {
        chrome.send('offlineLogin');
      };
    },

    onBeforeShow: function(lastNetworkType) {
      var currentScreen = Oobe.getInstance().currentScreen;

      cr.ui.DropDown.show('offline-networks-list', false, lastNetworkType);

      $('error-guest-signin').hidden = $('guestSignin').hidden ||
          !$('add-user-header-bar-item').hidden;

      $('error-offline-login').hidden = !currentScreen.isOfflineAllowed;
    },

    onBeforeHide: function() {
      cr.ui.DropDown.hide('offline-networks-list');
    },

    update: function() {
      chrome.send('loginRequestNetworkState',
                  ['login.ErrorMessageScreen.updateState',
                   'update']);
    },

    /**
     * Shows or hides offline message based on network on/offline state.
     * @param {Integer} state Current state of the network (see NET_STATE).
     * @param {string} network Name of the current network.
     * @param {string} reason Reason the callback was called.
     * @param {int} lastNetworkType Last active network type.
     */
    updateState_: function(state, network, reason, lastNetworkType) {
      var currentScreen = Oobe.getInstance().currentScreen;
      var offlineMessage = this;
      var isOnline = (state == NET_STATE.ONLINE);
      var isUnderCaptivePortal = (state == NET_STATE.PORTAL);
      var isProxyError = reason == ERROR_REASONS.PROXY_AUTH_CANCELLED ||
          reason == ERROR_REASONS.PROXY_CONNECTION_FAILED;
      var shouldOverlay = MANAGED_SCREENS.indexOf(currentScreen.id) != -1 &&
          !currentScreen.isLocal;
      var isTimeout = false;
      var isShown = !offlineMessage.classList.contains('hidden') &&
          !offlineMessage.classList.contains('faded');

      if (reason == ERROR_REASONS.PROXY_CONFIG_CHANGED && shouldOverlay &&
          isShown) {
        // Schedules a immediate retry.
        currentScreen.doReload();
        console.log('Retry page load since proxy settings has been changed');
      }

      // Fake portal state for loading timeout.
      if (reason == ERROR_REASONS.LOADING_TIMEOUT) {
        isOnline = false;
        isUnderCaptivePortal = true;
        isTimeout = true;
      }

      // Portal was detected via generate_204 redirect on Chrome side.
      // Subsequent call to show dialog if it's already shown does nothing.
      if (reason == ERROR_REASONS.PORTAL_DETECTED) {
        isOnline = false;
        isUnderCaptivePortal = true;
      }

      if (!isOnline && shouldOverlay) {
        console.log('Show offline message: state=' + state +
                    ', network=' + network + ', reason=' + reason +
                    ', isUnderCaptivePortal=' + isUnderCaptivePortal);

        offlineMessage.onBeforeShow(lastNetworkType);

        if (isUnderCaptivePortal && !isProxyError) {
          // Do not bother a user with obsessive captive portal showing. This
          // check makes captive portal being shown only once: either when error
          // screen is shown for the first time or when switching from another
          // error screen (offline, proxy).
          if (!isShown ||
              !offlineMessage.classList.contains('show-captive-portal')) {
            // In case of timeout we're suspecting that network might be
            // a captive portal but would like to check that first.
            // Otherwise (signal from flimflam / generate_204 got redirected)
            // show dialog right away.
            if (isTimeout)
              chrome.send('fixCaptivePortal');
            else
              chrome.send('showCaptivePortal');
          }
        } else {
          chrome.send('hideCaptivePortal');
        }

        if (isUnderCaptivePortal) {
          if (isProxyError) {
            offlineMessage.classList.remove('show-offline-message');
            offlineMessage.classList.remove('show-captive-portal');
            offlineMessage.classList.add('show-proxy-error');
          } else {
            $(CURRENT_NETWORK_NAME_ID).textContent = network;
            offlineMessage.classList.remove('show-offline-message');
            offlineMessage.classList.remove('show-proxy-error');
            offlineMessage.classList.add('show-captive-portal');
          }
        } else {
          offlineMessage.classList.remove('show-captive-portal');
          offlineMessage.classList.remove('show-proxy-error');
          offlineMessage.classList.add('show-offline-message');
        }

        offlineMessage.classList.remove('hidden');
        offlineMessage.classList.remove('faded');

        if (!currentScreen.classList.contains('faded')) {
          currentScreen.classList.add('faded');
          currentScreen.addEventListener('webkitTransitionEnd',
            function f(e) {
              currentScreen.removeEventListener('webkitTransitionEnd', f);
              if (currentScreen.classList.contains('faded'))
                currentScreen.classList.add('hidden');
            });
        }
        chrome.send('networkErrorShown');
      } else {
        chrome.send('hideCaptivePortal');

        if (!offlineMessage.classList.contains('faded')) {
          console.log('Hide offline message. state=' + state +
                      ', network=' + network + ', reason=' + reason);

          offlineMessage.onBeforeHide();

          offlineMessage.classList.add('faded');
          offlineMessage.addEventListener('webkitTransitionEnd',
            function f(e) {
              offlineMessage.removeEventListener('webkitTransitionEnd', f);
              if (offlineMessage.classList.contains('faded'))
                offlineMessage.classList.add('hidden');
            });

          currentScreen.classList.remove('hidden');
          currentScreen.classList.remove('faded');

          // Forces a reload for Gaia screen on hiding error message.
          if (currentScreen.id == 'gaia-signin')
            currentScreen.doReload();
        }
      }
    },

    // Request network state update with loading timeout as reason.
    showLoadingTimeoutError: function() {
      // Shows error message if it is not shown already.
      if (this.classList.contains('hidden')) {
        chrome.send('loginRequestNetworkState',
                    ['login.ErrorMessageScreen.updateState',
                     ERROR_REASONS.LOADING_TIMEOUT]);
      }
    }
  };

  /**
   * Network state changed callback.
   * @param {Integer} state Current state of the network (see NET_STATE).
   * @param {string} network Name of the current network.
   * @param {string} reason Reason the callback was called.
   * @param {int} lastNetworkType Last active network type.
   */
  ErrorMessageScreen.updateState = function(
      state, network, reason, lastNetworkType) {
    $('error-message').updateState_(state, network, reason, lastNetworkType);
  };

  /**
   * Handler for iframe's error notification coming from the outside.
   * For more info see C++ class 'SnifferObserver' which calls this method.
   * @param {number} error Error code.
   */
  ErrorMessageScreen.onFrameError = function(error) {
    console.log('Gaia frame error = ' + error);
    if (error == NET_ERROR.ABORTED_BY_USER) {
      // Gaia frame was reloaded. Nothing to do here.
      return;
    }
    $('gaia-signin').onFrameError(error);
    // Offline and simple captive portal cases are handled by the
    // NetworkStateInformer, so only the case when browser is online is
    // valuable.
    if (window.navigator.onLine) {
      // Check current network state if currentScreen is a managed one.
      var currentScreen = Oobe.getInstance().currentScreen;
      if (MANAGED_SCREENS.indexOf(currentScreen.id) != -1) {
        chrome.send('loginRequestNetworkState',
                    ['login.ErrorMessageScreen.maybeRetry',
                     'frame error:' + error]);
      }
    }
  };

  /**
   * Network state callback where we decide whether to schdule a retry.
   */
  ErrorMessageScreen.maybeRetry =
      function(state, network, reason, lastNetworkType) {
    console.log('ErrorMessageScreen.maybeRetry, state=' + state +
                ', network=' + network);

    // No retry if we are not online.
    if (state != NET_STATE.ONLINE)
      return;

    var currentScreen = Oobe.getInstance().currentScreen;
    if (MANAGED_SCREENS.indexOf(currentScreen.id) != -1) {
      this.updateState(NET_STATE.PORTAL, network, reason, lastNetworkType);
      // Schedules a retry.
      currentScreen.scheduleRetry();
    }
  };

  /**
   * Updates screen localized content like links since they're not updated
   * via template.
   */
  ErrorMessageScreen.updateLocalizedContent = function() {
    $('error-message').updateLocalizedContent_();
  };

  return {
    ErrorMessageScreen: ErrorMessageScreen
  };
});
<commit_msg>[cros,login] Do not rely on "window.navigator.onLine".<commit_after> // Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Offline message screen implementation.
 */

cr.define('login', function() {
  // Screens that should have offline message overlay.
  /** @const */ var MANAGED_SCREENS = ['gaia-signin'];

  // Network state constants.
  var NET_STATE = {
    OFFLINE: 0,
    ONLINE: 1,
    PORTAL: 2
  };

  // Error reasons which are passed to updateState_() method.
  /** @const */ var ERROR_REASONS = {
    PROXY_AUTH_CANCELLED: 'frame error:111',
    PROXY_CONNECTION_FAILED: 'frame error:130',
    PROXY_CONFIG_CHANGED: 'proxy changed',
    LOADING_TIMEOUT: 'loading timeout',
    PORTAL_DETECTED: 'portal detected'
  };

  // Frame loading errors.
  var NET_ERROR = {
    ABORTED_BY_USER: 3
  };

  // Link which starts guest session for captive portal fixing.
  /** @const */ var FIX_CAPTIVE_PORTAL_ID = 'captive-portal-fix-link';

  /** @const */ var FIX_PROXY_SETTINGS_ID = 'proxy-settings-fix-link';

  // Id of the element which holds current network name.
  /** @const */ var CURRENT_NETWORK_NAME_ID = 'captive-portal-network-name';

  // Link which triggers frame reload.
  /** @const */ var RELOAD_PAGE_ID = 'proxy-error-retry-link';

  /**
   * Creates a new offline message screen div.
   * @constructor
   * @extends {HTMLDivElement}
   */
  var ErrorMessageScreen = cr.ui.define('div');

  /**
   * Registers with Oobe.
   */
  ErrorMessageScreen.register = function() {
    var screen = $('error-message');
    ErrorMessageScreen.decorate(screen);

    // Note that ErrorMessageScreen is not registered with Oobe because
    // it is shown on top of sign-in screen instead of as an independent screen.
  };

  ErrorMessageScreen.prototype = {
    __proto__: HTMLDivElement.prototype,

    /** @inheritDoc */
    decorate: function() {
      chrome.send('loginAddNetworkStateObserver',
                  ['login.ErrorMessageScreen.updateState']);

      cr.ui.DropDown.decorate($('offline-networks-list'));
      this.updateLocalizedContent_();
    },

    /**
     * Updates localized content of the screen that is not updated via template.
     */
    updateLocalizedContent_: function() {
      $('captive-portal-message-text').innerHTML = localStrings.getStringF(
        'captivePortalMessage',
        '',
        '',
        '');
      $(FIX_CAPTIVE_PORTAL_ID).onclick = function() {
        chrome.send('showCaptivePortal');
      };

      $('captive-portal-proxy-message-text').innerHTML =
        localStrings.getStringF(
          'captivePortalProxyMessage',
          '',
          '');
      $(FIX_PROXY_SETTINGS_ID).onclick = function() {
        chrome.send('openProxySettings');
      };

      $('proxy-message-text').innerHTML = localStrings.getStringF(
          'proxyMessageText',
          '',
          '');
      $(RELOAD_PAGE_ID).onclick = function() {
        var currentScreen = Oobe.getInstance().currentScreen;
        // Schedules a immediate retry.
        currentScreen.doReload();
      };

      $('error-guest-signin').innerHTML = localStrings.getStringF(
          'guestSignin',
          '',
          '');
      $('error-guest-signin-link').onclick = function() {
        chrome.send('launchIncognito');
      };

      $('error-offline-login').innerHTML = localStrings.getStringF(
          'offlineLogin',
          '',
          '');
      $('error-offline-login-link').onclick = function() {
        chrome.send('offlineLogin');
      };
    },

    onBeforeShow: function(lastNetworkType) {
      var currentScreen = Oobe.getInstance().currentScreen;

      cr.ui.DropDown.show('offline-networks-list', false, lastNetworkType);

      $('error-guest-signin').hidden = $('guestSignin').hidden ||
          !$('add-user-header-bar-item').hidden;

      $('error-offline-login').hidden = !currentScreen.isOfflineAllowed;
    },

    onBeforeHide: function() {
      cr.ui.DropDown.hide('offline-networks-list');
    },

    update: function() {
      chrome.send('loginRequestNetworkState',
                  ['login.ErrorMessageScreen.updateState',
                   'update']);
    },

    /**
     * Shows or hides offline message based on network on/offline state.
     * @param {Integer} state Current state of the network (see NET_STATE).
     * @param {string} network Name of the current network.
     * @param {string} reason Reason the callback was called.
     * @param {int} lastNetworkType Last active network type.
     */
    updateState_: function(state, network, reason, lastNetworkType) {
      var currentScreen = Oobe.getInstance().currentScreen;
      var offlineMessage = this;
      var isOnline = (state == NET_STATE.ONLINE);
      var isUnderCaptivePortal = (state == NET_STATE.PORTAL);
      var isProxyError = reason == ERROR_REASONS.PROXY_AUTH_CANCELLED ||
          reason == ERROR_REASONS.PROXY_CONNECTION_FAILED;
      var shouldOverlay = MANAGED_SCREENS.indexOf(currentScreen.id) != -1 &&
          !currentScreen.isLocal;
      var isTimeout = false;
      var isShown = !offlineMessage.classList.contains('hidden') &&
          !offlineMessage.classList.contains('faded');

      if (reason == ERROR_REASONS.PROXY_CONFIG_CHANGED && shouldOverlay &&
          isShown) {
        // Schedules a immediate retry.
        currentScreen.doReload();
        console.log('Retry page load since proxy settings has been changed');
      }

      // Fake portal state for loading timeout.
      if (reason == ERROR_REASONS.LOADING_TIMEOUT) {
        isOnline = false;
        isUnderCaptivePortal = true;
        isTimeout = true;
      }

      // Portal was detected via generate_204 redirect on Chrome side.
      // Subsequent call to show dialog if it's already shown does nothing.
      if (reason == ERROR_REASONS.PORTAL_DETECTED) {
        isOnline = false;
        isUnderCaptivePortal = true;
      }

      if (!isOnline && shouldOverlay) {
        console.log('Show offline message: state=' + state +
                    ', network=' + network + ', reason=' + reason +
                    ', isUnderCaptivePortal=' + isUnderCaptivePortal);

        offlineMessage.onBeforeShow(lastNetworkType);

        if (isUnderCaptivePortal && !isProxyError) {
          // Do not bother a user with obsessive captive portal showing. This
          // check makes captive portal being shown only once: either when error
          // screen is shown for the first time or when switching from another
          // error screen (offline, proxy).
          if (!isShown ||
              !offlineMessage.classList.contains('show-captive-portal')) {
            // In case of timeout we're suspecting that network might be
            // a captive portal but would like to check that first.
            // Otherwise (signal from flimflam / generate_204 got redirected)
            // show dialog right away.
            if (isTimeout)
              chrome.send('fixCaptivePortal');
            else
              chrome.send('showCaptivePortal');
          }
        } else {
          chrome.send('hideCaptivePortal');
        }

        if (isUnderCaptivePortal) {
          if (isProxyError) {
            offlineMessage.classList.remove('show-offline-message');
            offlineMessage.classList.remove('show-captive-portal');
            offlineMessage.classList.add('show-proxy-error');
          } else {
            $(CURRENT_NETWORK_NAME_ID).textContent = network;
            offlineMessage.classList.remove('show-offline-message');
            offlineMessage.classList.remove('show-proxy-error');
            offlineMessage.classList.add('show-captive-portal');
          }
        } else {
          offlineMessage.classList.remove('show-captive-portal');
          offlineMessage.classList.remove('show-proxy-error');
          offlineMessage.classList.add('show-offline-message');
        }

        offlineMessage.classList.remove('hidden');
        offlineMessage.classList.remove('faded');

        if (!currentScreen.classList.contains('faded')) {
          currentScreen.classList.add('faded');
          currentScreen.addEventListener('webkitTransitionEnd',
            function f(e) {
              currentScreen.removeEventListener('webkitTransitionEnd', f);
              if (currentScreen.classList.contains('faded'))
                currentScreen.classList.add('hidden');
            });
        }
        chrome.send('networkErrorShown');
      } else {
        chrome.send('hideCaptivePortal');

        if (!offlineMessage.classList.contains('faded')) {
          console.log('Hide offline message. state=' + state +
                      ', network=' + network + ', reason=' + reason);

          offlineMessage.onBeforeHide();

          offlineMessage.classList.add('faded');
          offlineMessage.addEventListener('webkitTransitionEnd',
            function f(e) {
              offlineMessage.removeEventListener('webkitTransitionEnd', f);
              if (offlineMessage.classList.contains('faded'))
                offlineMessage.classList.add('hidden');
            });

          currentScreen.classList.remove('hidden');
          currentScreen.classList.remove('faded');

          // Forces a reload for Gaia screen on hiding error message.
          if (currentScreen.id == 'gaia-signin')
            currentScreen.doReload();
        }
      }
    },

    // Request network state update with loading timeout as reason.
    showLoadingTimeoutError: function() {
      // Shows error message if it is not shown already.
      if (this.classList.contains('hidden')) {
        chrome.send('loginRequestNetworkState',
                    ['login.ErrorMessageScreen.updateState',
                     ERROR_REASONS.LOADING_TIMEOUT]);
      }
    }
  };

  /**
   * Network state changed callback.
   * @param {Integer} state Current state of the network (see NET_STATE).
   * @param {string} network Name of the current network.
   * @param {string} reason Reason the callback was called.
   * @param {int} lastNetworkType Last active network type.
   */
  ErrorMessageScreen.updateState = function(
      state, network, reason, lastNetworkType) {
    $('error-message').updateState_(state, network, reason, lastNetworkType);
  };

  /**
   * Handler for iframe's error notification coming from the outside.
   * For more info see C++ class 'SnifferObserver' which calls this method.
   * @param {number} error Error code.
   */
  ErrorMessageScreen.onFrameError = function(error) {
    console.log('Gaia frame error = ' + error);
    if (error == NET_ERROR.ABORTED_BY_USER) {
      // Gaia frame was reloaded. Nothing to do here.
      return;
    }
    $('gaia-signin').onFrameError(error);
    // Check current network state if currentScreen is a managed one.
    var currentScreen = Oobe.getInstance().currentScreen;
    if (MANAGED_SCREENS.indexOf(currentScreen.id) != -1) {
      chrome.send('loginRequestNetworkState',
                  ['login.ErrorMessageScreen.maybeRetry',
                   'frame error:' + error]);
    }
  };

  /**
   * Network state callback where we decide whether to schdule a retry.
   */
  ErrorMessageScreen.maybeRetry =
      function(state, network, reason, lastNetworkType) {
    console.log('ErrorMessageScreen.maybeRetry, state=' + state +
                ', network=' + network);

    // No retry if we are not online.
    if (state != NET_STATE.ONLINE)
      return;

    var currentScreen = Oobe.getInstance().currentScreen;
    if (MANAGED_SCREENS.indexOf(currentScreen.id) != -1) {
      this.updateState(NET_STATE.PORTAL, network, reason, lastNetworkType);
      // Schedules a retry.
      currentScreen.scheduleRetry();
    }
  };

  /**
   * Updates screen localized content like links since they're not updated
   * via template.
   */
  ErrorMessageScreen.updateLocalizedContent = function() {
    $('error-message').updateLocalizedContent_();
  };

  return {
    ErrorMessageScreen: ErrorMessageScreen
  };
});
<|endoftext|>


<commit_before>var wideScreen = 641;
 'use strict';
  var _ = require('lodash');
  moj.Modules.FindLegalAdviser = {
    el: '#resultsMap',
    markers: [],
    searchLocationMarker: null,
    openInfoWindow: null,
    eventsBound: false,

    init: function() {
      this.cacheEls();

      this._handleMQTest();

      if(!this.$resultsMap.length) {
        return;
      }

      this.renderMap(this.$resultsMap.data('lat'), this.$resultsMap.data('lon'));
      this._prepareMarkers();

      $(window).resize(_.debounce($.proxy(this._handleMQTest, this), 500));
    },

    // Handle events which rely on media queries
    _handleMQTest: function() {
      if(window.Modernizr.mq('(min-width: ' + wideScreen + 'px)')) {
        if(!this.eventsBound) {
          this.bindEvents();
        }
      } else if(this.eventsBound) {
        this._unbindEvents();
      }
    },

    bindEvents: function() {
      var self = this;
      this.$organisationListItems.find('.org-summary').each(function() {
        $(this).replaceWith('' + $(this).html() + '');
      });

      this.$organisationListItems.on('click', '.org-summary', function(evt) {
        evt.preventDefault();
        self.$organisationListItems.find('.org-summary').attr('aria-expanded', false);
        self._handleItemHighlight(evt, $(this).closest('li'));
      });

      this.$resultsPagination.on('click', 'a', function(evt) {
        evt.preventDefault();

        if(window.LABELS && window.LABELS.loading) {
          $(evt.target).replaceWith('' + window.LABELS.loading + '');
        }

        self._fetchPage(evt.target.href);

        if(window.history && history.pushState) {
          history.pushState(null, null, evt.target.href);
        }
      });

      this.$findLegalAdviserForm.submit(function(evt) {
        evt.preventDefault();

        var url = document.location.pathname + '?' + $(this).serialize();
        self._fetchPage(url, true);

        if(window.history && history.pushState) {
          history.pushState(null, null, url);
        }

        if(!self.$resultsMap.length) {
          $('
' + window.LABELS.loading + '
').insertAfter($(this));
        }
      });

      window.onpopstate = function() {
        self._fetchPage(document.location.href);
      };

      this.eventsBound = true;
    },

    _unbindEvents: function() {
      this.$organisationListItems
        .unbind('click')
        .find('.org-summary')
        .each(function() {
          $(this).replaceWith('' + $(this).html() + '');
        });

      this.$resultsPagination.unbind('click');
      this.$findLegalAdviserForm.unbind('submit');
      window.onpopstate = null;

      this.eventsBound = false;
    },

    _fetchPage: function(url, scrollToResults) {
      var self = this;

      $.get(url)
        .success(function(data) {
          self.$findLegalAdviserContainer.replaceWith(data);
          self.markers = [];
          self.eventsBound = false;
          self.init();

          if(scrollToResults) {
            $('html, body').delay(300).animate({
              'scrollTop': self.$findLegalAdviserContainer.offset().top - 10
            }, 160);
          }

          $('.search-results-list').attr('tabindex', -1).focus();

          window.ga('send', 'pageview', stripPII(url));
        })
        .error();
    },

    _closeOpenInfoWindow: function() {
      if(this.openInfoWindow) {
        this.openInfoWindow.close();
      }
    },

    _prepareMarkers: function() {
      var organisations = $.map(this.$organisationListItems, function(item) {
        var $item = $(item);
        return {
          id: $item.data('id'),
          position: {
            lat: parseFloat($item.data('lat')),
            lng: parseFloat($item.data('lon'))
          },
          title: $item.find('.fn').text(),
          content: $item.html()
        };
      });

      this.addMarkers(organisations);
    },

    _fitAllMarkers: function() {
      var self = this;

      this.map.fitBounds(this.markers.reduce(function(bounds, marker) {
        return bounds.extend(marker.getPosition());
      }, new google.maps.LatLngBounds()));

      $.each(this.markers, function() {
        this.setMap(self.map);
      });
    },

    _handleHighlightedItemScroll: function($item, $container) {
      var itemHeight = $item.outerHeight();
      var containerHeight = $container.height();

      if(itemHeight + $item.position().top > containerHeight) {
        $container.scrollTop(containerHeight - itemHeight);
      }
    },

    _handleMarkersZooming: function(selectedMarkerId) {
      var markerOnMap = _.find(this.markers, { id: selectedMarkerId });

      $.each(this.markers, function() {
        this.setMap(null);
      });

      markerOnMap.setMap(this.map);

      var pairBounds = new google.maps.LatLngBounds();
      pairBounds.extend(markerOnMap.position);
      pairBounds.extend(this.searchLocationMarker.position);

      this.map.fitBounds(pairBounds);
    },

    _handleItemHighlight: function(evt, $item) {
      var $container = $item.closest('.search-results-list');

      if($item.hasClass('s-highlighted')) {
        this.$organisationListItems.removeClass('s-highlighted');
        this._fitAllMarkers();
        return;
      }

      this.$organisationListItems.removeClass('s-highlighted');
      $item.addClass('s-highlighted');
      $item.find('.org-summary').attr('aria-expanded', true);

      $item.find('.org-details').attr('tabindex', -1).focus();

      this._handleMarkersZooming($item.data('id'));
      this._handleHighlightedItemScroll($item, $container);

      var markerCount = parseInt($item.find('.marker').text(), 10);
      var currentPage = parseInt($container.data('current-page'), 10);
      var name = $item.find('.fn').text();
      var count;

      if(markerCount && currentPage) {
        count = markerCount + ((currentPage - 1) * 10);
      }

      name = (count ? count + ':' : '') + name;

      window.ga('send', 'event', 'find-legal-adviser', 'selected', name);
    },

    renderMap: function(lat, lon) {
      var self = this;

      var searchLocation = {
        lat: lat,
        lng: lon
      };

      var mapOptions = {
        center: searchLocation,
        zoom: 15,
        scrollwheel: false,
        panControl: false,
        streetViewControl: false
      };

      this.map = new google.maps.Map(this.$resultsMap[0], mapOptions);
      this.searchLocationMarker = this.addMarker(searchLocation, {
        title: 'Search location',
        icon: 'icon-location-2x'
      });

      google.maps.event.addListener(self.map, 'click', function() {
        self._closeOpenInfoWindow();
      });
    },

    addMarker: function(position, options) {
      var self = this;
      var image;
      options = options || {};

      if(options.icon) {
        image = {
          url: '/static/images/icons/' + options.icon + '.png',
          scaledSize: new google.maps.Size(16, 16),
          anchor: new google.maps.Point(8, 8)
        };
      } else if(options.id) {
        image = {
          url: '/static/images/icons/icon-numbered-markers-2x.png',
          size: new google.maps.Size(22, 40),
          scaledSize: new google.maps.Size(220, 40),
          origin: new google.maps.Point(22 * (options.id - 1), 0)
        };
      }

      var marker = new google.maps.Marker({
        position: position,
        id: options.id,
        title: options.title,
        map: this.map,
        icon: image
      });

      if(options.content) {
        google.maps.event.addListener(marker, 'click', function() {
          self._closeOpenInfoWindow();
          self.openInfoWindow = new google.maps.InfoWindow({
            content: options.content
          });
          self.openInfoWindow.open(self.map, marker);
        });
      }

      return marker;
    },

    addMarkers: function(points) {
      var self = this;

      $.each(points, function() {
        if(!(this.position)) {
          return;
        }
        self.markers.push(
          self.addMarker(this.position, {
            id: this.id,
            title: this.title,
            content: this.content
          })
        );
      });

      this._fitAllMarkers();
    },

    cacheEls: function() {
      this.$resultsMap = $(this.el);
      this.$findLegalAdviserContainer = $('.find-legal-adviser');
      this.$findLegalAdviserForm = $('.legal-adviser-search');
      this.$organisationListItems = $('.search-results-list .vcard');
      this.$resultsPagination = $('.search-results-pagination');
    }
  };

  function setMapHeight(setHeight) {
    if ($(window).width() >= wideScreen) {
      var listHeight = $("ul.org-list").height();
      if (listHeight > setHeight) setHeight = listHeight;
      $(".search-results-container, .search-results-list").height(setHeight);
    }
  }

  $("document").ready(function(){
    var originalHeight = $("#resultsMap").height();
    setMapHeight(originalHeight);
    $(".search-results-container").click(function(){
      setMapHeight(originalHeight);
    });
  });

<commit_msg>JS dataset retention<commit_after>var wideScreen = 641;
 'use strict';
  var _ = require('lodash');
  moj.Modules.FindLegalAdviser = {
    el: '#resultsMap',
    markers: [],
    searchLocationMarker: null,
    openInfoWindow: null,
    eventsBound: false,

    init: function() {
      this.cacheEls();

      this._handleMQTest();

      if(!this.$resultsMap.length) {
        return;
      }

      this.renderMap(this.$resultsMap.data('lat'), this.$resultsMap.data('lon'));
      this._prepareMarkers();

      $(window).resize(_.debounce($.proxy(this._handleMQTest, this), 500));
    },

    // Handle events which rely on media queries
    _handleMQTest: function() {
      if(window.Modernizr.mq('(min-width: ' + wideScreen + 'px)')) {
        if(!this.eventsBound) {
          this.bindEvents();
        }
      } else if(this.eventsBound) {
        this._unbindEvents();
      }
    },

    bindEvents: function() {
      var self = this;
      this.$organisationListItems.find('.org-summary').each(function() {
        $(this).replaceWith('' + $(this).html() + '');
      });

      this.$organisationListItems.on('click', '.org-summary', function(evt) {
        evt.preventDefault();
        self.$organisationListItems.find('.org-summary').attr('aria-expanded', false);
        self._handleItemHighlight(evt, $(this).closest('li'));
      });

      this.$resultsPagination.on('click', 'a', function(evt) {
        evt.preventDefault();

        if(window.LABELS && window.LABELS.loading) {
          $(evt.target).replaceWith('' + window.LABELS.loading + '');
        }

        self._fetchPage(evt.target.href);

        if(window.history && history.pushState) {
          history.pushState(null, null, evt.target.href);
        }
      });

      this.$findLegalAdviserForm.submit(function(evt) {
        evt.preventDefault();

        var url = document.location.pathname + '?' + $(this).serialize();
        self._fetchPage(url, true);

        if(window.history && history.pushState) {
          history.pushState(null, null, url);
        }

        if(!self.$resultsMap.length) {
          $('
' + window.LABELS.loading + '
').insertAfter($(this));
        }
      });

      window.onpopstate = function() {
        self._fetchPage(document.location.href);
      };

      this.eventsBound = true;
    },

    _unbindEvents: function() {
      this.$organisationListItems
        .unbind('click')
        .find('.org-summary')
        .each(function() {
          $(this).replaceWith('' + $(this).html() + '');
        });

      this.$resultsPagination.unbind('click');
      this.$findLegalAdviserForm.unbind('submit');
      window.onpopstate = null;

      this.eventsBound = false;
    },

    _fetchPage: function(url, scrollToResults) {
      var self = this;

      $.get(url)
        .success(function(data) {
          self.$findLegalAdviserContainer.replaceWith(data);
          self.markers = [];
          self.eventsBound = false;
          self.init();

          if(scrollToResults) {
            $('html, body').delay(300).animate({
              'scrollTop': self.$findLegalAdviserContainer.offset().top - 10
            }, 160);
          }

          $('.search-results-list').attr('tabindex', -1).focus();

          window.ga('send', 'pageview', stripPII(url));
        })
        .error();
    },

    _closeOpenInfoWindow: function() {
      if(this.openInfoWindow) {
        this.openInfoWindow.close();
      }
    },

    _prepareMarkers: function() {
      var organisations = $.map(this.$organisationListItems, function(item) {
        var $item = $(item);
        return {
          id: $item.data('id'),
          position: {
            lat: parseFloat($item.data('lat')),
            lng: parseFloat($item.data('lon'))
          },
          title: $item.find('.fn').text(),
          content: $item.html()
        };
      });

      this.addMarkers(organisations);
    },

    _fitAllMarkers: function() {
      var self = this;

      this.map.fitBounds(this.markers.reduce(function(bounds, marker) {
        return bounds.extend(marker.getPosition());
      }, new google.maps.LatLngBounds()));

      $.each(this.markers, function() {
        this.setMap(self.map);
      });
    },

    _handleHighlightedItemScroll: function($item, $container) {
      var itemHeight = $item.outerHeight();
      var containerHeight = $container.height();

      if(itemHeight + $item.position().top > containerHeight) {
        $container.scrollTop(containerHeight - itemHeight);
      }
    },

    _handleMarkersZooming: function(selectedMarkerId) {
      var markerOnMap = _.find(this.markers, { id: selectedMarkerId });

      $.each(this.markers, function() {
        this.setMap(null);
      });

      markerOnMap.setMap(this.map);

      var pairBounds = new google.maps.LatLngBounds();
      pairBounds.extend(markerOnMap.position);
      pairBounds.extend(this.searchLocationMarker.position);

      this.map.fitBounds(pairBounds);
    },

    _handleItemHighlight: function(evt, $item) {
      var $container = $item.closest('.search-results-list');

      if($item.hasClass('s-highlighted')) {
        this.$organisationListItems.removeClass('s-highlighted');
        this._fitAllMarkers();
        return;
      }

      this.$organisationListItems.removeClass('s-highlighted');
      $item.addClass('s-highlighted');
      $item.find('.org-summary').attr('aria-expanded', true);

      $item.find('.org-details').attr('tabindex', -1).focus();

      this._handleMarkersZooming($item.data('id'));
      this._handleHighlightedItemScroll($item, $container);

      var markerCount = parseInt($item.find('.marker').text(), 10);
      var currentPage = parseInt($container.data('current-page'), 10);
      var name = $item.find('.fn').text();
      var count;

      if(markerCount && currentPage) {
        count = markerCount + ((currentPage - 1) * 10);
      }

      name = (count ? count + ':' : '') + name;

      window.ga('send', 'event', 'find-legal-adviser', 'selected', name);
    },

    renderMap: function(lat, lon) {
      var self = this;

      var searchLocation = {
        lat: lat,
        lng: lon
      };

      var mapOptions = {
        center: searchLocation,
        zoom: 15,
        scrollwheel: false,
        panControl: false,
        streetViewControl: false
      };

      this.map = new google.maps.Map(this.$resultsMap[0], mapOptions);
      this.searchLocationMarker = this.addMarker(searchLocation, {
        title: 'Search location',
        icon: 'icon-location-2x'
      });

      google.maps.event.addListener(self.map, 'click', function() {
        self._closeOpenInfoWindow();
      });
    },

    addMarker: function(position, options) {
      var self = this;
      var image;
      options = options || {};

      if(options.icon) {
        image = {
          url: '/static/images/icons/' + options.icon + '.png',
          scaledSize: new google.maps.Size(16, 16),
          anchor: new google.maps.Point(8, 8)
        };
      } else if(options.id) {
        image = {
          url: '/static/images/icons/icon-numbered-markers-2x.png',
          size: new google.maps.Size(22, 40),
          scaledSize: new google.maps.Size(220, 40),
          origin: new google.maps.Point(22 * (options.id - 1), 0)
        };
      }

      var marker = new google.maps.Marker({
        position: position,
        id: options.id,
        title: options.title,
        map: this.map,
        icon: image
      });

      if(options.content) {
        google.maps.event.addListener(marker, 'click', function() {
          self._closeOpenInfoWindow();
          self.openInfoWindow = new google.maps.InfoWindow({
            content: options.content
          });
          self.openInfoWindow.open(self.map, marker);
        });
      }

      return marker;
    },

    addMarkers: function(points) {
      var self = this;

      $.each(points, function() {
        if(!(this.position)) {
          return;
        }
        self.markers.push(
          self.addMarker(this.position, {
            id: this.id,
            title: this.title,
            content: this.content
          })
        );
      });

      this._fitAllMarkers();
    },

    cacheEls: function() {
      this.$resultsMap = $(this.el);
      this.$findLegalAdviserContainer = $('.find-legal-adviser');
      this.$findLegalAdviserForm = $('.legal-adviser-search');
      this.$organisationListItems = $('.search-results-list .vcard');
      this.$resultsPagination = $('.search-results-pagination');
    }
  };

  function setMapHeight(setHeight) {
    if ($(window).width() >= wideScreen) {
      var listHeight = $("ul.org-list").height();
      if (listHeight > setHeight) setHeight = listHeight;
      $(".search-results-container, .search-results-list").height(setHeight);
    }
  }

  $("document").ready(function(){
    var originalHeight = $("#resultsMap").height();
    setMapHeight(originalHeight);
    $(".search-results-container").click(function(){
      setMapHeight(originalHeight);
    });
  });

<|endoftext|>