<commit_before>/* global Marionette, Handlebars */

/**
 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

(function(OC, OCA, Marionette, Handlebars, _, $) {
	'use strict';

	OCA.SpreedMe = OCA.SpreedMe || {};
	OCA.SpreedMe.Views = OCA.SpreedMe.Views || {};

	var uiChannel = Backbone.Radio.channel('ui');

	// These constants must match the values in "lib/Room.php".
	var ROOM_TYPE_ONE_TO_ONE = 1;
	var ROOM_TYPE_GROUP_CALL = 2;
	var ROOM_TYPE_PUBLIC_CALL = 3;

	var ITEM_TEMPLATE = '

 {{displayName}}'+
						'
'+
							'
'+
								'
<button></button>
'+
							'
'+
						'
'+
						'
'+
							'
'+
								'
'+
									'<button class="leave-room-button">'+
										''+
										''+t('spreed', 'Leave room')+''+
									'</button>'+
								'
'+
								'{{#if isDeletable}}'+
								'
'+
									'<button class="delete-room-button">'+
										''+
										''+t('spreed', 'Delete room')+''+
									'</button>'+
								'
'+
								'{{/if}}'+
							'
'+
						'
';

	var RoomItemView = Marionette.View.extend({
		tagName: 'li',
		modelEvents: {
			'change:active': function() {
				this.render();
			},
			'change:displayName': function() {
				this.render();
			},
			'change:participants': function() {
				this.render();
			},
			'change:hasCall': function() {
				this.render();
			},
			'change:participantInCall': function() {
				this.render();
			},
			'change:participantType': function() {
				this.render();
			},
			'change:type': function() {
				this.render();
			}
		},
		initialize: function() {
			// Add class to every room list item to detect it on click.
			this.$el.addClass('room-list-item');
			this.listenTo(uiChannel, 'document:click', function(event) {
				var target = $(event.target);
				if (!this.$el.is(target.closest('.room-list-item'))) {
					// Click was not triggered by this element -> close menu
					this.menuShown = false;
					this.toggleMenuClass();
				}
			});
		},
		templateContext: function() {
			return {
				isDeletable: (this.model.get('participantType') === 1 || this.model.get('participantType') === 2) &&
					(Object.keys(this.model.get('participants')).length > 2 || this.model.get('numGuests') > 0)
			};
		},
		onRender: function() {
			var roomURL;

			this.checkSharingStatus();

			roomURL = OC.generateUrl('/call/' + this.model.get('token'));
			this.$el.find('.app-navigation-entry-link').attr('href', roomURL);

			if (this.model.get('active')) {
				if (!this.$el.hasClass('active')) {
					this.addRoomMessage();
				}
				this.$el.addClass('active');
			} else {
				this.$el.removeClass('active');
			}

			//If the room is not a one2one room, we show tooltip.
			if (this.model.get('type') !== ROOM_TYPE_ONE_TO_ONE) {
				this.addTooltip();
			}

			this.toggleMenuClass();
		},
		events: {
			'click .app-navigation-entry-utils-menu-button button': 'toggleMenu',
			'click @ui.menu .leave-room-button': 'leaveRoom',
			'click @ui.menu .delete-room-button': 'deleteRoom',
			'click @ui.room': 'joinRoom'
		},
		ui: {
			'room': '.app-navigation-entry-link',
			'menu': '.app-navigation-entry-menu',
			'menuList': '.app-navigation-entry-menu-list'
		},
		template: Handlebars.compile(ITEM_TEMPLATE),
		menuShown: false,
		toggleMenu: function(e) {
			e.preventDefault();
			this.menuShown = !this.menuShown;
			this.toggleMenuClass();
		},
		toggleMenuClass: function() {
			this.ui.menu.toggleClass('open', this.menuShown);
		},
		checkSharingStatus: function() {
			if (this.model.get('type') === ROOM_TYPE_ONE_TO_ONE) { // 1on1
				this.$el.find('.public-room').removeClass('public-room').addClass('private-room');

				_.each(this.$el.find('.avatar'), function(a) {
					if ($(a).data('user-display-name')) {
						$(a).avatar($(a).data('user'), 32, undefined, false, undefined, $(a).data('user-display-name'));
					} else {
						$(a).avatar($(a).data('user'), 32);
					}
				});
			} else if (this.model.get('type') === ROOM_TYPE_GROUP_CALL) { // Group
				this.$el.find('.public-room').removeClass('public-room').addClass('private-room');

				_.each(this.$el.find('.avatar'), function(a) {
					$(a).removeClass('icon-public').addClass('icon-contacts-dark');
				});
			} else if (this.model.get('type') === ROOM_TYPE_PUBLIC_CALL) { // Public room
				this.$el.find('.private-room').removeClass('private-room').addClass('public-room');

				_.each(this.$el.find('.avatar'), function(a) {
					$(a).removeClass('icon-contacts-dark').addClass('icon-public');
				});
			}
		},
		leaveRoom: function() {
			this.exitingActiveRoom();
			this.$el.slideUp();

			$.ajax({
				url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token') + '/participants/self',
				type: 'DELETE'
			});
		},
		deleteRoom: function() {
			if (this.model.get('participantType') !== 1 &&
				this.model.get('participantType') !== 2) {
				return;
			}

			this.exitingActiveRoom();
			this.$el.slideUp();

			$.ajax({
				url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token'),
				type: 'DELETE'
			});
		},
		exitingActiveRoom: function() {
			if (!this.model.get('active')) {
				return;
			}

			OCA.SpreedMe.app._chatView.$el.detach();
			OCA.SpreedMe.app.connection.leaveCurrentCall(true);
			OC.Util.History.pushState({}, OC.generateUrl('/apps/spreed'));
		},
		joinRoom: function(e) {
			e.preventDefault();
			var token = this.ui.room.attr('data-token');
			OCA.SpreedMe.app.connection.joinRoom(token);

			OC.Util.History.pushState({
				token: token
			}, OC.generateUrl('/call/' + token));
		},
		addRoomMessage: function() {
			console.log('addRoomMessage');
			var participants = this.model.get('participants');

			switch(this.model.get('type')) {
				case ROOM_TYPE_ONE_TO_ONE:
					var participantId = '',
						participantName = '';

					_.each(participants, function(data, userId) {
						if (OC.getCurrentUser().uid !== userId) {
							participantId = userId;
							participantName = data.name;
						}
					});

					OCA.SpreedMe.app.setEmptyContentMessage(
						{ userId: participantId, displayName: participantName},
						t('spreed', 'Waiting for {participantName} to join the call …', {participantName: participantName})
					);
					break;
				case ROOM_TYPE_PUBLIC_CALL:
				case ROOM_TYPE_GROUP_CALL:
					var icon = '',
						message = '',
						messageAdditional = '',
						url = '';

					if (this.model.get('type') === ROOM_TYPE_PUBLIC_CALL) {
						icon = 'icon-public';
					} else {
						icon = 'icon-contacts-dark';
					}

					message = t('spreed', 'Waiting for others to join the call …');

					if (OC.getCurrentUser().uid !== null && Object.keys(participants).length === 1) {
						message = t('spreed', 'No other people in this call');
						if (this.model.get('participantType') === 0 || this.model.get('participantType') === 1) {
							messageAdditional = t('spreed', 'You can invite others in the participant tab of the sidebar');
						}
					}

					if (this.model.get('type') === ROOM_TYPE_PUBLIC_CALL) {
						messageAdditional = t('spreed', 'Share this link to invite others!');
						if (this.model.get('participantType') === 1 || this.model.get('participantType') === 2) {
							messageAdditional = t('spreed', 'You can invite others in the participant tab of the sidebar or share this link to invite others!');
						}
						url = window.location.protocol + '//' + window.location.host + OC.generateUrl('/call/' + this.model.get('token'));
					}

					OCA.SpreedMe.app.setEmptyContentMessage(icon, message, messageAdditional, url);
					break;
				default:
					console.log("Unknown room type", this.model.get('type'));
					return;
			}
		},
		addTooltip: function () {
			var participants = [];
			$.each(this.model.get('participants'), function(participantId, data) {
				if (participantId !== OC.getCurrentUser().uid) {
					participants.push(escapeHTML(data.name));
				}
			});

			if (this.model.get('guestList') !== '') {
				participants.push(this.model.get('guestList'));
			}

			if (participants.length === 0) {
				participants.push(t('spreed', 'You'));
			} else {
				participants.push(t('spreed', 'and you'));
			}

			var htmlstring = participants.join('
');

			this.ui.room.tooltip({
				placement: 'bottom',
				trigger: 'hover',
				html: 'true',
				title: htmlstring
			});
		}
	});

	var RoomListView = Marionette.CollectionView.extend({
		tagName: 'ul',
		childView: RoomItemView
	});

	OCA.SpreedMe.Views.RoomListView = RoomListView;

})(OC, OCA, Marionette, Handlebars, _, $);
<commit_msg>Rename the method<commit_after>/* global Marionette, Handlebars */

/**
 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

(function(OC, OCA, Marionette, Handlebars, _, $) {
	'use strict';

	OCA.SpreedMe = OCA.SpreedMe || {};
	OCA.SpreedMe.Views = OCA.SpreedMe.Views || {};

	var uiChannel = Backbone.Radio.channel('ui');

	// These constants must match the values in "lib/Room.php".
	var ROOM_TYPE_ONE_TO_ONE = 1;
	var ROOM_TYPE_GROUP_CALL = 2;
	var ROOM_TYPE_PUBLIC_CALL = 3;

	var ITEM_TEMPLATE = '

 {{displayName}}'+
						'
'+
							'
'+
								'
<button></button>
'+
							'
'+
						'
'+
						'
'+
							'
'+
								'
'+
									'<button class="leave-room-button">'+
										''+
										''+t('spreed', 'Leave room')+''+
									'</button>'+
								'
'+
								'{{#if isDeletable}}'+
								'
'+
									'<button class="delete-room-button">'+
										''+
										''+t('spreed', 'Delete room')+''+
									'</button>'+
								'
'+
								'{{/if}}'+
							'
'+
						'
';

	var RoomItemView = Marionette.View.extend({
		tagName: 'li',
		modelEvents: {
			'change:active': function() {
				this.render();
			},
			'change:displayName': function() {
				this.render();
			},
			'change:participants': function() {
				this.render();
			},
			'change:hasCall': function() {
				this.render();
			},
			'change:participantInCall': function() {
				this.render();
			},
			'change:participantType': function() {
				this.render();
			},
			'change:type': function() {
				this.render();
			}
		},
		initialize: function() {
			// Add class to every room list item to detect it on click.
			this.$el.addClass('room-list-item');
			this.listenTo(uiChannel, 'document:click', function(event) {
				var target = $(event.target);
				if (!this.$el.is(target.closest('.room-list-item'))) {
					// Click was not triggered by this element -> close menu
					this.menuShown = false;
					this.toggleMenuClass();
				}
			});
		},
		templateContext: function() {
			return {
				isDeletable: (this.model.get('participantType') === 1 || this.model.get('participantType') === 2) &&
					(Object.keys(this.model.get('participants')).length > 2 || this.model.get('numGuests') > 0)
			};
		},
		onRender: function() {
			var roomURL;

			this.checkSharingStatus();

			roomURL = OC.generateUrl('/call/' + this.model.get('token'));
			this.$el.find('.app-navigation-entry-link').attr('href', roomURL);

			if (this.model.get('active')) {
				if (!this.$el.hasClass('active')) {
					this.addRoomMessage();
				}
				this.$el.addClass('active');
			} else {
				this.$el.removeClass('active');
			}

			//If the room is not a one2one room, we show tooltip.
			if (this.model.get('type') !== ROOM_TYPE_ONE_TO_ONE) {
				this.addTooltip();
			}

			this.toggleMenuClass();
		},
		events: {
			'click .app-navigation-entry-utils-menu-button button': 'toggleMenu',
			'click @ui.menu .leave-room-button': 'leaveRoom',
			'click @ui.menu .delete-room-button': 'deleteRoom',
			'click @ui.room': 'joinRoom'
		},
		ui: {
			'room': '.app-navigation-entry-link',
			'menu': '.app-navigation-entry-menu',
			'menuList': '.app-navigation-entry-menu-list'
		},
		template: Handlebars.compile(ITEM_TEMPLATE),
		menuShown: false,
		toggleMenu: function(e) {
			e.preventDefault();
			this.menuShown = !this.menuShown;
			this.toggleMenuClass();
		},
		toggleMenuClass: function() {
			this.ui.menu.toggleClass('open', this.menuShown);
		},
		checkSharingStatus: function() {
			if (this.model.get('type') === ROOM_TYPE_ONE_TO_ONE) { // 1on1
				this.$el.find('.public-room').removeClass('public-room').addClass('private-room');

				_.each(this.$el.find('.avatar'), function(a) {
					if ($(a).data('user-display-name')) {
						$(a).avatar($(a).data('user'), 32, undefined, false, undefined, $(a).data('user-display-name'));
					} else {
						$(a).avatar($(a).data('user'), 32);
					}
				});
			} else if (this.model.get('type') === ROOM_TYPE_GROUP_CALL) { // Group
				this.$el.find('.public-room').removeClass('public-room').addClass('private-room');

				_.each(this.$el.find('.avatar'), function(a) {
					$(a).removeClass('icon-public').addClass('icon-contacts-dark');
				});
			} else if (this.model.get('type') === ROOM_TYPE_PUBLIC_CALL) { // Public room
				this.$el.find('.private-room').removeClass('private-room').addClass('public-room');

				_.each(this.$el.find('.avatar'), function(a) {
					$(a).removeClass('icon-contacts-dark').addClass('icon-public');
				});
			}
		},
		leaveRoom: function() {
			this.cleanupIfActiveRoom();
			this.$el.slideUp();

			$.ajax({
				url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token') + '/participants/self',
				type: 'DELETE'
			});
		},
		deleteRoom: function() {
			if (this.model.get('participantType') !== 1 &&
				this.model.get('participantType') !== 2) {
				return;
			}

			this.cleanupIfActiveRoom();
			this.$el.slideUp();

			$.ajax({
				url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token'),
				type: 'DELETE'
			});
		},
		cleanupIfActiveRoom: function() {
			if (!this.model.get('active')) {
				return;
			}

			OCA.SpreedMe.app._chatView.$el.detach();
			OCA.SpreedMe.app.connection.leaveCurrentCall(true);
			OC.Util.History.pushState({}, OC.generateUrl('/apps/spreed'));
		},
		joinRoom: function(e) {
			e.preventDefault();
			var token = this.ui.room.attr('data-token');
			OCA.SpreedMe.app.connection.joinRoom(token);

			OC.Util.History.pushState({
				token: token
			}, OC.generateUrl('/call/' + token));
		},
		addRoomMessage: function() {
			console.log('addRoomMessage');
			var participants = this.model.get('participants');

			switch(this.model.get('type')) {
				case ROOM_TYPE_ONE_TO_ONE:
					var participantId = '',
						participantName = '';

					_.each(participants, function(data, userId) {
						if (OC.getCurrentUser().uid !== userId) {
							participantId = userId;
							participantName = data.name;
						}
					});

					OCA.SpreedMe.app.setEmptyContentMessage(
						{ userId: participantId, displayName: participantName},
						t('spreed', 'Waiting for {participantName} to join the call …', {participantName: participantName})
					);
					break;
				case ROOM_TYPE_PUBLIC_CALL:
				case ROOM_TYPE_GROUP_CALL:
					var icon = '',
						message = '',
						messageAdditional = '',
						url = '';

					if (this.model.get('type') === ROOM_TYPE_PUBLIC_CALL) {
						icon = 'icon-public';
					} else {
						icon = 'icon-contacts-dark';
					}

					message = t('spreed', 'Waiting for others to join the call …');

					if (OC.getCurrentUser().uid !== null && Object.keys(participants).length === 1) {
						message = t('spreed', 'No other people in this call');
						if (this.model.get('participantType') === 0 || this.model.get('participantType') === 1) {
							messageAdditional = t('spreed', 'You can invite others in the participant tab of the sidebar');
						}
					}

					if (this.model.get('type') === ROOM_TYPE_PUBLIC_CALL) {
						messageAdditional = t('spreed', 'Share this link to invite others!');
						if (this.model.get('participantType') === 1 || this.model.get('participantType') === 2) {
							messageAdditional = t('spreed', 'You can invite others in the participant tab of the sidebar or share this link to invite others!');
						}
						url = window.location.protocol + '//' + window.location.host + OC.generateUrl('/call/' + this.model.get('token'));
					}

					OCA.SpreedMe.app.setEmptyContentMessage(icon, message, messageAdditional, url);
					break;
				default:
					console.log("Unknown room type", this.model.get('type'));
					return;
			}
		},
		addTooltip: function () {
			var participants = [];
			$.each(this.model.get('participants'), function(participantId, data) {
				if (participantId !== OC.getCurrentUser().uid) {
					participants.push(escapeHTML(data.name));
				}
			});

			if (this.model.get('guestList') !== '') {
				participants.push(this.model.get('guestList'));
			}

			if (participants.length === 0) {
				participants.push(t('spreed', 'You'));
			} else {
				participants.push(t('spreed', 'and you'));
			}

			var htmlstring = participants.join('
');

			this.ui.room.tooltip({
				placement: 'bottom',
				trigger: 'hover',
				html: 'true',
				title: htmlstring
			});
		}
	});

	var RoomListView = Marionette.CollectionView.extend({
		tagName: 'ul',
		childView: RoomItemView
	});

	OCA.SpreedMe.Views.RoomListView = RoomListView;

})(OC, OCA, Marionette, Handlebars, _, $);
<|endoftext|>


<commit_before>// vim: set ts=2 sw=2 et
// Credit for the solution goes to http://stackoverflow.com/a/11694229

var target = document.querySelector('head > title');

var observer = new window.MutationObserver(
  function(mutations) {
    mutations.forEach(
      function(mutation){
        notify(mutation.target.textContent, true);
      }
    );
  }
);

observer.observe(target, { subtree: true, characterData: true, childList: true });

notify(target.textContent, false);

function notify(title, changed) {
  var count = -1;

  var match = /^\((\d+)\)/.exec(title);
  var match_zero = /^The Old Reader$/.exec(title); // Does not fire on navigation

  if (match && match[1]) {
    count = match[1];
  } else if (match_zero && changed) {
    count = 0;
  }

  if (count >= 0) {
    try {
      chrome.runtime.sendMessage({'count' : count});
    } catch(e) { // Happens when parent extension is no longer available or was reloaded
      console.warn("Could not communicate with parent extension, deregistering observer");
      observer.disconnect();
    }
  }
}

// Declare extension capabilities to the page
var capabilities = {
  openInBrowser : true
};

// Extend capabilities without overriding, in case there is another extension
var code = "window.ExtensionCapabilities = window.ExtensionCapabilities || {};";
for (var key in capabilities) {
  code += "window.ExtensionCapabilities[" + JSON.stringify(key) +
          "] = " + JSON.stringify(capabilities[key]) + ";"
}

var script = document.createElement('script');
script.textContent = code;
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);

// Add an event listener for openPostInBackground
window.addEventListener("tor:openPostInBackground", function(evt) {
  chrome.runtime.sendMessage({openInBackground: true, url: evt.url});
}, false);
<commit_msg>Adapt event data structure (fixes #39)<commit_after>// vim: set ts=2 sw=2 et
// Credit for the solution goes to http://stackoverflow.com/a/11694229

var target = document.querySelector('head > title');

var observer = new window.MutationObserver(
  function(mutations) {
    mutations.forEach(
      function(mutation){
        notify(mutation.target.textContent, true);
      }
    );
  }
);

observer.observe(target, { subtree: true, characterData: true, childList: true });

notify(target.textContent, false);

function notify(title, changed) {
  var count = -1;

  var match = /^\((\d+)\)/.exec(title);
  var match_zero = /^The Old Reader$/.exec(title); // Does not fire on navigation

  if (match && match[1]) {
    count = match[1];
  } else if (match_zero && changed) {
    count = 0;
  }

  if (count >= 0) {
    try {
      chrome.runtime.sendMessage({'count' : count});
    } catch(e) { // Happens when parent extension is no longer available or was reloaded
      console.warn("Could not communicate with parent extension, deregistering observer");
      observer.disconnect();
    }
  }
}

// Declare extension capabilities to the page
var capabilities = {
  openInBrowser : true
};

// Extend capabilities without overriding, in case there is another extension
var code = "window.ExtensionCapabilities = window.ExtensionCapabilities || {};";
for (var key in capabilities) {
  code += "window.ExtensionCapabilities[" + JSON.stringify(key) +
          "] = " + JSON.stringify(capabilities[key]) + ";"
}

var script = document.createElement('script');
script.textContent = code;
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);

// Add an event listener for openPostInBackground
window.addEventListener("tor:openPostInBackground", function(evt) {
  chrome.runtime.sendMessage({openInBackground: true, url: evt.detail});
}, false);
<|endoftext|>


<commit_before>goog.module('ngeo.olcs.Manager');
goog.module.declareLegacyNamespace();

goog.require('olcs.contrib.Manager');

const Manager = class extends olcs.contrib.Manager {
  /**
   * @override
   */
  constructor() {
    super(...arguments);
    /**
     * @type {angular.Scope}
     * @private
     */
    this.rootScope_;
  }

  /**
   * @param {angular.Scope} $rootScope Angular root scope.
   */
  setRootScope($rootScope) {
    this.rootScope_ = $rootScope;
  }

  /**
   * @override
   */
  toggle3d() {
    return super.toggle3d().then(() => {
      this.rootScope_.$apply(() => {});
    });
  }
};

exports = Manager;
<commit_msg>Fix calls to constructor in dependent projects<commit_after>goog.module('ngeo.olcs.Manager');
goog.module.declareLegacyNamespace();

goog.require('olcs.contrib.Manager');

const Manager = class extends olcs.contrib.Manager {
  /**
   * @override
   */
  constructor(...args) {
    super(...args);
    /**
     * @type {angular.Scope}
     * @private
     */
    this.rootScope_;
  }

  /**
   * @param {angular.Scope} $rootScope Angular root scope.
   */
  setRootScope($rootScope) {
    this.rootScope_ = $rootScope;
  }

  /**
   * @override
   */
  toggle3d() {
    return super.toggle3d().then(() => {
      this.rootScope_.$apply(() => {});
    });
  }
};

exports = Manager;
<|endoftext|>


<commit_before>/* globals L:true, ActiveXObject:true, Terraformer */

L.esri.BasemapLayer = L.TileLayer.extend({
  statics: {
    TILES: {
      Streets: {
        urlTemplate: "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
        attributionUrl: "http://static.arcgis.com/attribution/World_Street_Map?f=json",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri"
        }
      },
      Topographic: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}",
        attributionUrl: "http://static.arcgis.com/attribution/World_Topo_Map?f=json",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri"
        }
      },
      Oceans: {
        urlTemplate: "http://server.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/{z}/{y}/{x}",
        attributionUrl: "http://static.arcgis.com/attribution/Ocean_Basemap?f=json",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri"
        }
      },
      NationalGeographic: {
        urlTemplate: "http://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri"
        }
      },
      Gray: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Copyright: ©2013 Esri, DeLorme, NAVTEQ"
        }
      },
      GrayLabels: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19
        }
      },
      Imagery: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri, DigitalGlobe, GeoEye, i-cubed, USDA, USGS, AEX, Getmapping, Aerogrid, IGN, IGP, swisstopo, and the GIS User Community"
        }
      },
      ImageryLabels: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19
        }
      }
    }
  },
  initialize: function(key, options){
    var config;

    // set the config variable with the appropriate config object
    if (typeof key === "object" && key.urlTemplate && key.options){
      config = key;
    } else if(typeof key === "string" && L.esri.BasemapLayer.TILES[key]){
      config = L.esri.BasemapLayer.TILES[key];
    } else {
      throw new Error("L.esri.TileLayer: Invalid parameter. Use one of 'Streets', 'Topographic', 'Oceans', 'NationalGeographic', 'Gray', 'GrayLabels', 'Imagery' or 'ImageryLabels'");
    }

    // merge passed options into the config options
    var mergedOptions = L.Util.extend(config.options, options);

    // call the initialize method on L.TileLayer to set everything up
    L.TileLayer.prototype.initialize.call(this, config.urlTemplate, L.Util.setOptions(this, mergedOptions));

    // if this basemap requires dynamic attribution set it up
    if(config.attributionUrl){
      this.dynamicAttribution = true;
      this.getAttributionData(config.attributionUrl);
    }
  },
  dynamicAttribution: false,
  bounds: null,
  zoom: null,
  handleTileUpdates: function(e){
    var newBounds;
    var newZoom;

    if(e.type === "load"){
      newBounds = this._map.getBounds();
      newZoom = this._map.getZoom();
    }

    if(e.type === "viewreset" || e.type === "dragend" || e.type ==="zoomend"){
      newBounds = e.target.getBounds();
      newZoom = e.target.getZoom();
    }

    if(this.attributionBoundingBoxes && newBounds && newZoom){
      if(!newBounds.equals(this.bounds) || newZoom !== this.zoom){
        this.bounds = newBounds;
        this.zoom = newZoom;
        this.updateMapAttribution();
      }
    }
  },
  onAdd: function(map){
    L.TileLayer.prototype.onAdd.call(this, map);
    if(this.dynamicAttribution){
      this.on("load", this.handleTileUpdates);
      this._map.on("viewreset zoomend dragend", this.handleTileUpdates);
      this._map.on("resize", this.resizeAttribution);
    }
  },
  resizeAttribution: function(){
    this.attributionSpan.style.maxWidth = (this._map.getSize().x * 0.75) - 65 + "px";
  },
  onRemove: function(map){
    if(this.dynamicAttribution){
      this.off("load", this.handleTileUpdates);
      this._map.off("viewreset zoomend dragend", this.handleTileUpdates);
      this._map.off("resize", this.resizeAttribution);
    }
    L.TileLayer.prototype.onRemove.call(this, map);
  },
  getAttributionData: function(url){
    this.attributionBoundingBoxes = [];
    var httpRequest;
    if (window.XMLHttpRequest) {
      httpRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
      httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    }
    httpRequest.onreadystatechange = L.bind(this.processAttributionData, this);
    httpRequest.open('GET', url, true);
    httpRequest.send(null);
  },
  processAttributionData: function(httpRequest){
    if (httpRequest.target.readyState === 4 && httpRequest.target.status === 200) {
      this.attributionIndex = new Terraformer.RTree();
      var attributionData = JSON.parse(httpRequest.target.responseText);

      for (var c = 0; c < attributionData.contributors.length; c++) {
        var contributor = attributionData.contributors[c];
        for (var i = 0; i < contributor.coverageAreas.length; i++) {
          var coverageArea = contributor.coverageAreas[i];
          var southWest = new L.LatLng(coverageArea.bbox[0], coverageArea.bbox[1]);
          var northEast = new L.LatLng(coverageArea.bbox[2], coverageArea.bbox[3]);
          var bounds = new L.LatLngBounds(southWest, northEast);
          var envelope = L.esri.Util.boundsToEnvelope(bounds);
          this.attributionIndex.insert(envelope, {
            attribution: contributor.attribution,
            score: coverageArea.score,
            minZoom: coverageArea.zoomMin,
            maxZoom: coverageArea.zoomMax
          });
        }
      }

      if(this.bounds){
        this.updateMapAttribution();
      }
    }
  },
  updateMapAttribution: function(){
    var newAttributions = [];
    var searchEnvelope = L.esri.Util.boundsToEnvelope(this.bounds);
    if(this.attributionIndex){
      this.attributionIndex.search(searchEnvelope).then(L.Util.bind(function(results){
        results.sort(function(a,b){
          if (a.score  b.score){ return 1; }
          return 0;
        });

        for (var i = results.length - 1; i >= 0; i--) {
          var result = results[i];
          if(this.zoom >= result.minZoom && this.zoom <= result.maxZoom){
            if(newAttributions.indexOf(result.attribution) === -1){
              newAttributions.push(result.attribution);
            }
          }
        }

        this.attributionSpan = this._map._container.getElementsByClassName("esri-attributions")[0];
        this.attributionSpan.innerHTML = newAttributions.join(", ");
        this.resizeAttribution();
      }, this));
    }
  }
});

L.esri.basemapLayer = function(key, options){
  return new L.esri.BasemapLayer(key, options);
};<commit_msg>Add L.esri namespace to new BasemapLayer.js so it can be used stand-alone to load L.esri.basemapLayer<commit_after>/* globals L:true, ActiveXObject:true, Terraformer */

if(typeof L.esri === "undefined"){
  L.esri = {};
}

L.esri.BasemapLayer = L.TileLayer.extend({
  statics: {
    TILES: {
      Streets: {
        urlTemplate: "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
        attributionUrl: "http://static.arcgis.com/attribution/World_Street_Map?f=json",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri"
        }
      },
      Topographic: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}",
        attributionUrl: "http://static.arcgis.com/attribution/World_Topo_Map?f=json",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri"
        }
      },
      Oceans: {
        urlTemplate: "http://server.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/{z}/{y}/{x}",
        attributionUrl: "http://static.arcgis.com/attribution/Ocean_Basemap?f=json",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri"
        }
      },
      NationalGeographic: {
        urlTemplate: "http://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri"
        }
      },
      Gray: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Copyright: ©2013 Esri, DeLorme, NAVTEQ"
        }
      },
      GrayLabels: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19
        }
      },
      Imagery: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19,
          attribution: "Esri, DigitalGlobe, GeoEye, i-cubed, USDA, USGS, AEX, Getmapping, Aerogrid, IGN, IGP, swisstopo, and the GIS User Community"
        }
      },
      ImageryLabels: {
        urlTemplate: "http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer/tile/{z}/{y}/{x}",
        options: {
          minZoom: 1,
          maxZoom: 19
        }
      }
    }
  },
  initialize: function(key, options){
    var config;

    // set the config variable with the appropriate config object
    if (typeof key === "object" && key.urlTemplate && key.options){
      config = key;
    } else if(typeof key === "string" && L.esri.BasemapLayer.TILES[key]){
      config = L.esri.BasemapLayer.TILES[key];
    } else {
      throw new Error("L.esri.TileLayer: Invalid parameter. Use one of 'Streets', 'Topographic', 'Oceans', 'NationalGeographic', 'Gray', 'GrayLabels', 'Imagery' or 'ImageryLabels'");
    }

    // merge passed options into the config options
    var mergedOptions = L.Util.extend(config.options, options);

    // call the initialize method on L.TileLayer to set everything up
    L.TileLayer.prototype.initialize.call(this, config.urlTemplate, L.Util.setOptions(this, mergedOptions));

    // if this basemap requires dynamic attribution set it up
    if(config.attributionUrl){
      this.dynamicAttribution = true;
      this.getAttributionData(config.attributionUrl);
    }
  },
  dynamicAttribution: false,
  bounds: null,
  zoom: null,
  handleTileUpdates: function(e){
    var newBounds;
    var newZoom;

    if(e.type === "load"){
      newBounds = this._map.getBounds();
      newZoom = this._map.getZoom();
    }

    if(e.type === "viewreset" || e.type === "dragend" || e.type ==="zoomend"){
      newBounds = e.target.getBounds();
      newZoom = e.target.getZoom();
    }

    if(this.attributionBoundingBoxes && newBounds && newZoom){
      if(!newBounds.equals(this.bounds) || newZoom !== this.zoom){
        this.bounds = newBounds;
        this.zoom = newZoom;
        this.updateMapAttribution();
      }
    }
  },
  onAdd: function(map){
    L.TileLayer.prototype.onAdd.call(this, map);
    if(this.dynamicAttribution){
      this.on("load", this.handleTileUpdates);
      this._map.on("viewreset zoomend dragend", this.handleTileUpdates);
      this._map.on("resize", this.resizeAttribution);
    }
  },
  resizeAttribution: function(){
    this.attributionSpan.style.maxWidth = (this._map.getSize().x * 0.75) - 65 + "px";
  },
  onRemove: function(map){
    if(this.dynamicAttribution){
      this.off("load", this.handleTileUpdates);
      this._map.off("viewreset zoomend dragend", this.handleTileUpdates);
      this._map.off("resize", this.resizeAttribution);
    }
    L.TileLayer.prototype.onRemove.call(this, map);
  },
  getAttributionData: function(url){
    this.attributionBoundingBoxes = [];
    var httpRequest;
    if (window.XMLHttpRequest) {
      httpRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
      httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    }
    httpRequest.onreadystatechange = L.bind(this.processAttributionData, this);
    httpRequest.open('GET', url, true);
    httpRequest.send(null);
  },
  processAttributionData: function(httpRequest){
    if (httpRequest.target.readyState === 4 && httpRequest.target.status === 200) {
      this.attributionIndex = new Terraformer.RTree();
      var attributionData = JSON.parse(httpRequest.target.responseText);

      for (var c = 0; c < attributionData.contributors.length; c++) {
        var contributor = attributionData.contributors[c];
        for (var i = 0; i < contributor.coverageAreas.length; i++) {
          var coverageArea = contributor.coverageAreas[i];
          var southWest = new L.LatLng(coverageArea.bbox[0], coverageArea.bbox[1]);
          var northEast = new L.LatLng(coverageArea.bbox[2], coverageArea.bbox[3]);
          var bounds = new L.LatLngBounds(southWest, northEast);
          var envelope = L.esri.Util.boundsToEnvelope(bounds);
          this.attributionIndex.insert(envelope, {
            attribution: contributor.attribution,
            score: coverageArea.score,
            minZoom: coverageArea.zoomMin,
            maxZoom: coverageArea.zoomMax
          });
        }
      }

      if(this.bounds){
        this.updateMapAttribution();
      }
    }
  },
  updateMapAttribution: function(){
    var newAttributions = [];
    var searchEnvelope = L.esri.Util.boundsToEnvelope(this.bounds);
    if(this.attributionIndex){
      this.attributionIndex.search(searchEnvelope).then(L.Util.bind(function(results){
        results.sort(function(a,b){
          if (a.score  b.score){ return 1; }
          return 0;
        });

        for (var i = results.length - 1; i >= 0; i--) {
          var result = results[i];
          if(this.zoom >= result.minZoom && this.zoom <= result.maxZoom){
            if(newAttributions.indexOf(result.attribution) === -1){
              newAttributions.push(result.attribution);
            }
          }
        }

        this.attributionSpan = this._map._container.getElementsByClassName("esri-attributions")[0];
        this.attributionSpan.innerHTML = newAttributions.join(", ");
        this.resizeAttribution();
      }, this));
    }
  }
});

L.esri.basemapLayer = function(key, options){
  return new L.esri.BasemapLayer(key, options);
};<|endoftext|>


<commit_before>import {createAction} from 'redux-actions';
import values from 'lodash/values';
import {UnitActions, SearchActions} from './constants';
import {Action} from '../common/constants';
import {ApiResponse, UnitServices} from './constants';

export const fetchUnits = (/*params: Object*/): Action =>
  createAction(UnitActions.FETCH)({params: {
    service: `${values(UnitServices).join(',')}`,
    include: 'observations',
    page_size: 1000
  }});

export const receiveUnits = (data: ApiResponse): Action =>
  createAction(UnitActions.RECEIVE)(data);

export const searchTarget = (data) =>
  createAction(SearchActions.SEARCH)(data);

export const receiveSearchResults = (results) =>
  createAction(SearchActions.RECEIVE_SEARCH_RESULTS)(results);
<commit_msg>Include service info in unit fetches<commit_after>import {createAction} from 'redux-actions';
import values from 'lodash/values';
import {UnitActions, SearchActions} from './constants';
import {Action} from '../common/constants';
import {ApiResponse, UnitServices} from './constants';

export const fetchUnits = (/*params: Object*/): Action =>
  createAction(UnitActions.FETCH)({params: {
    service: `${values(UnitServices).join(',')}`,
    include: 'observations,services',
    page_size: 1000
  }});

export const receiveUnits = (data: ApiResponse): Action =>
  createAction(UnitActions.RECEIVE)(data);

export const searchTarget = (data) =>
  createAction(SearchActions.SEARCH)(data);

export const receiveSearchResults = (results) =>
  createAction(SearchActions.RECEIVE_SEARCH_RESULTS)(results);
<|endoftext|>


<commit_before>//* @protected
enyo.requiresWindow(function() {
	// add touch-specific gesture feature
	var gesture = enyo.gesture;
	var oldevents = gesture.events;
	//
	gesture.events.touchstart = function(e) {
		// for duration of this touch, only handle touch events.  Old event
		// structure will be restored during touchend.
		gesture.events = touchGesture;
		gesture.events.touchstart(e);
	};
	//
	var touchGesture = {
		_touchCount: 0,
		touchstart: function(inEvent) {
			enyo.job.stop("resetGestureEvents");
			this._touchCount += inEvent.changedTouches.length;
			this.excludedTarget = null;
			var e = this.makeEvent(inEvent);
			gesture.down(e);
			// generate a new event object since over is a different event
			e = this.makeEvent(inEvent);
			this.overEvent = e;
			gesture.over(e);
		},
		touchmove: function(inEvent) {
			enyo.job.stop("resetGestureEvents");
			// NOTE: allow user to supply a node to exclude from event
			// target finding via the drag event.
			var de = gesture.drag.dragEvent;
			this.excludedTarget = de && de.dragInfo && de.dragInfo.node;
			var e = this.makeEvent(inEvent);
			gesture.move(e);
			// prevent default document scrolling if enyo.bodyIsFitting == true
			// avoid window scrolling by preventing default on this event
			// note: this event can be made unpreventable (native scrollers do this)
			if (enyo.bodyIsFitting) {
				inEvent.preventDefault();
			}
			// synthesize over and out (normally generated via mouseout)
			if (this.overEvent && this.overEvent.target != e.target) {
				this.overEvent.relatedTarget = e.target;
				e.relatedTarget = this.overEvent.target;
				gesture.out(this.overEvent);
				gesture.over(e);
			}
			this.overEvent = e;
		},
		touchend: function(inEvent) {
			gesture.up(this.makeEvent(inEvent));
			// NOTE: in touch land, there is no distinction between
			// a pointer enter/leave and a drag over/out.
			// While it may make sense to send a leave event when a touch
			// ends, it does not make sense to send a dragout.
			// We avoid this by processing out after up, but
			// this ordering is ad hoc.
			gesture.out(this.overEvent);
			// reset the event handlers back to the mouse-friendly ones after
			// a short timeout. We can't do this directly in this handler
			// because it messes up Android to handle the mouseup event.
			// FIXME: for 2.1 release, conditional on platform being
			// desktop Chrome, since we're seeing issues in PhoneGap with this
			// code.
			this._touchCount -= inEvent.changedTouches.length;
			if (enyo.platform.chrome && this._touchCount === 0) {
				enyo.job("resetGestureEvents", function() {
					gesture.events = oldevents;
				}, 10);
			}
		},
		makeEvent: function(inEvent) {
			var e = enyo.clone(inEvent.changedTouches[0]);
			e.srcEvent = inEvent;
			e.target = this.findTarget(e.clientX, e.clientY);
			// normalize "mouse button" info
			e.which = 1;
			//console.log("target for " + inEvent.type + " at " + e.pageX + ", " + e.pageY + " is " + (e.target ? e.target.id : "none"));
			return e;
		},
		calcNodeOffset: function(inNode) {
			if (inNode.getBoundingClientRect) {
				var o = inNode.getBoundingClientRect();
				return {
					left: o.left,
					top: o.top,
					width: o.width,
					height: o.height
				};
			}
		},
		findTarget: function(inX, inY) {
			return document.elementFromPoint(inX, inY);
		},
		// NOTE: will find only 1 element under the touch and
		// will fail if an element is positioned outside the bounding box of its parent
		findTargetTraverse: function(inNode, inX, inY) {
			var n = inNode || document.body;
			var o = this.calcNodeOffset(n);
			if (o && n != this.excludedTarget) {
				var x = inX - o.left;
				var y = inY - o.top;
				//console.log("test: " + n.id + " (left: " + o.left + ", top: " + o.top + ", width: " + o.width + ", height: " + o.height + ")");
				if (x>0 && y>0 && x<=o.width && y<=o.height) {
					//console.log("IN: " + n.id + " -> [" + x + "," + y + " in " + o.width + "x" + o.height + "] (children: " + n.childNodes.length + ")");
					var target;
					for (var n$=n.childNodes, i=n$.length-1, c; (c=n$[i]); i--) {
						target = this.findTargetTraverse(c, inX, inY);
						if (target) {
							return target;
						}
					}
					return n;
				}
			}
		},
		connect: function() {
			enyo.forEach(['ontouchstart', 'ontouchmove', 'ontouchend', 'ongesturestart', 'ongesturechange', 'ongestureend'], function(e) {
				document[e] = enyo.dispatch;
			});
			// use proper target finding technique based on feature detection.
			if (enyo.platform.androidChrome <= 18) {
				// HACK: on Chrome for Android v18 on devices with higher density displays,
				// document.elementFromPoint uses wrong pixel system, so manually scale
				var dpr = window.devicePixelRatio;
				this.findTarget = function(inX, inY) {
					return document.elementFromPoint(inX * dpr, inY * dpr);
				};
			} else if (!document.elementFromPoint) {
				this.findTarget = function(inX, inY) {
					return this.findTargetTraverse(null, inX, inY);
				};
			}
		}
	};
	//
	touchGesture.connect();
});<commit_msg>ENYO-1300: change chrome on Android findTarget code to use screenX/Y instead of clientX/Y to work around bug<commit_after>//* @protected
enyo.requiresWindow(function() {
	// add touch-specific gesture feature
	var gesture = enyo.gesture;
	var oldevents = gesture.events;
	//
	gesture.events.touchstart = function(e) {
		// for duration of this touch, only handle touch events.  Old event
		// structure will be restored during touchend.
		gesture.events = touchGesture;
		gesture.events.touchstart(e);
	};
	//
	var touchGesture = {
		_touchCount: 0,
		touchstart: function(inEvent) {
			enyo.job.stop("resetGestureEvents");
			this._touchCount += inEvent.changedTouches.length;
			this.excludedTarget = null;
			var e = this.makeEvent(inEvent);
			gesture.down(e);
			// generate a new event object since over is a different event
			e = this.makeEvent(inEvent);
			this.overEvent = e;
			gesture.over(e);
		},
		touchmove: function(inEvent) {
			enyo.job.stop("resetGestureEvents");
			// NOTE: allow user to supply a node to exclude from event
			// target finding via the drag event.
			var de = gesture.drag.dragEvent;
			this.excludedTarget = de && de.dragInfo && de.dragInfo.node;
			var e = this.makeEvent(inEvent);
			gesture.move(e);
			// prevent default document scrolling if enyo.bodyIsFitting == true
			// avoid window scrolling by preventing default on this event
			// note: this event can be made unpreventable (native scrollers do this)
			if (enyo.bodyIsFitting) {
				inEvent.preventDefault();
			}
			// synthesize over and out (normally generated via mouseout)
			if (this.overEvent && this.overEvent.target != e.target) {
				this.overEvent.relatedTarget = e.target;
				e.relatedTarget = this.overEvent.target;
				gesture.out(this.overEvent);
				gesture.over(e);
			}
			this.overEvent = e;
		},
		touchend: function(inEvent) {
			gesture.up(this.makeEvent(inEvent));
			// NOTE: in touch land, there is no distinction between
			// a pointer enter/leave and a drag over/out.
			// While it may make sense to send a leave event when a touch
			// ends, it does not make sense to send a dragout.
			// We avoid this by processing out after up, but
			// this ordering is ad hoc.
			gesture.out(this.overEvent);
			// reset the event handlers back to the mouse-friendly ones after
			// a short timeout. We can't do this directly in this handler
			// because it messes up Android to handle the mouseup event.
			// FIXME: for 2.1 release, conditional on platform being
			// desktop Chrome, since we're seeing issues in PhoneGap with this
			// code.
			this._touchCount -= inEvent.changedTouches.length;
			if (enyo.platform.chrome && this._touchCount === 0) {
				enyo.job("resetGestureEvents", function() {
					gesture.events = oldevents;
				}, 10);
			}
		},
		makeEvent: function(inEvent) {
			var e = enyo.clone(inEvent.changedTouches[0]);
			e.srcEvent = inEvent;
			e.target = this.findTarget(e);
			// normalize "mouse button" info
			e.which = 1;
			//console.log("target for " + inEvent.type + " at " + e.pageX + ", " + e.pageY + " is " + (e.target ? e.target.id : "none"));
			return e;
		},
		calcNodeOffset: function(inNode) {
			if (inNode.getBoundingClientRect) {
				var o = inNode.getBoundingClientRect();
				return {
					left: o.left,
					top: o.top,
					width: o.width,
					height: o.height
				};
			}
		},
		findTarget: function(e) {
			return document.elementFromPoint(e.clientX, e.clientY);
		},
		// NOTE: will find only 1 element under the touch and
		// will fail if an element is positioned outside the bounding box of its parent
		findTargetTraverse: function(inNode, inX, inY) {
			var n = inNode || document.body;
			var o = this.calcNodeOffset(n);
			if (o && n != this.excludedTarget) {
				var x = inX - o.left;
				var y = inY - o.top;
				//console.log("test: " + n.id + " (left: " + o.left + ", top: " + o.top + ", width: " + o.width + ", height: " + o.height + ")");
				if (x>0 && y>0 && x<=o.width && y<=o.height) {
					//console.log("IN: " + n.id + " -> [" + x + "," + y + " in " + o.width + "x" + o.height + "] (children: " + n.childNodes.length + ")");
					var target;
					for (var n$=n.childNodes, i=n$.length-1, c; (c=n$[i]); i--) {
						target = this.findTargetTraverse(c, inX, inY);
						if (target) {
							return target;
						}
					}
					return n;
				}
			}
		},
		connect: function() {
			enyo.forEach(['ontouchstart', 'ontouchmove', 'ontouchend', 'ongesturestart', 'ongesturechange', 'ongestureend'], function(e) {
				document[e] = enyo.dispatch;
			});
			// use proper target finding technique based on feature detection.
			if (enyo.platform.androidChrome <= 18) {
				// HACK: on Chrome for Android v18 on devices with higher density displays,
				// document.elementFromPoint expects screen coordinates, not document ones
				this.findTarget = function(e) {
					return document.elementFromPoint(e.screenX, e.screenY);
				};
			} else if (!document.elementFromPoint) {
				this.findTarget = function(e) {
					return this.findTargetTraverse(null, e.clientX, e.clientY);
				};
			}
		}
	};
	//
	touchGesture.connect();
});<|endoftext|>


<commit_before>var exec = require("child_process").exec;

function start(response) {
	console.log("Request handler 'start' was called.");

	exec(
		"ls -lah",
		function (error, stdout, stderr) {
			response.writeHead(200, {"Content-Type": "text/plain"});
			response.write(stdout);
			response.end();
		}
	);
}

function upload(response) {
	console.log("Request handler 'upload' was called.");
	response.writeHead(200, {"Content-Type": "text/plain"});
	response.write("Hello Upload");
	response.end();
}

exports.start = start;
exports.upload = upload;
<commit_msg>Write HTML in `response`<commit_after>function start(response) {
	console.log("Request handler 'start' was called.");

	var body = ''+
		''+
		'<meta http-equiv="Content-Type" content="text/html; '+
		'charset=UTF-8" />'+
		''+
		''+
		'<form action="/upload" method="post">'+
		'<textarea name="text" rows="20" cols="60"></textarea>'+
		'<input type="submit" value="Submit text" />'+
		'</form>'+
		''+
		'';

	response.writeHead(200, {"Content-Type": "text/html"});
	response.write(body);
	response.end();
}

function upload(response) {
	console.log("Request handler 'upload' was called.");
	response.writeHead(200, {"Content-Type": "text/plain"});
	response.write("Hello Upload");
	response.end();
}

exports.start = start;
exports.upload = upload;
<|endoftext|>


<commit_before>const _ = require("lodash");
const CarouselClass = require("../src/carousel");
// const ViewportDetect = require("viewport-detection-es6");

function createCarousel() {
  let carouselInner = document.createElement("div");
  let carouselOuter = document.createElement("div");

  carouselInner.className = "carousel-inner";
  carouselOuter.id = "carousel";

  carouselOuter.appendChild(carouselInner);

  createCarouselItems(carouselInner);

  document.body.appendChild(carouselOuter);

  return carouselOuter;
}

function createCarouselImageContainers(item, i) {
  let dataURLDesktop, dataURLMobile, dataURLTablet;
  let carouselImageContainer = document.createElement("div");

  carouselImageContainer.className = "carousel-image-container";

  dataURLDesktop = "desktop.jpg";

  if(i % 2) {
    dataURLMobile = "null";
    dataURLTablet = "null";
  } else {
    dataURLMobile = "mobile.jpg";
    dataURLTablet = "tablet.jpg";
  }

  carouselImageContainer.setAttribute("data-mobile", dataURLMobile);
  carouselImageContainer.setAttribute("data-tablet", dataURLTablet);
  carouselImageContainer.setAttribute("data-desktop", dataURLDesktop);

  carouselImageContainer.style.backgroundImage = "url('" + dataURLDesktop + "')";

  createCarouselOverlays(carouselImageContainer, i);

  item.appendChild(carouselImageContainer);
}

function createCarouselItems(carouselInner, items = 2) {
  let item;
  let range = _.range(1, (items + 1));

  _.forEach(range, (i) => {
    item = document.createElement("div");
    item.className = "carousel-item";

    createCarouselImageContainers(item, i);

    carouselInner.appendChild(item);
  });
}

function createCarouselOverlays(carouselImageContainer, i) {
  let carouselOverlay = document.createElement("div");
  let a = document.createElement("a");
  let subtitle = document.createElement("h3");
  let title = document.createElement("h2");

  carouselOverlay.className = "carousel-overlay";

  if(i % 2) {
    a.href = "http://www.bobdylan.com";
    a.innerHTML = "Bob Dylan";
    title.innerHTML = "Bob Dylan's official website"
    subtitle.innerHTML = "Blind boy grunt"

  } else {
    a.href = "http://www.paulsimon.com";
    a.innerHTML = "Paul Simon";
    title.innerHTML = "Paul Simon's official website"
    subtitle.innerHTML = "He's a tiny little showbiz man"
  }

  carouselOverlay.appendChild(title);
  carouselOverlay.appendChild(subtitle);
  carouselOverlay.appendChild(a);

  carouselImageContainer.appendChild(carouselOverlay);
}

describe("carousel", () => {
  let c, carousel, viewport, revert;

  beforeEach(() => {
    c = createCarousel();
    viewport = CarouselClass.__get__("viewport");

    carousel = new CarouselClass({
      element: c,
      autoPlay: false,
      itemClass: "carousel-item"
    }, false);
  });

  // afterEach(()=>{
  //   revert();
  // })

  it("should exist", () => {
    expect(carousel).toBeDefined();
  });

  describe("render function", () => {
    beforeEach(() => {
      spyOn(carousel, "_getItems");
      spyOn(carousel, "_setDefaultSelected");

      carousel.render();
    });

    it("should call the _getItems function", () => {
      expect(carousel._getItems).toHaveBeenCalled();
    });

    it("should call the _setDefaultSelected function", () => {
      expect(carousel._setDefaultSelected).toHaveBeenCalled();
    });
  });

  describe("_init function", () => {
    beforeEach(() => {
      spyOn(carousel, "render");

      carousel._init();
    });

    it("should set this.animating to false", () => {
      expect(carousel.animating).toBeFalsy();
    });

    it("should set this.eventManager to the _manageListeners function", () => {
      expect(carousel.eventManager.addListener).toBeDefined();
      expect(carousel.eventManager.removeAll).toBeDefined();
    });

    it("should set this.hasDataURLs to false", () => {
      expect(carousel.hasDataURLs).toBeFalsy();
    });

    it("should set this.itemActive to 0", () => {
      expect(carousel.itemActive).toEqual(0);
    });

    it("should set this.items to be an empty array", () => {
      expect(carousel.items.length).toEqual(0);
    });

    it("should call the render function", () => {
      expect(carousel.render).toHaveBeenCalled();
    });
  });

  describe("_initViewport function", () => {
    beforeEach(() => {
      spyOn(viewport, "trackSize");
      spyOn(viewport, "getDevice").and.returnValue("bollocks");
    });

    it("should set this.device to the viewport.getDevice function", () => {
      carousel._initViewport();

      expect(carousel.device).toEqual("bollocks");
    });

    // Ade, why is this failing? I'm confused!
    // it("should call the viewport.trackSize function", () => {
    //   expect(viewport.trackSize).toHaveBeenCalled();
    // });
  });
});<commit_msg>Adding tests<commit_after>const _ = require("lodash");
const CarouselClass = require("../src/carousel");

function createCarousel() {
  let carouselInner = document.createElement("div");
  let carouselOuter = document.createElement("div");

  carouselInner.className = "carousel-inner";
  carouselOuter.id = "carousel";

  carouselOuter.appendChild(carouselInner);

  createCarouselItems(carouselInner);

  document.body.appendChild(carouselOuter);

  return carouselOuter;
}

function createCarouselImageContainers(item, i) {
  let dataURLDesktop, dataURLMobile, dataURLTablet;
  let carouselImageContainer = document.createElement("div");

  carouselImageContainer.className = "carousel-image-container";

  dataURLDesktop = "desktop.jpg";

  if(i % 2) {
    dataURLMobile = "null";
    dataURLTablet = "null";
  } else {
    dataURLMobile = "mobile.jpg";
    dataURLTablet = "tablet.jpg";
  }

  carouselImageContainer.setAttribute("data-mobile", dataURLMobile);
  carouselImageContainer.setAttribute("data-tablet", dataURLTablet);
  carouselImageContainer.setAttribute("data-desktop", dataURLDesktop);

  carouselImageContainer.style.backgroundImage = "url('" + dataURLDesktop + "')";

  createCarouselOverlays(carouselImageContainer, i);

  item.appendChild(carouselImageContainer);
}

function createCarouselItems(carouselInner, items = 2) {
  let item;
  let range = _.range(1, (items + 1));

  _.forEach(range, (i) => {
    item = document.createElement("div");
    item.className = "carousel-item";

    createCarouselImageContainers(item, i);

    carouselInner.appendChild(item);
  });
}

function createCarouselOverlays(carouselImageContainer, i) {
  let carouselOverlay = document.createElement("div");
  let a = document.createElement("a");
  let subtitle = document.createElement("h3");
  let title = document.createElement("h2");

  carouselOverlay.className = "carousel-overlay";

  if(i % 2) {
    a.href = "http://www.bobdylan.com";
    a.innerHTML = "Bob Dylan";
    title.innerHTML = "Bob Dylan's official website"
    subtitle.innerHTML = "Blind boy grunt"

  } else {
    a.href = "http://www.paulsimon.com";
    a.innerHTML = "Paul Simon";
    title.innerHTML = "Paul Simon's official website"
    subtitle.innerHTML = "He's a tiny little showbiz man"
  }

  carouselOverlay.appendChild(title);
  carouselOverlay.appendChild(subtitle);
  carouselOverlay.appendChild(a);

  carouselImageContainer.appendChild(carouselOverlay);
}

describe("carousel", () => {
  let c, carousel, viewport;

  beforeEach(() => {
    c = createCarousel();
    viewport = CarouselClass.__get__("viewport");

    carousel = new CarouselClass({
      element: c,
      autoPlay: false,
      itemClass: "carousel-item"
    }, false);
  });

  it("should exist", () => {
    expect(carousel).toBeDefined();
  });

  describe("render function", () => {
    beforeEach(() => {
      spyOn(carousel, "_getItems");
      spyOn(carousel, "_setDefaultSelected");

      carousel.render();
    });

    it("should call the _getItems function", () => {
      expect(carousel._getItems).toHaveBeenCalled();
    });

    it("should call the _setDefaultSelected function", () => {
      expect(carousel._setDefaultSelected).toHaveBeenCalled();
    });
  });

  describe("_init function", () => {
    beforeEach(() => {
      spyOn(carousel, "render");

      carousel._init();
    });

    it("should set this.animating to false", () => {
      expect(carousel.animating).toBeFalsy();
    });

    it("should set this.eventManager to the _manageListeners function", () => {
      expect(carousel.eventManager.addListener).toBeDefined();
      expect(carousel.eventManager.removeAll).toBeDefined();
    });

    it("should set this.hasDataURLs to false", () => {
      expect(carousel.hasDataURLs).toBeFalsy();
    });

    it("should set this.itemActive to 0", () => {
      expect(carousel.itemActive).toEqual(0);
    });

    it("should set this.items to be an empty array", () => {
      expect(carousel.items.length).toEqual(0);
    });

    it("should call the render function", () => {
      expect(carousel.render).toHaveBeenCalled();
    });
  });

  describe("_initViewport function", () => {
    beforeEach(() => {
      spyOn(viewport, "getDevice").and.returnValue("massive swanky monitor");
      spyOn(viewport, "windowSize").and.returnValue("99999px");
      spyOn(viewport, "trackSize");

      carousel._initViewport();

    });

    it("should set this.device to the viewport.getDevice function", () => {

      expect(carousel.device).toEqual("massive swanky monitor");
    });

    it("should set this.size to the viewport.windowSize function", () => {

      expect(carousel.size).toEqual("99999px");
    });

    it("should call the viewport.trackSize function", () => {
      expect(viewport.trackSize).toHaveBeenCalled();
    });
  });
});<|endoftext|>


<commit_before>var expect       = require('expect.js');
var EventEmitter = require('events').EventEmitter;
var Inspector    = require('../lib/inspector.js');
var fixtures     = require('./fixtures');

describe('Inspector', function() {
  // Used to test emitted events
  var found;
  var listener = function(match) {
    found.push(match);
  };

  beforeEach(function() {
    found = [];
  });

  describe('constructor', function() {
    it('inherits from EventEmitter', function() {
      expect(new Inspector()).to.be.an(EventEmitter);
    });

    it('accepts an array of file paths', function() {
      var filePaths = ['path1.js', 'path2.js'];
      var inspector = new Inspector(filePaths);
      expect(inspector._filePaths).to.be(filePaths);
    });

    it('assigns a default threshold of 30', function() {
      var inspector = new Inspector([]);
      expect(inspector._threshold).to.be(30);
    });

    it('accepts an options object', function() {
      var opts = {threshold: 12};
      var inspector = new Inspector([], opts);
      expect(inspector._threshold).to.be(opts.threshold);
    });
  });

  describe('run', function() {
    it('emits a start event', function() {
      var emitted;
      var inspector = new Inspector([fixtures.intersection]);
      inspector.on('start', function() {
        emitted = true;
      });

      inspector.run();
      expect(emitted).to.be(true);
    });

    it('emits an end event', function() {
      var emitted;
      var inspector = new Inspector([fixtures.intersection]);
      inspector.on('end', function() {
        emitted = true;
      });

      inspector.run();
      expect(emitted).to.be(true);
    });

    it('emits the "match" event when a match is found', function() {
      var inspector = new Inspector([fixtures.intersection], {
        threshold: 10
      });

      inspector.on('match', listener);
      inspector.run();
      expect(found).to.have.length(1);
    });
  });

  it('can find an exact match between instances', function() {
    var inspector = new Inspector([fixtures.intersection], {
      threshold: 15
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 1, column: 0});
    expect(match.instances[0].end).to.eql({line: 5, column: 1});
    expect(match.instances[1].start).to.eql({line: 7, column: 0});
    expect(match.instances[1].end).to.eql({line: 11, column: 1});
  });

  it('can find the largest match between two instances', function() {
    var inspector = new Inspector([fixtures.redundantIntersection], {
      threshold: 11
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 1, column: 0});
    expect(match.instances[0].end).to.eql({line: 9, column: 1});
    expect(match.instances[1].start).to.eql({line: 11, column: 0});
    expect(match.instances[1].end).to.eql({line: 19, column: 1});
  });

  it('supports ES6', function() {
    var inspector = new Inspector([fixtures.es6ClassExport], {
      threshold: 20
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 2, column: 2});
    expect(match.instances[0].end).to.eql({line: 6, column: 3});
    expect(match.instances[1].start).to.eql({line: 8, column: 2});
    expect(match.instances[1].end).to.eql({line: 12, column: 3});
  });

  it('supports JSX', function() {
    var inspector = new Inspector([fixtures.jsxTodo], {
      threshold: 20
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 3, column: 0});
    expect(match.instances[0].end).to.eql({line: 9, column: 1});
    expect(match.instances[1].start).to.eql({line: 11, column: 0});
    expect(match.instances[1].end).to.eql({line: 17, column: 1});
  });

  it('supports Flow', function() {
    var inspector = new Inspector([fixtures.flowIntersection], {
      threshold: 20
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 1, column: 0});
    expect(match.instances[0].end).to.eql({line: 5, column: 1});
    expect(match.instances[1].start).to.eql({line: 7, column: 0});
    expect(match.instances[1].end).to.eql({line: 11, column: 1});
  });

  it('includes the lines with the match', function() {
    var inspector = new Inspector([fixtures.intersection], {
      threshold: 11,
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].lines).to.be(
      'function intersectionA(array1, array2) {\n' +
      '  array1.filter(function(n) {\n' +
      '    return array2.indexOf(n) != -1;\n' +
      '  });\n' +
      '}'
    );
    expect(match.instances[1].lines).to.be(
      'function intersectionB(arrayA, arrayB) {\n' +
      '  arrayA.filter(function(n) {\n' +
      '    return arrayB.indexOf(n) != -1;\n' +
      '  });\n' +
      '}'
    );
  });

  it('ignores matches with less than the supplied minimum', function() {
    var inspector = new Inspector([fixtures.matches], {
      threshold: 2,
      matches: 3
    });

    inspector.on('match', listener);
    inspector.run();
    expect(found).to.have.length(1);
    expect(found[0].instances).to.have.length(3);
  });

  it('ignores CommonJS require statements', function() {
    var inspector = new Inspector([fixtures.commonjs], {
      threshold: 3
    });

    inspector.on('match', listener);
    inspector.run();
    expect(found).to.have.length(0);
  });

  it('ignores AMD define expressions', function() {
    var inspector = new Inspector([fixtures.amd], {
      threshold: 5
    });

    inspector.on('match', listener);
    inspector.run();
    expect(found).to.have.length(0);
  });
});
<commit_msg>Fix build<commit_after>var expect       = require('expect.js');
var EventEmitter = require('events').EventEmitter;
var Inspector    = require('../lib/inspector.js');
var fixtures     = require('./fixtures');

describe('Inspector', function() {
  // Used to test emitted events
  var found;
  var listener = function(match) {
    found.push(match);
  };

  beforeEach(function() {
    found = [];
  });

  describe('constructor', function() {
    it('inherits from EventEmitter', function() {
      expect(new Inspector()).to.be.an(EventEmitter);
    });

    it('accepts an array of file paths', function() {
      var filePaths = ['path1.js', 'path2.js'];
      var inspector = new Inspector(filePaths);
      expect(inspector._filePaths).to.be(filePaths);
    });

    it('assigns a default threshold of 30', function() {
      var inspector = new Inspector([]);
      expect(inspector._threshold).to.be(30);
    });

    it('accepts an options object', function() {
      var opts = {threshold: 12};
      var inspector = new Inspector([], opts);
      expect(inspector._threshold).to.be(opts.threshold);
    });
  });

  describe('run', function() {
    it('emits a start event', function() {
      var emitted;
      var inspector = new Inspector([fixtures.intersection]);
      inspector.on('start', function() {
        emitted = true;
      });

      inspector.run();
      expect(emitted).to.be(true);
    });

    it('emits an end event', function() {
      var emitted;
      var inspector = new Inspector([fixtures.intersection]);
      inspector.on('end', function() {
        emitted = true;
      });

      inspector.run();
      expect(emitted).to.be(true);
    });

    it('emits the "match" event when a match is found', function() {
      var inspector = new Inspector([fixtures.intersection], {
        threshold: 10
      });

      inspector.on('match', listener);
      inspector.run();
      expect(found).to.have.length(1);
    });
  });

  it('can find an exact match between instances', function() {
    var inspector = new Inspector([fixtures.intersection], {
      threshold: 15
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 1, column: 0});
    expect(match.instances[0].end).to.eql({line: 5, column: 1});
    expect(match.instances[1].start).to.eql({line: 7, column: 0});
    expect(match.instances[1].end).to.eql({line: 11, column: 1});
  });

  it('can find the largest match between two instances', function() {
    var inspector = new Inspector([fixtures.redundantIntersection], {
      threshold: 11
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 1, column: 0});
    expect(match.instances[0].end).to.eql({line: 9, column: 1});
    expect(match.instances[1].start).to.eql({line: 11, column: 0});
    expect(match.instances[1].end).to.eql({line: 19, column: 1});
  });

  it('supports ES6', function() {
    var inspector = new Inspector([fixtures.es6ClassExport], {
      threshold: 20
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 2, column: 2});
    expect(match.instances[0].end).to.eql({line: 6, column: 3});
    expect(match.instances[1].start).to.eql({line: 8, column: 2});
    expect(match.instances[1].end).to.eql({line: 12, column: 3});
  });

  it('supports JSX', function() {
    var inspector = new Inspector([fixtures.jsxTodo], {
      threshold: 20
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 3, column: 0});
    expect(match.instances[0].end).to.eql({line: 9, column: 1});
    expect(match.instances[1].start).to.eql({line: 11, column: 0});
    expect(match.instances[1].end).to.eql({line: 17, column: 1});
  });

  it('supports Flow', function() {
    var inspector = new Inspector([fixtures.flowIntersection], {
      threshold: 20
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].start).to.eql({line: 1, column: 0});
    expect(match.instances[0].end).to.eql({line: 5, column: 1});
    expect(match.instances[1].start).to.eql({line: 7, column: 0});
    expect(match.instances[1].end).to.eql({line: 11, column: 1});
  });

  it('includes the lines with the match', function() {
    var inspector = new Inspector([fixtures.intersection], {
      threshold: 11,
    });

    inspector.on('match', listener);
    inspector.run();

    var match = found[0];
    expect(found).to.have.length(1);
    expect(match.instances).to.have.length(2);
    expect(match.instances[0].lines).to.be(
      'function intersectionA(array1, array2) {\n' +
      '  array1.filter(function(n) {\n' +
      '    return array2.indexOf(n) != -1;\n' +
      '  });\n' +
      '}'
    );
    expect(match.instances[1].lines).to.be(
      'function intersectionB(arrayA, arrayB) {\n' +
      '  arrayA.filter(function(n) {\n' +
      '    return arrayB.indexOf(n) != -1;\n' +
      '  });\n' +
      '}'
    );
  });

  it('ignores matches with less than the supplied minimum', function() {
    var inspector = new Inspector([fixtures.matches], {
      threshold: 2,
      minInstances: 3
    });

    inspector.on('match', listener);
    inspector.run();
    expect(found).to.have.length(1);
    expect(found[0].instances).to.have.length(3);
  });

  it('ignores CommonJS require statements', function() {
    var inspector = new Inspector([fixtures.commonjs], {
      threshold: 3
    });

    inspector.on('match', listener);
    inspector.run();
    expect(found).to.have.length(0);
  });

  it('ignores AMD define expressions', function() {
    var inspector = new Inspector([fixtures.amd], {
      threshold: 5
    });

    inspector.on('match', listener);
    inspector.run();
    expect(found).to.have.length(0);
  });
});
<|endoftext|>


<commit_before>/* eslint-disable import/prefer-default-export */
/* eslint-disable react/forbid-prop-types */
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';

import { UIDatabase } from '../database';
import Settings from '../settings/MobileAppSettings';

import { MODAL_KEYS, getAllPrograms } from '../utilities';
import { usePageReducer, useSyncListener, useNavigationFocus } from '../hooks';
import { getItemLayout, recordKeyExtractor } from './dataTableUtilities';

import { PageButton, DataTablePageView, SearchBar } from '../widgets';
import { BottomConfirmModal, DataTablePageModal } from '../widgets/modals';
import { DataTable, DataTableHeaderRow, DataTableRow } from '../widgets/DataTable';

import { buttonStrings, modalStrings } from '../localization';
import globalStyles, { SUSSOL_ORANGE, newPageStyles } from '../globalStyles';

import {
  gotoStocktakeManagePage,
  createStocktake,
  gotoStocktakeEditPage,
} from '../navigation/actions';

const stateInitialiser = () => {
  const backingData = UIDatabase.objects('Stocktake');
  return {
    backingData,
    data: backingData.sorted('createdDate', false).slice(),
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['name'],
    sortBy: 'createdDate',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    usingPrograms: getAllPrograms(Settings, UIDatabase).length > 0,
  };
};

export const StocktakesPage = ({ routeName, currentUser, dispatch: reduxDispatch, navigation }) => {
  const [state, dispatch, instantDebouncedDispatch] = usePageReducer(
    routeName,
    {},
    stateInitialiser
  );

  const {
    data,
    dataState,
    sortBy,
    isAscending,
    searchTerm,
    modalKey,
    hasSelection,
    usingPrograms,
    keyExtractor,
    columns,
    PageActions,
  } = state;

  const callback = useCallback(() => dispatch(PageActions.refreshData()), []);
  // Listen to sync changing stocktake data - refresh if there are any.
  useSyncListener(callback, ['Stocktake']);
  // Listen to navigation focusing this page - fresh if so.
  useNavigationFocus(callback, navigation);

  const onRowPress = useCallback(stocktake => reduxDispatch(gotoStocktakeEditPage(stocktake)), []);
  const onFilterData = value => dispatch(PageActions.filterData(value));
  const onCancelDelete = () => dispatch(PageActions.deselectAll());
  const onConfirmDelete = () => dispatch(PageActions.deleteStocktakes());
  const onCloseModal = () => dispatch(PageActions.closeModal());

  const onNewStocktake = () => {
    if (usingPrograms) return dispatch(PageActions.openModal(MODAL_KEYS.PROGRAM_STOCKTAKE));
    return reduxDispatch(gotoStocktakeManagePage({ stocktakeName: '' }));
  };

  const getAction = (colKey, propName) => {
    switch (colKey) {
      case 'remove':
        if (propName === 'onCheckAction') return PageActions.selectRow;
        return PageActions.deselectRow;
      default:
        return null;
    }
  };

  const getModalOnSelect = () => {
    switch (modalKey) {
      case MODAL_KEYS.PROGRAM_STOCKTAKE:
        return ({ stocktakeName, program }) => {
          reduxDispatch(createStocktake({ program, stocktakeName, currentUser }));
          onCloseModal();
        };
      default:
        return null;
    }
  };

  const renderRow = useCallback(
    listItem => {
      const { item, index } = listItem;
      const rowKey = keyExtractor(item);
      return (
        <DataTableRow
          rowData={data[index]}
          rowState={dataState.get(rowKey)}
          rowKey={rowKey}
          columns={columns}
          dispatch={dispatch}
          getAction={getAction}
          onPress={onRowPress}
        />
      );
    },
    [data, dataState]
  );

  const renderHeader = useCallback(
    () => (
      <DataTableHeaderRow
        columns={columns}
        dispatch={instantDebouncedDispatch}
        sortAction={PageActions.sortData}
        isAscending={isAscending}
        sortBy={sortBy}
      />
    ),
    [sortBy, isAscending]
  );

  const PageButtons = useCallback(() => {
    const { verticalContainer, topButton } = globalStyles;
    return (
      <View style={verticalContainer}>
        <PageButton style={topButton} text={buttonStrings.new_stocktake} onPress={onNewStocktake} />
      </View>
    );
  }, []);

  const {
    newPageTopSectionContainer,
    newPageTopLeftSectionContainer,
    newPageTopRightSectionContainer,
    searchBar,
  } = newPageStyles;
  return (
    <DataTablePageView>
      <View style={newPageTopSectionContainer}>
        <View style={newPageTopLeftSectionContainer}>
          <SearchBar
            onChangeText={onFilterData}
            style={searchBar}
            color={SUSSOL_ORANGE}
            placeholder=""
            value={searchTerm}
          />
        </View>
        <View style={newPageTopRightSectionContainer}>
          <PageButtons />
        </View>
      </View>
      <DataTable
        data={data}
        extraData={dataState}
        renderRow={renderRow}
        renderHeader={renderHeader}
        keyExtractor={keyExtractor}
        getItemLayout={getItemLayout}
      />
      <BottomConfirmModal
        isOpen={hasSelection}
        questionText={modalStrings.remove_these_items}
        onCancel={onCancelDelete}
        onConfirm={onConfirmDelete}
        confirmText={modalStrings.remove}
      />
      <DataTablePageModal
        fullScreen={false}
        isOpen={!!modalKey}
        modalKey={modalKey}
        onClose={onCloseModal}
        onSelect={getModalOnSelect()}
        dispatch={dispatch}
      />
    </DataTablePageView>
  );
};

StocktakesPage.propTypes = {
  routeName: PropTypes.string.isRequired,
  dispatch: PropTypes.func.isRequired,
  currentUser: PropTypes.object.isRequired,
  navigation: PropTypes.object.isRequired,
};
<commit_msg>Add corrected initial sorting and propType error fix<commit_after>/* eslint-disable import/prefer-default-export */
/* eslint-disable react/forbid-prop-types */
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';

import { UIDatabase } from '../database';
import Settings from '../settings/MobileAppSettings';

import { MODAL_KEYS, getAllPrograms } from '../utilities';
import { usePageReducer, useSyncListener, useNavigationFocus } from '../hooks';
import { getItemLayout, recordKeyExtractor } from './dataTableUtilities';

import { PageButton, DataTablePageView, SearchBar } from '../widgets';
import { BottomConfirmModal, DataTablePageModal } from '../widgets/modals';
import { DataTable, DataTableHeaderRow, DataTableRow } from '../widgets/DataTable';

import { buttonStrings, modalStrings } from '../localization';
import globalStyles, { SUSSOL_ORANGE, newPageStyles } from '../globalStyles';

import {
  gotoStocktakeManagePage,
  createStocktake,
  gotoStocktakeEditPage,
} from '../navigation/actions';

const stateInitialiser = () => {
  const backingData = UIDatabase.objects('Stocktake');
  return {
    backingData,
    data: backingData.sorted('createdDate', true).slice(),
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['name'],
    sortBy: 'createdDate',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    usingPrograms: getAllPrograms(Settings, UIDatabase).length > 0,
  };
};

export const StocktakesPage = ({ routeName, currentUser, dispatch: reduxDispatch, navigation }) => {
  const [state, dispatch, instantDebouncedDispatch] = usePageReducer(
    routeName,
    {},
    stateInitialiser
  );

  const {
    data,
    dataState,
    sortBy,
    isAscending,
    searchTerm,
    modalKey,
    hasSelection,
    usingPrograms,
    keyExtractor,
    columns,
    PageActions,
  } = state;

  const callback = useCallback(() => dispatch(PageActions.refreshData()), []);
  // Listen to sync changing stocktake data - refresh if there are any.
  useSyncListener(callback, ['Stocktake']);
  // Listen to navigation focusing this page - fresh if so.
  useNavigationFocus(callback, navigation);

  const onRowPress = useCallback(stocktake => reduxDispatch(gotoStocktakeEditPage(stocktake)), []);
  const onFilterData = value => dispatch(PageActions.filterData(value));
  const onCancelDelete = () => dispatch(PageActions.deselectAll());
  const onConfirmDelete = () => dispatch(PageActions.deleteStocktakes());
  const onCloseModal = () => dispatch(PageActions.closeModal());

  const onNewStocktake = () => {
    if (usingPrograms) return dispatch(PageActions.openModal(MODAL_KEYS.PROGRAM_STOCKTAKE));
    return reduxDispatch(gotoStocktakeManagePage({ stocktakeName: '' }));
  };

  const getAction = (colKey, propName) => {
    switch (colKey) {
      case 'remove':
        if (propName === 'onCheckAction') return PageActions.selectRow;
        return PageActions.deselectRow;
      default:
        return null;
    }
  };

  const getModalOnSelect = () => {
    switch (modalKey) {
      case MODAL_KEYS.PROGRAM_STOCKTAKE:
        return ({ stocktakeName, program }) => {
          reduxDispatch(createStocktake({ program, stocktakeName, currentUser }));
          onCloseModal();
        };
      default:
        return null;
    }
  };

  const renderRow = useCallback(
    listItem => {
      const { item, index } = listItem;
      const rowKey = keyExtractor(item);
      return (
        <DataTableRow
          rowData={data[index]}
          rowState={dataState.get(rowKey)}
          rowKey={rowKey}
          columns={columns}
          dispatch={dispatch}
          getAction={getAction}
          onPress={onRowPress}
          rowIndex={index}
        />
      );
    },
    [data, dataState]
  );

  const renderHeader = useCallback(
    () => (
      <DataTableHeaderRow
        columns={columns}
        dispatch={instantDebouncedDispatch}
        sortAction={PageActions.sortData}
        isAscending={isAscending}
        sortBy={sortBy}
      />
    ),
    [sortBy, isAscending]
  );

  const PageButtons = useCallback(() => {
    const { verticalContainer, topButton } = globalStyles;
    return (
      <View style={verticalContainer}>
        <PageButton style={topButton} text={buttonStrings.new_stocktake} onPress={onNewStocktake} />
      </View>
    );
  }, []);

  const {
    newPageTopSectionContainer,
    newPageTopLeftSectionContainer,
    newPageTopRightSectionContainer,
    searchBar,
  } = newPageStyles;
  return (
    <DataTablePageView>
      <View style={newPageTopSectionContainer}>
        <View style={newPageTopLeftSectionContainer}>
          <SearchBar
            onChangeText={onFilterData}
            style={searchBar}
            color={SUSSOL_ORANGE}
            placeholder=""
            value={searchTerm}
          />
        </View>
        <View style={newPageTopRightSectionContainer}>
          <PageButtons />
        </View>
      </View>
      <DataTable
        data={data}
        extraData={dataState}
        renderRow={renderRow}
        renderHeader={renderHeader}
        keyExtractor={keyExtractor}
        getItemLayout={getItemLayout}
      />
      <BottomConfirmModal
        isOpen={hasSelection}
        questionText={modalStrings.remove_these_items}
        onCancel={onCancelDelete}
        onConfirm={onConfirmDelete}
        confirmText={modalStrings.remove}
      />
      <DataTablePageModal
        fullScreen={false}
        isOpen={!!modalKey}
        modalKey={modalKey}
        onClose={onCloseModal}
        onSelect={getModalOnSelect()}
        dispatch={dispatch}
      />
    </DataTablePageView>
  );
};

StocktakesPage.propTypes = {
  routeName: PropTypes.string.isRequired,
  dispatch: PropTypes.func.isRequired,
  currentUser: PropTypes.object.isRequired,
  navigation: PropTypes.object.isRequired,
};
<|endoftext|>


<commit_before>define([
    'require',
    '../lib/dist/underscore',
    '../../lib/chosen.jquery',
    '../logging'
], function(require) {
    var log = require('../logging').getLogger('breadcrumbs');

    var init = function($el, opts) {
        // wrap elements in a UL in case none exists
        if (!$el.is(':has(ul)')) {
            $el.children().wrapAll('

').wrap('

');
        }
        var $ul = $el.find('ul');

        // put content into a container that can be shifted around
        var $shift = $('shift')
                .prependTo($el).hide();
    };

    var pattern = {
        markup_trigger: 'nav.breadcrumbs',
        init: init
    };
    return pattern;
});<commit_msg>adjust breadcrumb markup<commit_after>define([
    'require',
    '../lib/dist/underscore',
    '../../lib/chosen.jquery',
    '../logging'
], function(require) {
    var log = require('../logging').getLogger('breadcrumbs');

    var init = function($el, opts) {
        // wrap elements in a DIV
        $el.children().wrapAll('

');

        // put content into a container that can be shifted around
        var $shift = $('shift')
                .prependTo($el).hide();
    };

    var pattern = {
        markup_trigger: 'nav.breadcrumbs',
        init: init
    };
    return pattern;
});<|endoftext|>


<commit_before>/**
 * @fileoverview Run the bootstrap service
 */

var port = 3020,
    system = require('system'),
    page = require('webpage').create(),
    serverObj = require('./server').create(port),
    util = require('./util'),
    module = system.args[1],
    config = system.args[2];

if (!module) {
    console.error('missing module');
    serverObj.close();
    phantom.exit(1);
}

if (!config) {
    console.error('missing config');
    serverObj.close();
    phantom.exit(1);
}

config = decodeURIComponent(config);
var url = 'http://localhost:' + port + '/' + module + '.html?config=' + config;
console.log('<!-- html generated by Livefyre -->');
page.open(url, function(status) {
    if (status !== 'success') {
        console.error('Page could not be opened');
        serverObj.close();
        phantom.exit(1);
    }

    // TODO(rrp): Generalize this bit
    // Wait for fyre-comment-stream el? (need to ensure 100% loaded somehow)
    util.waitFor(function() {
        return page.evaluate(function() {
            return document.getElementsByClassName('fyre-comment-stream').length > 0;
        });
    }, function() {
        var html = page.evaluate(function() {
            return document.getElementById('bs').innerHTML;
        });
        console.log(html);
        serverObj.close();
        phantom.exit();
    }, 30000);
});
<commit_msg>Put eval in setTimeout as an attempt to ensure that the page is really rendered<commit_after>/**
 * @fileoverview Run the bootstrap service
 */

var port = 3020,
    system = require('system'),
    page = require('webpage').create(),
    serverObj = require('./server').create(port),
    util = require('./util'),
    module = system.args[1],
    config = system.args[2];

if (!module) {
    console.error('missing module');
    serverObj.close();
    phantom.exit(1);
}

if (!config) {
    console.error('missing config');
    serverObj.close();
    phantom.exit(1);
}

config = decodeURIComponent(config);
var url = 'http://localhost:' + port + '/' + module + '.html?config=' + config;
console.log('<!-- html generated by Livefyre -->');
page.open(url, function(status) {
    if (status !== 'success') {
        console.error('Page could not be opened');
        serverObj.close();
        phantom.exit(1);
    }

    // TODO(rrp): Generalize this bit
    // Wait for fyre-comment-stream el? (need to ensure 100% loaded somehow)
    util.waitFor(function() {
        return page.evaluate(function() {
            return document.getElementsByClassName('fyre-comment-stream').length > 0;
        });
    }, function() {
        setTimeout(function() {
            var html = page.evaluate(function() {
                return document.getElementById('bs').innerHTML;
            });
            console.log(html);
            serverObj.close();
            phantom.exit();
        }, 500);
    }, 30000);
});
<|endoftext|>


<commit_before>(function() {
  function Lights(name, deps)
  {
    console.log('Lights plugin loaded');

    var self            = this;

    self.setting        = 0;

    //  Settings:       = [ 0 .. 5 ]
    self.levelMap        = [ 0, 48, 64, 96, 160, 255 ];
    self.maxLevel        = self.levelMap.length - 1;

    // Cockpit
    deps.cockpit.on('plugin.lights.toggle', function()
    {
        toggleLights();
    });

    deps.cockpit.on('plugin.lights.adjust', function( value )
    {
        adjustLights( value );
    });

    deps.cockpit.on('plugin.lights.set', function( value )
    {
        setLights( value );
    });

    deps.cockpit.on('plugin.lights.setOnOff', function( setOn )
    {
        if( setOn )
        {
            // Max light power
            setLights( self.maxLevel );
        }
        else
        {
            // Min light power
            setLights( 0 );
        }
    });

    // Arduino
    deps.globalEventLoop.on( 'mcu.status', function (data)
    {
        if ('LIGT' in data)
        {
            // Value of 0-255 representing percent
            var level = parseInt( data.LIGT );

            // Search for the level in the level map
            var setting = self.levelMap.indexOf( level );

            if( setting != -1 )
            {
                // The new setting value is the array index of the level in the level map, if it exists
                self.setting = setting;

                console.log( "A: " + self.setting );
            }
            else
            {
                // Find the closest level in our map
                var closest = self.levelMap.reduce( function (prev, curr)
                {
                    return (Math.abs(curr - level) < Math.abs(prev - level) ? curr : prev);
                });

                // Set the new setting value based on the index of the closest level
                self.setting = self.levelMap.indexOf( closest );

                console.log( "B: " + self.setting );
            }

            deps.cockpit.emit( 'plugin.lights.state', { level: self.setting } );
        }
    });

     var adjustLights = function adjustLights( value )
    {
        // Modify current setting
        console.log( "C: " + ( self.setting + value ) );
        console.log( "D: " + value );

        setLights( self.setting + value );
    };

    var toggleLights = function toggleLights()
    {
        if( self.setting > 0 )
        {
            // Set to min power
            setLights( 0 );
        }
        else
        {
            // Set to max power
            setLights( self.maxLevel );
        }
    };

    var setLights = function setLights( value )
    {
        console.log( "E: " + value );

        // Range limit the new setting from 0 to the max number of defined levels
        if( value < 0 )
        {
            value = 0;
        }
        else if( value >= self.maxLevel )
        {
            value = self.maxLevel;
        }

        // Make sure the new setting is an integer
        self.setting = Math.round( value );

        var command = 'ligt(' + self.levelMap[ self.setting ] + ')';

        console.log( "F: " + self.setting );

        deps.globalEventLoop.emit( 'mcu.SendCommand', command );
    };
  }

  module.exports = function (name, deps)
  {
    return new Lights(name,deps);
  };

})();
<commit_msg>Modified internal led light map<commit_after>(function() {
  function Lights(name, deps)
  {
    console.log('Lights plugin loaded');

    var self            = this;

    self.setting        = 0;

    //  Settings:       = [ 0 .. 5 ]
    self.levelMap        = [ 0, 80, 100, 130, 190, 255 ];
    self.maxLevel        = self.levelMap.length - 1;

    // Cockpit
    deps.cockpit.on('plugin.lights.toggle', function()
    {
        toggleLights();
    });

    deps.cockpit.on('plugin.lights.adjust', function( value )
    {
        adjustLights( value );
    });

    deps.cockpit.on('plugin.lights.set', function( value )
    {
        setLights( value );
    });

    deps.cockpit.on('plugin.lights.setOnOff', function( setOn )
    {
        if( setOn )
        {
            // Max light power
            setLights( self.maxLevel );
        }
        else
        {
            // Min light power
            setLights( 0 );
        }
    });

    // Arduino
    deps.globalEventLoop.on( 'mcu.status', function (data)
    {
        if ('LIGT' in data)
        {
            // Value of 0-255 representing percent
            var level = parseInt( data.LIGT );

            // Search for the level in the level map
            var setting = self.levelMap.indexOf( level );

            if( setting != -1 )
            {
                // The new setting value is the array index of the level in the level map, if it exists
                self.setting = setting;
            }
            else
            {
                // Find the closest level in our map
                var closest = self.levelMap.reduce( function (prev, curr)
                {
                    return (Math.abs(curr - level) < Math.abs(prev - level) ? curr : prev);
                });

                // Set the new setting value based on the index of the closest level
                self.setting = self.levelMap.indexOf( closest );
            }

            deps.cockpit.emit( 'plugin.lights.state', { level: self.setting } );
        }
    });

     var adjustLights = function adjustLights( value )
    {
        // Modify current setting
        setLights( self.setting + value );
    };

    var toggleLights = function toggleLights()
    {
        if( self.setting > 0 )
        {
            // Set to min power
            setLights( 0 );
        }
        else
        {
            // Set to max power
            setLights( self.maxLevel );
        }
    };

    var setLights = function setLights( value )
    {
        // Range limit the new setting from 0 to the max number of defined levels
        if( value < 0 )
        {
            value = 0;
        }
        else if( value >= self.maxLevel )
        {
            value = self.maxLevel;
        }

        // Make sure the new setting is an integer
        self.setting = Math.round( value );

        var command = 'ligt(' + self.levelMap[ self.setting ] + ')';

        deps.globalEventLoop.emit( 'mcu.SendCommand', command );
    };
  }

  module.exports = function (name, deps)
  {
    return new Lights(name,deps);
  };

})();
<|endoftext|>