<commit_before>//Application Definition//

angular.module('fedeApp')

//DynamicDataCtrl Data Fetch and Display Controller

.controller('dynamicDataCtrl', function($scope, $http) {

	$scope.lastDisplayTarget = '';

	$scope.lastListTarget = '';

	$scope.reverse = 'none';

	$scope.selectedOrder = '';

	//Load Data

	$scope.dataLoader = function(arg)	{

		$http.get("./dataList.php?dataSet="+arg).then(function(response) {

			$scope.dataList = response.data.records;

		});

	}

	//Order Data

	$scope.orderController = function($event, arg)	{

		$scope.reverse = ($scope.selectedOrder === arg) ? !$scope.reverse : false;

		$scope.selectedOrder = arg;

	}

	//CSS Controls

	$scope.styleSwap = function($event, switchTarget)	{

		switch(switchTarget)	{

			case 'dataDisplay' :

				if($scope.reverse == false)	{

					$event.currentTarget.querySelector('.buttonBox')

					.className = "dropdown buttonBox";

				}

				else if($scope.reverse == true)	{

					$event.currentTarget.querySelector('.buttonBox')

					.className = "dropup buttonBox";

				}

				$event.currentTarget.querySelector('.caretBox')

				.className = "caret caretBox";

				if($scope.lastDisplayTarget != '' && $scope.lastDisplayTarget

				!= $event.currentTarget)	{

					$scope.lastDisplayTarget.querySelector('.buttonBox')

					.className = "buttonBox";

					$scope.lastDisplayTarget.querySelector('.caretBox')

					.className = "caretBox";

				}

				$scope.lastDisplayTarget = $event.currentTarget;

				break;

			case 'dataListItem' :

				$event.currentTarget.className = "dataListItem strong";

				if($scope.lastListTarget != '' && $scope.lastListTarget

				!= $event.currentTarget)	{

					$scope.lastListTarget.className = "dataListItem";

				}

				$scope.lastListTarget = $event.currentTarget;

				break;

		}

	}

})<commit_msg>not needed<commit_after><|endoftext|>


<commit_before>/**
 * Created with JetBrains PhpStorm.
 * User: fifti
 * Date: 15.08.16
 * Time: 13:59
 * To change this template use File | Settings | File Templates.
 */
function EntityList() {

}

EntityList.prototype.setReadOnly = function(isReadOnly) {
  if (isReadOnly) {
    $$('ADD_ENTITY_LABEL').hide();
  } else {
    $$('ADD_ENTITY_LABEL').show();
  }
};

EntityList.prototype.onCreate = function(data) {
  var parentId = Identity.parentId(Identity.idFromData(data));
  var entity = Identity.entityFromData(data);
  if (this.getRootId() === parentId) {
    $$('entity_list').add(entity, 1);
    $$('entity_list').select(entity.id);
  }
};

EntityList.prototype.listen = function() {
  Mydataspace.on('entities.delete.res', function(data) {
    var entityId = Identity.idFromData(data);

    if ($$('entity_list').getFirstId() === entityId) { // Parent item "."
      return;
    }

    if ($$('entity_list').getItem(entityId) == null) {
      return;
    }

    if (entityId === this.getCurrentId()) { // Select other item if selected item is deleted.
      let nextId = $$('entity_list').getPrevId(entityId) || $$('entity_list').getNextId(entityId);
      $$('entity_list').select(nextId);
    }

    $$('entity_list').remove(entityId);
  }.bind(this));

  Mydataspace.on('entities.create.res', this.onCreate.bind(this));
};

EntityList.prototype.setRootId = function(id) {
  if (this.rootId === id) {
    return;
  }
  this.rootId = id;

  // var subscription = Identity.dataFromId(id);
  // var childrenSubscription = Identity.dataFromId(id);
  // childrenSubscription.path += '/*';
  // Mydataspace.emit('entities.subscribe', subscription);
  // Mydataspace.emit('entities.subscribe', childrenSubscription);

  this.refreshData();
};

EntityList.prototype.getRootId = function() {
  return this.rootId;
};

EntityList.prototype.setCurrentId = function(id) {
   this.currentId = id;
};

EntityList.prototype.getCurrentId = function() {
  return this.currentId;
};

/**
 * Reload data (from server) of entity list.
 * Uses entityList_fill internally.
 */
EntityList.prototype.refreshData = function() {
  var identity = Identity.dataFromId(this.getRootId());
  var search = $$('entity_list__search').getValue();
  if (MDSCommon.isPresent(search)) {
    identity['filterByName'] = search;
  }
  $$('entity_list').disable();
  Mydataspace.request('entities.getChildren', identity, function(data) {
    var showMoreChildId =
      Identity.childId(this.getRootId(), UIHelper.ENTITY_LIST_SHOW_MORE_ID);
    var entityId = Identity.idFromData(data);
    var children = data.children.filter(x => x.root !== 'root' || x.path !== '').map(Identity.entityFromData);
    if (this.getRootId() === entityId) {
      if (children.length === UIHelper.NUMBER_OF_ENTITIES_LOADED_AT_TIME) {
        children[children.length - 1] = {
          id: Identity.childId(entityId, UIHelper.ENTITY_LIST_SHOW_MORE_ID),
          value: STRINGS.SHOW_MORE
        }
      }
      this.fill(entityId, children, data);
      $$('entity_list').addCss(showMoreChildId, 'entity_list__show_more_item');
    }
    this.setReadOnly(!data.mine);
    $$('entity_list').enable();
  }.bind(this), function(err) { UI.error(err); });
};

/**
 * Fills entity list by items from children array.
 *
 * @param parentEntityId Root entity (selected in entity tree).
 *                       Displays as '.' in entity list.
 * @param children Items of entity list.
 */
EntityList.prototype.fill = function(parentEntityId, children, data) {
  $$('entity_list').clearAll();
  for (var i in children) {
    $$('entity_list').add(children[i], -1);
  }
  $$('entity_list').add({ id: parentEntityId,  value: '.', count: data.numberOfChildren }, 0);
  $$('entity_list').select(parentEntityId);
};

/**
 * Creates new entity by data received from the 'New Entity' form.
 * @param formData data received from form by method getValues.
 */
EntityList.prototype.createByFormData = function(formData) {
  var newEntityId = Identity.childId(this.getRootId(), formData.name);
  var data = Identity.dataFromId(newEntityId);
  data.fields = [];
  data.othersCan = formData.othersCan;
  Mydataspace.emit('entities.create', data);
};

EntityList.prototype.addChildren = function(children) {
  var showMoreChildId =
    Identity.childId(this.getRootId(), UIHelper.ENTITY_LIST_SHOW_MORE_ID);

  var startIndex;
  if (children.length === UIHelper.NUMBER_OF_ENTITIES_LOADED_AT_TIME) {
    delete children[children.length - 1];
    startIndex = this.count() + 1;
  } else {
    $$('entity_list').remove(showMoreChildId);
    startIndex = this.count() + 2;
  }

  var offset = 0;
  for (var i in children) {
    $$('entity_list').add(children[i], startIndex + offset);
    offset++;
  }
};

EntityList.prototype.showMore = function() {
  var req = Identity.dataFromId(this.getRootId());
  req.offset = this.count();
  Mydataspace.request('entities.getChildren', req, function(data) {
    var children = data.children.map(Identity.entityFromData);
    this.addChildren(children);
  }.bind(this));
};

/**
 * Calculates number of items of entity list.
 * @returns {number} Number of items in entity list.
 */
EntityList.prototype.count = function() {
  var lastId = $$('entity_list').getLastId();
  var lastIndex = $$('entity_list').getIndexById(lastId);
  if (lastId.endsWith(UIHelper.ENTITY_LIST_SHOW_MORE_ID)) {
    return lastIndex - 1;
  }
  return lastIndex;
};
<commit_msg>fix(list): search items by FTS<commit_after>/**
 * Created with JetBrains PhpStorm.
 * User: fifti
 * Date: 15.08.16
 * Time: 13:59
 * To change this template use File | Settings | File Templates.
 */
function EntityList() {

}

EntityList.prototype.setReadOnly = function(isReadOnly) {
  if (isReadOnly) {
    $$('ADD_ENTITY_LABEL').hide();
  } else {
    $$('ADD_ENTITY_LABEL').show();
  }
};

EntityList.prototype.onCreate = function(data) {
  var parentId = Identity.parentId(Identity.idFromData(data));
  var entity = Identity.entityFromData(data);
  if (this.getRootId() === parentId) {
    $$('entity_list').add(entity, 1);
    $$('entity_list').select(entity.id);
  }
};

EntityList.prototype.listen = function() {
  Mydataspace.on('entities.delete.res', function(data) {
    var entityId = Identity.idFromData(data);

    if ($$('entity_list').getFirstId() === entityId) { // Parent item "."
      return;
    }

    if ($$('entity_list').getItem(entityId) == null) {
      return;
    }

    if (entityId === this.getCurrentId()) { // Select other item if selected item is deleted.
      var nextId = $$('entity_list').getPrevId(entityId) || $$('entity_list').getNextId(entityId);
      $$('entity_list').select(nextId);
    }

    $$('entity_list').remove(entityId);
  }.bind(this));

  Mydataspace.on('entities.create.res', this.onCreate.bind(this));
};

EntityList.prototype.setRootId = function(id) {
  if (this.rootId === id) {
    return;
  }
  this.rootId = id;

  // var subscription = Identity.dataFromId(id);
  // var childrenSubscription = Identity.dataFromId(id);
  // childrenSubscription.path += '/*';
  // Mydataspace.emit('entities.subscribe', subscription);
  // Mydataspace.emit('entities.subscribe', childrenSubscription);

  this.refreshData();
};

EntityList.prototype.getRootId = function() {
  return this.rootId;
};

EntityList.prototype.setCurrentId = function(id) {
   this.currentId = id;
};

EntityList.prototype.getCurrentId = function() {
  return this.currentId;
};

/**
 * Reload data (from server) of entity list.
 * Uses entityList_fill internally.
 */
EntityList.prototype.refreshData = function() {
  var identity = Identity.dataFromId(this.getRootId());
  var search = $$('entity_list__search').getValue();
  if (MDSCommon.isPresent(search)) {
    identity['search'] = search;
  }
  $$('entity_list').disable();
  Mydataspace.request('entities.getChildren', identity, function(data) {
    var showMoreChildId =
      Identity.childId(this.getRootId(), UIHelper.ENTITY_LIST_SHOW_MORE_ID);
    var entityId = Identity.idFromData(data);
    var children = data.children.filter(function(x) { return x.root !== 'root' || x.path !== ''; }).map(Identity.entityFromData);
    if (this.getRootId() === entityId) {
      if (children.length === UIHelper.NUMBER_OF_ENTITIES_LOADED_AT_TIME) {
        children[children.length - 1] = {
          id: Identity.childId(entityId, UIHelper.ENTITY_LIST_SHOW_MORE_ID),
          value: STRINGS.SHOW_MORE
        }
      }
      this.fill(entityId, children, data);
      $$('entity_list').addCss(showMoreChildId, 'entity_list__show_more_item');
    }
    this.setReadOnly(!data.mine);
    $$('entity_list').enable();
  }.bind(this), function(err) { UI.error(err); });
};

/**
 * Fills entity list by items from children array.
 *
 * @param parentEntityId Root entity (selected in entity tree).
 *                       Displays as '.' in entity list.
 * @param children Items of entity list.
 */
EntityList.prototype.fill = function(parentEntityId, children, data) {
  $$('entity_list').clearAll();
  for (var i in children) {
    $$('entity_list').add(children[i], -1);
  }
  $$('entity_list').add({ id: parentEntityId,  value: '.', count: data.numberOfChildren }, 0);
  $$('entity_list').select(parentEntityId);
};

/**
 * Creates new entity by data received from the 'New Entity' form.
 * @param formData data received from form by method getValues.
 */
EntityList.prototype.createByFormData = function(formData) {
  var newEntityId = Identity.childId(this.getRootId(), formData.name);
  var data = Identity.dataFromId(newEntityId);
  data.fields = [];
  data.othersCan = formData.othersCan;
  Mydataspace.emit('entities.create', data);
};

EntityList.prototype.addChildren = function(children) {
  var showMoreChildId =
    Identity.childId(this.getRootId(), UIHelper.ENTITY_LIST_SHOW_MORE_ID);

  var startIndex;
  if (children.length === UIHelper.NUMBER_OF_ENTITIES_LOADED_AT_TIME) {
    delete children[children.length - 1];
    startIndex = this.count() + 1;
  } else {
    $$('entity_list').remove(showMoreChildId);
    startIndex = this.count() + 2;
  }

  var offset = 0;
  for (var i in children) {
    $$('entity_list').add(children[i], startIndex + offset);
    offset++;
  }
};

EntityList.prototype.showMore = function() {
  var req = Identity.dataFromId(this.getRootId());
  req.offset = this.count();
  Mydataspace.request('entities.getChildren', req, function(data) {
    var children = data.children.map(Identity.entityFromData);
    this.addChildren(children);
  }.bind(this));
};

/**
 * Calculates number of items of entity list.
 * @returns {number} Number of items in entity list.
 */
EntityList.prototype.count = function() {
  var lastId = $$('entity_list').getLastId();
  var lastIndex = $$('entity_list').getIndexById(lastId);
  if (lastId.endsWith(UIHelper.ENTITY_LIST_SHOW_MORE_ID)) {
    return lastIndex - 1;
  }
  return lastIndex;
};
<|endoftext|>


<commit_before>/* global Gallery */
(function ($, _, OC, t, Gallery) {
	"use strict";
	/**
	 * Builds and updates the Gallery view
	 *
	 * @constructor
	 */
	var View = function () {
		this.element = $('#gallery');
		this.loadVisibleRows.loading = false;
		this.breadcrumb = new Gallery.Breadcrumb();
	};

	View.prototype = {
		element: null,
		breadcrumb: null,
		requestId: -1,

		/**
		 * Removes all thumbnails from the view
		 */
		clear: function () {
			// We want to keep all the events
			this.element.children().detach();
			Gallery.showLoading();
		},

		/**
		 * Populates the view if there are images or albums to show
		 *
		 * @param {string} albumPath
		 */
		init: function (albumPath) {
			// Only do it when the app is initialised
			if (this.requestId === -1) {
				this._initButtons();
			}
			if ($.isEmptyObject(Gallery.imageMap)) {
				this.clear();
				if (albumPath === '') {
					Gallery.showEmpty();
				} else {
					Gallery.showEmptyFolder();
					this.hideButtons();
					Gallery.currentAlbum = albumPath;
					var availableWidth = $(window).width() - Gallery.buttonsWidth;
					this.breadcrumb.init(albumPath, availableWidth);
					Gallery.config.albumDesign = null;
				}
			} else {
				this.viewAlbum(albumPath);
			}

			this._setBackgroundColour();
		},

		/**
		 * Starts the slideshow
		 *
		 * @param {string} path
		 * @param {string} albumPath
		 */
		startSlideshow: function (path, albumPath) {
			var album = Gallery.albumMap[albumPath];
			var images = album.images;
			var startImage = Gallery.imageMap[path];
			Gallery.slideShow(images, startImage, false);
		},

		/**
		 * Sets up the controls and starts loading the gallery rows
		 *
		 * @param {string|null} albumPath
		 */
		viewAlbum: function (albumPath) {
			albumPath = albumPath || '';
			if (!Gallery.albumMap[albumPath]) {
				return;
			}

			this.clear();

			if (albumPath !== Gallery.currentAlbum) {
				this.loadVisibleRows.loading = false;
				Gallery.currentAlbum = albumPath;
				this._setupButtons(albumPath);
			}

			Gallery.albumMap[albumPath].viewedItems = 0;
			Gallery.albumMap[albumPath].preloadOffset = 0;

			// Each request has a unique ID, so that we can track which request a row belongs to
			this.requestId = Math.random();
			Gallery.albumMap[Gallery.currentAlbum].requestId = this.requestId;

			// Loading rows without blocking the execution of the rest of the script
			setTimeout(function () {
				this.loadVisibleRows.activeIndex = 0;
				this.loadVisibleRows(Gallery.albumMap[Gallery.currentAlbum], Gallery.currentAlbum);
			}.bind(this), 0);
		},

		/**
		 * Manages the sorting interface
		 *
		 * @param {string} sortType name or date
		 * @param {string} sortOrder asc or des
		 */
		sortControlsSetup: function (sortType, sortOrder) {
			var reverseSortType = 'date';
			if (sortType === 'date') {
				reverseSortType = 'name';
			}
			this._setSortButton(sortType, sortOrder, true);
			this._setSortButton(reverseSortType, 'asc', false); // default icon
		},

		/**
		 * Loads and displays gallery rows on screen
		 *
		 * @param {Album} album
		 * @param {string} path
		 *
		 * @returns {boolean|null|*}
		 */
		loadVisibleRows: function (album, path) {
			var view = this;
			// If the row is still loading (state() = 'pending'), let it load
			if (this.loadVisibleRows.loading &&
				this.loadVisibleRows.loading.state() !== 'resolved') {
				return this.loadVisibleRows.loading;
			}

			/**
			 * At this stage, there is no loading taking place (loading = false|null), so we can
			 * look for new rows
			 */

			var scroll = $('#content-wrapper').scrollTop() + $(window).scrollTop();
			// 2 windows worth of rows is the limit from which we need to start loading new rows.
			// As we scroll down, it grows
			var targetHeight = ($(window).height() * 2) + scroll;
			var showRows = function (album) {

				// If we've reached the end of the album, we kill the loader
				if (!(album.viewedItems < album.subAlbums.length + album.images.length)) {
					view.loadVisibleRows.loading = null;
					return;
				}

				// Everything is still in sync, since no deferred calls have been placed yet

				var row = album.getRow($(window).width(), view.requestId);
				var rowDom = row.getDom();
				view.element.append(rowDom);

				return album.fillNextRow(row).then(function () {
					/**
					 * At this stage, the row has a width and contains references to images based
					 * on
					 * information available when making the request, but this information may have
					 * changed while we were receiving thumbnails for the row
					 */
					if (view.requestId === row.requestId) {
						if (Gallery.currentAlbum !== path) {
							view.loadVisibleRows.loading = null;
							return; //throw away the row if the user has navigated away in the
									// meantime
						}
						if (view.element.length === 1) {
							Gallery.showNormal();
						}
						if (album.viewedItems < album.subAlbums.length + album.images.length &&
							view.element.height() < targetHeight) {
							return showRows(album);
						}
						// No more rows to load at the moment
						view.loadVisibleRows.loading = null;
					} else {
						// This is the safest way to do things
						view.viewAlbum(Gallery.currentAlbum);
					}
				}, function () {
					// Something went wrong, so kill the loader
					view.loadVisibleRows.loading = null;
				});
			};
			if (this.element.height() < targetHeight) {
				this.loadVisibleRows.loading = true;
				this.loadVisibleRows.loading = showRows(album);
				return this.loadVisibleRows.loading;
			}
		},

		hideButtons: function () {
			$('#album-info-button').hide();
			$('#share-button').hide();
			$('#sort-name-button').hide();
			$('#sort-date-button').hide();
		},

		/**
		 * Adds all the click handlers to buttons the first time they appear in the interface
		 *
		 * @private
		 */
		_initButtons: function () {
			$('#filelist-button').click(Gallery.switchToFilesView);
			$('#download').click(Gallery.download);
			$('#share-button').click(Gallery.share);
			Gallery.infoBox = new Gallery.InfoBox();
			$('#album-info-button').click(Gallery.showInfo);
			$('#sort-name-button').click(Gallery.sorter);
			$('#sort-date-button').click(Gallery.sorter);
			$('#save #save-button').click(Gallery.showSaveForm);
			$('.save-form').submit(Gallery.saveForm);

			this.requestId = Math.random();
		},

		/**
		 * Sets up all the buttons of the interface and the breadcrumbs
		 *
		 * @param {string} albumPath
		 * @private
		 */
		_setupButtons: function (albumPath) {
			this._shareButtonSetup(albumPath);
			this._infoButtonSetup();

			var availableWidth = $(window).width() - Gallery.buttonsWidth;
			this.breadcrumb.init(albumPath, availableWidth);

			$('#sort-name-button').show();
			$('#sort-date-button').show();
			var currentSort = Gallery.config.albumSorting;
			this.sortControlsSetup(currentSort.type, currentSort.order);
			Gallery.albumMap[Gallery.currentAlbum].images.sort(
				Gallery.utility.sortBy(currentSort.type,
					currentSort.order));
			Gallery.albumMap[Gallery.currentAlbum].subAlbums.sort(Gallery.utility.sortBy('name',
				currentSort.albumOrder));
		},

		/**
		 * Shows or hides the share button depending on if we're in a public gallery or not
		 *
		 * @param {string} albumPath
		 * @private
		 */
		_shareButtonSetup: function (albumPath) {
			var shareButton = $('#share-button');
			if (albumPath === '' || Gallery.token) {
				shareButton.hide();
			} else {
				shareButton.show();
			}
		},

		/**
		 * Shows or hides the info button based on the information we've received from the server
		 *
		 * @private
		 */
		_infoButtonSetup: function () {
			var infoButton = $('#album-info-button');
			infoButton.find('span').hide();
			var infoContentContainer = $('.album-info-container');
			infoContentContainer.slideUp();
			infoContentContainer.css('max-height',
				$(window).height() - Gallery.browserToolbarHeight);
			var albumInfo = Gallery.config.albumInfo;
			if (Gallery.config.albumError) {
				infoButton.hide();
				var text = '' + t('gallery', 'Configuration error') + '
' +
					Gallery.config.albumError.message + '

';
				Gallery.utility.showHtmlNotification(text, 7);
			} else if ($.isEmptyObject(albumInfo)) {
				infoButton.hide();
			} else {
				infoButton.show();
				if (albumInfo.inherit !== 'yes' || albumInfo.level === 0) {
					infoButton.find('span').delay(1000).slideDown();
				}
			}
		},

		/**
		 * Sets the background colour of the photowall
		 *
		 * @private
		 */
		_setBackgroundColour: function () {
			var wrapper = $('#content-wrapper');
			var albumDesign = Gallery.config.albumDesign;
			if (!$.isEmptyObject(albumDesign) && albumDesign.background) {
				wrapper.css('background-color', albumDesign.background);
			} else {
				wrapper.css('background-color', '#fff');
			}
		},

		/**
		 * Picks the image which matches the sort order
		 *
		 * @param {string} sortType name or date
		 * @param {string} sortOrder asc or des
		 * @param {boolean} active determines if we're setting up the active sort button
		 * @private
		 */
		_setSortButton: function (sortType, sortOrder, active) {
			var button = $('#sort-' + sortType + '-button');
			// Removing all the classes which control the image in the button
			button.removeClass('active-button');
			button.find('img').removeClass('front');
			button.find('img').removeClass('back');

			// We need to determine the reverse order in order to send that image to the back
			var reverseSortOrder = 'des';
			if (sortOrder === 'des') {
				reverseSortOrder = 'asc';
			}

			// We assign the proper order to the button images
			button.find('img.' + sortOrder).addClass('front');
			button.find('img.' + reverseSortOrder).addClass('back');

			// The active button needs a hover action for the flip effect
			if (active) {
				button.addClass('active-button');
				if (button.is(":hover")) {
					button.removeClass('hover');
				}
				// We can't use a toggle here
				button.hover(function () {
						$(this).addClass('hover');
					},
					function () {
						$(this).removeClass('hover');
					});
			}
		}
	};

	Gallery.View = View;
})(jQuery, _, OC, t, Gallery);
<commit_msg>Throttle rows (cherry picked from commit 0af1416) (cherry picked from commit 52a89f2)<commit_after>/* global Gallery */
(function ($, _, OC, t, Gallery) {
	"use strict";
	/**
	 * Builds and updates the Gallery view
	 *
	 * @constructor
	 */
	var View = function () {
		this.element = $('#gallery');
		this.loadVisibleRows.loading = false;
		this.breadcrumb = new Gallery.Breadcrumb();
	};

	View.prototype = {
		element: null,
		breadcrumb: null,
		requestId: -1,

		/**
		 * Removes all thumbnails from the view
		 */
		clear: function () {
			// We want to keep all the events
			this.element.children().detach();
			Gallery.showLoading();
		},

		/**
		 * Populates the view if there are images or albums to show
		 *
		 * @param {string} albumPath
		 */
		init: function (albumPath) {
			// Only do it when the app is initialised
			if (this.requestId === -1) {
				this._initButtons();
			}
			if ($.isEmptyObject(Gallery.imageMap)) {
				this.clear();
				if (albumPath === '') {
					Gallery.showEmpty();
				} else {
					Gallery.showEmptyFolder();
					this.hideButtons();
					Gallery.currentAlbum = albumPath;
					var availableWidth = $(window).width() - Gallery.buttonsWidth;
					this.breadcrumb.init(albumPath, availableWidth);
					Gallery.config.albumDesign = null;
				}
			} else {
				this.viewAlbum(albumPath);
			}

			this._setBackgroundColour();
		},

		/**
		 * Starts the slideshow
		 *
		 * @param {string} path
		 * @param {string} albumPath
		 */
		startSlideshow: function (path, albumPath) {
			var album = Gallery.albumMap[albumPath];
			var images = album.images;
			var startImage = Gallery.imageMap[path];
			Gallery.slideShow(images, startImage, false);
		},

		/**
		 * Sets up the controls and starts loading the gallery rows
		 *
		 * @param {string|null} albumPath
		 */
		viewAlbum: function (albumPath) {
			albumPath = albumPath || '';
			if (!Gallery.albumMap[albumPath]) {
				return;
			}

			this.clear();

			if (albumPath !== Gallery.currentAlbum) {
				this.loadVisibleRows.loading = false;
				Gallery.currentAlbum = albumPath;
				this._setupButtons(albumPath);
			}

			Gallery.albumMap[albumPath].viewedItems = 0;
			Gallery.albumMap[albumPath].preloadOffset = 0;

			// Each request has a unique ID, so that we can track which request a row belongs to
			this.requestId = Math.random();
			Gallery.albumMap[Gallery.currentAlbum].requestId = this.requestId;

			// Loading rows without blocking the execution of the rest of the script
			setTimeout(function () {
				this.loadVisibleRows.activeIndex = 0;
				this.loadVisibleRows(Gallery.albumMap[Gallery.currentAlbum], Gallery.currentAlbum);
			}.bind(this), 0);
		},

		/**
		 * Manages the sorting interface
		 *
		 * @param {string} sortType name or date
		 * @param {string} sortOrder asc or des
		 */
		sortControlsSetup: function (sortType, sortOrder) {
			var reverseSortType = 'date';
			if (sortType === 'date') {
				reverseSortType = 'name';
			}
			this._setSortButton(sortType, sortOrder, true);
			this._setSortButton(reverseSortType, 'asc', false); // default icon
		},

		/**
		 * Loads and displays gallery rows on screen
		 *
		 * @param {Album} album
		 * @param {string} path
		 *
		 * @returns {boolean|null|*}
		 */
		loadVisibleRows: function (album, path) {
			var view = this;
			// If the row is still loading (state() = 'pending'), let it load
			if (this.loadVisibleRows.loading &&
				this.loadVisibleRows.loading.state() !== 'resolved') {
				return this.loadVisibleRows.loading;
			}

			/**
			 * At this stage, there is no loading taking place (loading = false|null), so we can
			 * look for new rows
			 */

			var scroll = $('#content-wrapper').scrollTop() + $(window).scrollTop();
			// 2 windows worth of rows is the limit from which we need to start loading new rows.
			// As we scroll down, it grows
			var targetHeight = ($(window).height() * 2) + scroll;
			var showRows = _.throttle(function (album) {

				// If we've reached the end of the album, we kill the loader
				if (!(album.viewedItems < album.subAlbums.length + album.images.length)) {
					view.loadVisibleRows.loading = null;
					return;
				}

				// Everything is still in sync, since no deferred calls have been placed yet

				var row = album.getRow($(window).width(), view.requestId);
				var rowDom = row.getDom();
				view.element.append(rowDom);

				return album.fillNextRow(row).then(function () {
					/**
					 * At this stage, the row has a width and contains references to images based
					 * on
					 * information available when making the request, but this information may have
					 * changed while we were receiving thumbnails for the row
					 */
					if (view.requestId === row.requestId) {
						if (Gallery.currentAlbum !== path) {
							view.loadVisibleRows.loading = null;
							return; //throw away the row if the user has navigated away in the
									// meantime
						}
						if (view.element.length === 1) {
							Gallery.showNormal();
						}
						if (album.viewedItems < album.subAlbums.length + album.images.length &&
							view.element.height() < targetHeight) {
							return showRows(album);
						}
						// No more rows to load at the moment
						view.loadVisibleRows.loading = null;
					} else {
						// This is the safest way to do things
						view.viewAlbum(Gallery.currentAlbum);
					}
				}, function () {
					// Something went wrong, so kill the loader
					view.loadVisibleRows.loading = null;
				});
			}, 100);
			if (this.element.height() < targetHeight) {
				this.loadVisibleRows.loading = true;
				this.loadVisibleRows.loading = showRows(album);
				return this.loadVisibleRows.loading;
			}
		},

		hideButtons: function () {
			$('#album-info-button').hide();
			$('#share-button').hide();
			$('#sort-name-button').hide();
			$('#sort-date-button').hide();
		},

		/**
		 * Adds all the click handlers to buttons the first time they appear in the interface
		 *
		 * @private
		 */
		_initButtons: function () {
			$('#filelist-button').click(Gallery.switchToFilesView);
			$('#download').click(Gallery.download);
			$('#share-button').click(Gallery.share);
			Gallery.infoBox = new Gallery.InfoBox();
			$('#album-info-button').click(Gallery.showInfo);
			$('#sort-name-button').click(Gallery.sorter);
			$('#sort-date-button').click(Gallery.sorter);
			$('#save #save-button').click(Gallery.showSaveForm);
			$('.save-form').submit(Gallery.saveForm);

			this.requestId = Math.random();
		},

		/**
		 * Sets up all the buttons of the interface and the breadcrumbs
		 *
		 * @param {string} albumPath
		 * @private
		 */
		_setupButtons: function (albumPath) {
			this._shareButtonSetup(albumPath);
			this._infoButtonSetup();

			var availableWidth = $(window).width() - Gallery.buttonsWidth;
			this.breadcrumb.init(albumPath, availableWidth);

			$('#sort-name-button').show();
			$('#sort-date-button').show();
			var currentSort = Gallery.config.albumSorting;
			this.sortControlsSetup(currentSort.type, currentSort.order);
			Gallery.albumMap[Gallery.currentAlbum].images.sort(
				Gallery.utility.sortBy(currentSort.type,
					currentSort.order));
			Gallery.albumMap[Gallery.currentAlbum].subAlbums.sort(Gallery.utility.sortBy('name',
				currentSort.albumOrder));
		},

		/**
		 * Shows or hides the share button depending on if we're in a public gallery or not
		 *
		 * @param {string} albumPath
		 * @private
		 */
		_shareButtonSetup: function (albumPath) {
			var shareButton = $('#share-button');
			if (albumPath === '' || Gallery.token) {
				shareButton.hide();
			} else {
				shareButton.show();
			}
		},

		/**
		 * Shows or hides the info button based on the information we've received from the server
		 *
		 * @private
		 */
		_infoButtonSetup: function () {
			var infoButton = $('#album-info-button');
			infoButton.find('span').hide();
			var infoContentContainer = $('.album-info-container');
			infoContentContainer.slideUp();
			infoContentContainer.css('max-height',
				$(window).height() - Gallery.browserToolbarHeight);
			var albumInfo = Gallery.config.albumInfo;
			if (Gallery.config.albumError) {
				infoButton.hide();
				var text = '' + t('gallery', 'Configuration error') + '
' +
					Gallery.config.albumError.message + '

';
				Gallery.utility.showHtmlNotification(text, 7);
			} else if ($.isEmptyObject(albumInfo)) {
				infoButton.hide();
			} else {
				infoButton.show();
				if (albumInfo.inherit !== 'yes' || albumInfo.level === 0) {
					infoButton.find('span').delay(1000).slideDown();
				}
			}
		},

		/**
		 * Sets the background colour of the photowall
		 *
		 * @private
		 */
		_setBackgroundColour: function () {
			var wrapper = $('#content-wrapper');
			var albumDesign = Gallery.config.albumDesign;
			if (!$.isEmptyObject(albumDesign) && albumDesign.background) {
				wrapper.css('background-color', albumDesign.background);
			} else {
				wrapper.css('background-color', '#fff');
			}
		},

		/**
		 * Picks the image which matches the sort order
		 *
		 * @param {string} sortType name or date
		 * @param {string} sortOrder asc or des
		 * @param {boolean} active determines if we're setting up the active sort button
		 * @private
		 */
		_setSortButton: function (sortType, sortOrder, active) {
			var button = $('#sort-' + sortType + '-button');
			// Removing all the classes which control the image in the button
			button.removeClass('active-button');
			button.find('img').removeClass('front');
			button.find('img').removeClass('back');

			// We need to determine the reverse order in order to send that image to the back
			var reverseSortOrder = 'des';
			if (sortOrder === 'des') {
				reverseSortOrder = 'asc';
			}

			// We assign the proper order to the button images
			button.find('img.' + sortOrder).addClass('front');
			button.find('img.' + reverseSortOrder).addClass('back');

			// The active button needs a hover action for the flip effect
			if (active) {
				button.addClass('active-button');
				if (button.is(":hover")) {
					button.removeClass('hover');
				}
				// We can't use a toggle here
				button.hover(function () {
						$(this).addClass('hover');
					},
					function () {
						$(this).removeClass('hover');
					});
			}
		}
	};

	Gallery.View = View;
})(jQuery, _, OC, t, Gallery);
<|endoftext|>


<commit_before>'use strict';

function draw_logic(){
    // Save the current buffer state.
    canvas_buffer.save();

    for(var hexagon in hexagons){
        var vertices = [];
        for(var i = 0; i < 6; i++){
            var angle = math_degrees_to_radians(30 + i * 60);
            vertices.push({
              'type': i === 0
                ? 'moveTo'
                : 'lineTo',
              'x': hexagons[hexagon]['x'] + Math.cos(angle) * 25 + canvas_x,
              'y': hexagons[hexagon]['y'] + Math.sin(angle) * 25 + canvas_y,
            });
        }
        canvas_draw_path(
          vertices,
          {
            'fillStyle': hexagons[hexagon]['color'],
          }
        );
    }

    canvas_buffer.fillText(
      'Turn: ' + turn,
      0,
      25
    );
}

function logic(){
    if(canvas_menu){
        return;
    }
}

function setmode_logic(newgame){
    hexagons = [];
    turn = 0;

    // Main menu mode.
    if(canvas_mode === 0){
        document.body.innerHTML = '

New Game

'
          + '

<input disabled value=ESC>Menu
'
          + '<input id=end-turn-key>End Turn

'
          + '
<input id=hexagons>Hexagons
'
          + '<input id=players>Players
'
          + 'Reset Settings

';
        settings_update();

    // New game mode.
    }else{
        if(newgame){
            settings_save();
        }
    }
}

function toggle_hexagon(x, y){
    var side = x % 46 < 23
      ? 23
      : -23;
    x = Math.ceil((x - 23) / 46) * 46;
    y = Math.ceil((y - 20) / 40) * 40;
    if(y % 80){
        x += side;
    }

    // Modify hexagon if one exists at this x,y.
    for(var hexagon in hexagons){
        if(hexagons[hexagon]['x'] === x
          && hexagons[hexagon]['y'] === y){
            return;
        }
    }

    hexagons.push({
      'color': default_color,
      'x': x,
      'y': y,
    });
}

var default_color = '#fff';
var hexagons = [];
var players = [];
var turn = 0;

window.onkeydown = function(e){
    if(canvas_mode <= 0){
        return;
    }

    var key = e.keyCode || e.which;

    // ESC: return to main menu.
    if(key === 27){
        canvas_menu_toggle();
        return;
    }

    key = String.fromCharCode(key);

    if(key === settings_settings['end-turn-key']){
        if(turn === players.length - 1){
            turn = 0;

        }else{
            turn += 1;
        }

    }else if(key === 'Q'){
        canvas_menu_quit();
    }
};

window.onload = function(){
    settings_init(
      'Hexagons-2D.htm-',
      {
        'end-turn-key': 'H',
        'hexagons': 100,
        'players': 5,
      }
    );
    canvas_init();
};
<commit_msg>made turn listing match player color<commit_after>'use strict';

function draw_logic(){
    // Save the current buffer state.
    canvas_buffer.save();

    for(var hexagon in hexagons){
        var vertices = [];
        for(var i = 0; i < 6; i++){
            var angle = math_degrees_to_radians(30 + i * 60);
            vertices.push({
              'type': i === 0
                ? 'moveTo'
                : 'lineTo',
              'x': hexagons[hexagon]['x'] + Math.cos(angle) * 25 + canvas_x,
              'y': hexagons[hexagon]['y'] + Math.sin(angle) * 25 + canvas_y,
            });
        }
        canvas_draw_path(
          vertices,
          {
            'fillStyle': hexagons[hexagon]['color'],
          }
        );
    }

    canvas_buffer.fillStyle = players[turn]['color'];
    canvas_buffer.fillText(
      'Turn: ' + turn,
      0,
      25
    );
}

function logic(){
    if(canvas_menu){
        return;
    }
}

function setmode_logic(newgame){
    hexagons = [];
    turn = 0;

    // Main menu mode.
    if(canvas_mode === 0){
        document.body.innerHTML = '

New Game

'
          + '

<input disabled value=ESC>Menu
'
          + '<input id=end-turn-key>End Turn

'
          + '
<input id=hexagons>Hexagons
'
          + '<input id=players>Players
'
          + 'Reset Settings

';
        settings_update();

    // New game mode.
    }else{
        if(newgame){
            settings_save();
        }
    }
}

function toggle_hexagon(x, y){
    var side = x % 46 < 23
      ? 23
      : -23;
    x = Math.ceil((x - 23) / 46) * 46;
    y = Math.ceil((y - 20) / 40) * 40;
    if(y % 80){
        x += side;
    }

    // Modify hexagon if one exists at this x,y.
    for(var hexagon in hexagons){
        if(hexagons[hexagon]['x'] === x
          && hexagons[hexagon]['y'] === y){
            return;
        }
    }

    hexagons.push({
      'color': default_color,
      'x': x,
      'y': y,
    });
}

var default_color = '#fff';
var hexagons = [];
var players = [];
var turn = 0;

window.onkeydown = function(e){
    if(canvas_mode <= 0){
        return;
    }

    var key = e.keyCode || e.which;

    // ESC: return to main menu.
    if(key === 27){
        canvas_menu_toggle();
        return;
    }

    key = String.fromCharCode(key);

    if(key === settings_settings['end-turn-key']){
        if(turn === players.length - 1){
            turn = 0;

        }else{
            turn += 1;
        }

    }else if(key === 'Q'){
        canvas_menu_quit();
    }
};

window.onload = function(){
    settings_init(
      'Hexagons-2D.htm-',
      {
        'end-turn-key': 'H',
        'hexagons': 100,
        'players': 5,
      }
    );
    canvas_init();
};
<|endoftext|>


<commit_before>'use strict';

function create_hexagon(x, y, size){
    // Only create a hexagon if one doesn't already exist at this x,y.
    for(var hexagon in hexagons){
        if(hexagons[hexagon]['x'] === x
          && hexagons[hexagon]['y'] === y){
            return;
        }
    }

    hexagons.push({
      'color': settings_settings['default-color'],
      'size': size,
      'x': x,
      'y': y,
    });
}

function create_player(properties){
    properties = properties || {};
    properties = {
      'ai': properties['ai'] || false,
      'color': properties['color'] || random_hex(),
      'hexagons': 1,
    };

    var hexagon = random_integer(hexagons.length);
    while(hexagons[hexagon]['color'] !== settings_settings['default-color']){
        hexagon = random_integer(hexagons.length);
    }
    hexagons[hexagon]['color'] = properties['color'];

    player_ids.push(player_count);
    players[player_count] = properties;
    player_count += 1;
}

function draw_hexagon(x, y, size, color){
    if(y % 80){
        x += 23;
    }

    var vertices = [];
    for(var i = 0; i < 6; i++){
        var angle = math_degrees_to_radians({
          'degrees': 30 + i * 60,
        });
        vertices.push({
          'type': i === 0
            ? 'moveTo'
            : 'lineTo',
          'x': x + Math.cos(angle) * size + canvas_x,
          'y': y + Math.sin(angle) * size + canvas_y,
        });
    }
    canvas_draw_path(
      vertices,
      {
        'fillStyle': color,
      }
    );
}

function draw_logic(){
    // Save the current buffer state.
    canvas_buffer.save();

    // Draw selection.
    draw_hexagon(
      camera['x'],
      camera['y'],
      30,
      players[player_ids[turn]]['color']
    );

    // Draw hexagons.
    for(var hexagon in hexagons){
        draw_hexagon(
          hexagons[hexagon]['x'],
          hexagons[hexagon]['y'],
          hexagons[hexagon]['size'],
          hexagons[hexagon]['color']
        );
    }

    var x = 25;
    for(var player in players){
        canvas_buffer.fillStyle = players[player]['color'];
        canvas_buffer.fillText(
          (players[player]['ai']
            ? 'AI'
            : ' P')
            + player + ': '
            + players[player]['hexagons']
            + (player == player_ids[turn]
              ? ', TURN'
              : ''),
          0,
          x
        );
        x += 25;
    }

    if(player_count === 1){
        canvas_buffer.fillStyle = '#fff';
        canvas_buffer.fillText(
          'Player ' + player_ids[turn] + ' wins!',
          0,
          50
        );
    }
}

function end_turn(){
    if(turn >= player_ids.length - 1){
        turn = 0;

    }else{
        turn += 1;
    }

    if(!players[player_ids[turn]]){
        end_turn();
    }
}

function handle_ai_turn(){
    if(!players[player_ids[turn]]['ai']){
        return;
    }

    for(var player in players){
        if(!players[player]['ai']){
            continue;
        }

        for(var hexagon in hexagons){
            if(hexagons[hexagon]['color'] !== players[player]['color']){
                continue;
            }
        }
    }

    end_turn();
}

function logic(){
    if(canvas_menu){
        return;
    }

    handle_ai_turn();
}

function lose_hexagon(player){
    players[player]['hexagons'] -= 1;
    if(players[player]['hexagons'] <= 0){
        delete players[player];
        player_count -= 1;
    }
}

function select_hexagon(x, y){
    return {
      'x': Math.ceil((x - 23) / 46) * 46,
      'y': Math.ceil((y - 20) / 40) * 40,
    };
}

function select_y_mod(x, y, move){
    move = move || -23;

    var y_mod = Math.abs(y % 80);
    if(y_mod > 20
      && y_mod < 60){
        x += move;
    }

    return x;
}

function setmode_logic(newgame){
    hexagons = [];
    player_count = 0;
    player_ids = [];
    players = {};
    turn = 0;

    // Main menu mode.
    if(canvas_mode === 0){
        document.body.innerHTML = '

New Game

'
          + '

<input id=delete-player>Delete Player
'
          + '<input id=end-turn-key>End Turn
'
          + '<input disabled value=ESC>Menu

'
          + '
<input id=ai>AI
'
          + '<input id=default-color>Default Color
'
          + '<input id=height>Height
'
          + '<input id=hexagons>Hexagons
'
          + '<input id=players>Players
'
          + '
<input id=width>Width
'
          + 'Reset Settings

';
        settings_update();

    // New game mode.
    }else if(newgame){
        settings_save();
    }
}

var camera = {};
var hexagons = [];
var player_count = 0;
var player_ids = [];
var players = {};
var turn = 0;

window.onkeydown = function(e){
    if(canvas_mode <= 0){
        return;
    }

    var key = e.keyCode || e.which;

    // ESC: return to main menu.
    if(key === 27){
        canvas_menu_toggle();
        return;
    }

    key = String.fromCharCode(key);

    if(key === settings_settings['end-turn-key']){
        end_turn();

    }else if(key === 'Q'){
        canvas_menu_quit();

    }else if(key === 'P'){
        if(player_count > 1){
            for(var hexagon in hexagons){
                if(!players[player_ids[turn]]){
                    break;
                }
                if(hexagons[hexagon]['color'] === players[player_ids[turn]]['color']){
                    hexagons[hexagon]['color'] = settings_settings['default-color'];
                    lose_hexagon(player_ids[turn]);
                }
            }
            end_turn();
        }
    }
};

window.onmousedown = function(e){
    if(canvas_mode <= 0){
        return;
    }

    if(players[player_ids[turn]]['ai']){
        return;
    }

    var position = select_hexagon(
      camera['x'],
      camera['y']
    );

    // Check if a hexagon exists at this location.
    var target = false;
    for(var hexagon in hexagons){
        if(hexagons[hexagon]['x'] === position['x']
          && hexagons[hexagon]['y'] === position['y']){
            target = hexagon;
            break;
        }
    }
    if(target === false){
        return;
    }

    // Check if current player has a hexagon next to target hexagon.
    var next = false;
    var next_positions = [
      [-23, -40,],
      [-46, 0,],
      [-23, 40,],
      [23, -40,],
      [46, 0,],
      [23, 40,],
    ];
    next_position_loop:
    for(var next_position in next_positions){
        if(camera['y'] % 80){
            next_positions[next_position][0] += 46;
        }

        var new_next_position = select_hexagon(
          select_y_mod(
            hexagons[target]['x'] + next_positions[next_position][0],
            hexagons[target]['y'] + next_positions[next_position][1]
          ),
          hexagons[target]['y'] + next_positions[next_position][1]
        );
        for(hexagon in hexagons){
            if(hexagons[hexagon]['x'] === new_next_position['x']
              && hexagons[hexagon]['y'] === new_next_position['y']
              && hexagons[hexagon]['color'] === players[player_ids[turn]]['color']){
                next = true;
                break next_position_loop;
            }
        }
    }
    if(next === false){
        return;
    }

    // Attempt to conquer the hexagon.
    if(hexagons[target]['color'] !== players[player_ids[turn]]['color']){
        if(hexagons[target]['color'] === settings_settings['default-color']
          || random_boolean()){
            var old_color = hexagons[target]['color'];
            hexagons[target]['color'] = players[player_ids[turn]]['color'];
            players[player_ids[turn]]['hexagons'] += 1;
            for(var player in players){
                if(old_color === players[player]['color']){
                    lose_hexagon(player);
                    break;
                }
            }
        }

        end_turn();
    }
};

window.onmousemove = function(e){
    var mouse_x = e.pageX - canvas_x;
    var mouse_y = e.pageY - canvas_y;
    camera = select_hexagon(
      select_y_mod(
        mouse_x,
        mouse_y
      ),
      mouse_y
    );
};

window.onload = function(){
    settings_init(
      'Hexagons-2D.htm-',
      {
        'ai': 4,
        'default-color': '#fff',
        'delete-player': 'P',
        'end-turn-key': 'H',
        'height': 500,
        'hexagons': 100,
        'players': 1,
        'width': 500,
      }
    );
    canvas_init();
};
<commit_msg>added name property<commit_after>'use strict';

function create_hexagon(x, y, size){
    // Only create a hexagon if one doesn't already exist at this x,y.
    for(var hexagon in hexagons){
        if(hexagons[hexagon]['x'] === x
          && hexagons[hexagon]['y'] === y){
            return;
        }
    }

    hexagons.push({
      'color': settings_settings['default-color'],
      'size': size,
      'x': x,
      'y': y,
    });
}

function create_player(properties){
    properties = properties || {};
    properties = {
      'ai': properties['ai'] || false,
      'color': properties['color'] || random_hex(),
      'hexagons': 1,
      'name': '',
    };

    var hexagon = random_integer(hexagons.length);
    while(hexagons[hexagon]['color'] !== settings_settings['default-color']){
        hexagon = random_integer(hexagons.length);
    }
    hexagons[hexagon]['color'] = properties['color'];

    player_ids.push(player_count);
    properties['name'] = (properties['ai']
      ? 'AI'
      : ' P')
      + player_count;
    players[player_count] = properties;
    player_count += 1;
}

function draw_hexagon(x, y, size, color){
    if(y % 80){
        x += 23;
    }

    var vertices = [];
    for(var i = 0; i < 6; i++){
        var angle = math_degrees_to_radians({
          'degrees': 30 + i * 60,
        });
        vertices.push({
          'type': i === 0
            ? 'moveTo'
            : 'lineTo',
          'x': x + Math.cos(angle) * size + canvas_x,
          'y': y + Math.sin(angle) * size + canvas_y,
        });
    }
    canvas_draw_path(
      vertices,
      {
        'fillStyle': color,
      }
    );
}

function draw_logic(){
    // Save the current buffer state.
    canvas_buffer.save();

    // Draw selection.
    draw_hexagon(
      camera['x'],
      camera['y'],
      30,
      players[player_ids[turn]]['color']
    );

    // Draw hexagons.
    for(var hexagon in hexagons){
        draw_hexagon(
          hexagons[hexagon]['x'],
          hexagons[hexagon]['y'],
          hexagons[hexagon]['size'],
          hexagons[hexagon]['color']
        );
    }

    var x = 25;
    for(var player in players){
        canvas_buffer.fillStyle = players[player]['color'];
        canvas_buffer.fillText(
          players[player]['name']  + ': '
            + players[player]['hexagons']
            + (player == player_ids[turn]
              ? ', TURN'
              : ''),
          0,
          x
        );
        x += 25;
    }

    if(player_count === 1){
        canvas_buffer.fillStyle = '#fff';
        canvas_buffer.fillText(
          players[player]['name'] + player_ids[turn] + ' wins!',
          0,
          50
        );
    }
}

function end_turn(){
    if(turn >= player_ids.length - 1){
        turn = 0;

    }else{
        turn += 1;
    }

    if(!players[player_ids[turn]]){
        end_turn();
    }
}

function handle_ai_turn(){
    if(!players[player_ids[turn]]['ai']){
        return;
    }

    for(var player in players){
        if(!players[player]['ai']){
            continue;
        }

        for(var hexagon in hexagons){
            if(hexagons[hexagon]['color'] !== players[player]['color']){
                continue;
            }
        }
    }

    end_turn();
}

function logic(){
    if(canvas_menu){
        return;
    }

    handle_ai_turn();
}

function lose_hexagon(player){
    players[player]['hexagons'] -= 1;
    if(players[player]['hexagons'] <= 0){
        delete players[player];
        player_count -= 1;
    }
}

function select_hexagon(x, y){
    return {
      'x': Math.ceil((x - 23) / 46) * 46,
      'y': Math.ceil((y - 20) / 40) * 40,
    };
}

function select_y_mod(x, y, move){
    move = move || -23;

    var y_mod = Math.abs(y % 80);
    if(y_mod > 20
      && y_mod < 60){
        x += move;
    }

    return x;
}

function setmode_logic(newgame){
    hexagons = [];
    player_count = 0;
    player_ids = [];
    players = {};
    turn = 0;

    // Main menu mode.
    if(canvas_mode === 0){
        document.body.innerHTML = '

New Game

'
          + '

<input id=delete-player>Delete Player
'
          + '<input id=end-turn-key>End Turn
'
          + '<input disabled value=ESC>Menu

'
          + '
<input id=ai>AI
'
          + '<input id=default-color>Default Color
'
          + '<input id=height>Height
'
          + '<input id=hexagons>Hexagons
'
          + '<input id=players>Players
'
          + '
<input id=width>Width
'
          + 'Reset Settings

';
        settings_update();

    // New game mode.
    }else if(newgame){
        settings_save();
    }
}

var camera = {};
var hexagons = [];
var player_count = 0;
var player_ids = [];
var players = {};
var turn = 0;

window.onkeydown = function(e){
    if(canvas_mode <= 0){
        return;
    }

    var key = e.keyCode || e.which;

    // ESC: return to main menu.
    if(key === 27){
        canvas_menu_toggle();
        return;
    }

    key = String.fromCharCode(key);

    if(key === settings_settings['end-turn-key']){
        end_turn();

    }else if(key === 'Q'){
        canvas_menu_quit();

    }else if(key === 'P'){
        if(player_count > 1){
            for(var hexagon in hexagons){
                if(!players[player_ids[turn]]){
                    break;
                }
                if(hexagons[hexagon]['color'] === players[player_ids[turn]]['color']){
                    hexagons[hexagon]['color'] = settings_settings['default-color'];
                    lose_hexagon(player_ids[turn]);
                }
            }
            end_turn();
        }
    }
};

window.onmousedown = function(e){
    if(canvas_mode <= 0){
        return;
    }

    if(players[player_ids[turn]]['ai']){
        return;
    }

    var position = select_hexagon(
      camera['x'],
      camera['y']
    );

    // Check if a hexagon exists at this location.
    var target = false;
    for(var hexagon in hexagons){
        if(hexagons[hexagon]['x'] === position['x']
          && hexagons[hexagon]['y'] === position['y']){
            target = hexagon;
            break;
        }
    }
    if(target === false){
        return;
    }

    // Check if current player has a hexagon next to target hexagon.
    var next = false;
    var next_positions = [
      [-23, -40,],
      [-46, 0,],
      [-23, 40,],
      [23, -40,],
      [46, 0,],
      [23, 40,],
    ];
    next_position_loop:
    for(var next_position in next_positions){
        if(camera['y'] % 80){
            next_positions[next_position][0] += 46;
        }

        var new_next_position = select_hexagon(
          select_y_mod(
            hexagons[target]['x'] + next_positions[next_position][0],
            hexagons[target]['y'] + next_positions[next_position][1]
          ),
          hexagons[target]['y'] + next_positions[next_position][1]
        );
        for(hexagon in hexagons){
            if(hexagons[hexagon]['x'] === new_next_position['x']
              && hexagons[hexagon]['y'] === new_next_position['y']
              && hexagons[hexagon]['color'] === players[player_ids[turn]]['color']){
                next = true;
                break next_position_loop;
            }
        }
    }
    if(next === false){
        return;
    }

    // Attempt to conquer the hexagon.
    if(hexagons[target]['color'] !== players[player_ids[turn]]['color']){
        if(hexagons[target]['color'] === settings_settings['default-color']
          || random_boolean()){
            var old_color = hexagons[target]['color'];
            hexagons[target]['color'] = players[player_ids[turn]]['color'];
            players[player_ids[turn]]['hexagons'] += 1;
            for(var player in players){
                if(old_color === players[player]['color']){
                    lose_hexagon(player);
                    break;
                }
            }
        }

        end_turn();
    }
};

window.onmousemove = function(e){
    var mouse_x = e.pageX - canvas_x;
    var mouse_y = e.pageY - canvas_y;
    camera = select_hexagon(
      select_y_mod(
        mouse_x,
        mouse_y
      ),
      mouse_y
    );
};

window.onload = function(){
    settings_init(
      'Hexagons-2D.htm-',
      {
        'ai': 4,
        'default-color': '#fff',
        'delete-player': 'P',
        'end-turn-key': 'H',
        'height': 500,
        'hexagons': 100,
        'players': 1,
        'width': 500,
      }
    );
    canvas_init();
};
<|endoftext|>


<commit_before>(function($){

    function cmdq(options) {
      if (!(this instanceof cmdq)) {
        return new cmdq(options);
      }
      this.options=options;
      this.init();
    }

    $.extend(true,cmdq.prototype,{
        defaults: {
          q: [],
          callback: function(){}
        },

        init: function() {
          $.extend(true,this,this.defaults,this.options);
        },

        push: function(cmd,sync) {
          this.q.push({
              cmd: cmd,
              sync: sync
          });
        },

        run: function() {
          if (!this.length) {
            this.callback();
            return:
          }
          var job=this.shift();
          job.cmd.call(this);
          if (job.sync) {
            setTimeout(this.run,0);
          }
        }
    });

    $.cmdq=cmdq;

})(jQuery);
<commit_msg>jquery.cmdq.js<commit_after>(function($){

    function CmdQ(options) {
      if (!(this instanceof CmdQ)) {
        return new CmdQ(options);
      }
      this.options=options;
      this.init();
    }

    $.extend(true,CmdQ.prototype,{
        defaults: {
          q: [],
          callback: function(){
            console.log('cmdq empty');
          },
          error: function(e){
            console.log(e);
          },
          mode: {
            autorun: true,
            running: false
          }
        },

        init: function() {
          $.extend(true,this,this.defaults,this.options);
        },

        push: function(cmd,sync) {
          var cmdq=this;
          this.q.push({
              cmd: cmd,
              sync: sync
          });
          if (!cmdq.mode.running && cmdq.mode.autorun) {
            cmdq.run();
          }
        },

        run: function() {
          var cmdq=this;
          cmdq.mode.running=true;
          if (!cmdq.length) {
            cmdq.mode.running=false;
            cmdq.callback();
            return:
          }
          var job=cmdq.shift();
          try {
            job.cmd.call(cmdq);
          } catch(e) {
            console.log(e);
            cmdq.error(e);
          }
          if (job.sync) {
            setTimeout(function(){
              cmdq.run.call(cmdq);
            },0);
          }
        }
    });

    $.cmdq=cmdq;

})(jQuery);
<|endoftext|>


<commit_before>//Karyoviewer object
jviz.modules.karyoviewer = function(opt)
{
  //Check the options
  if(typeof opt !== 'object'){ var opt = {}; }

  //Save the ideogram ID
  this._id = (typeof opt.id === 'undefined') ? jviz.misc.getID({ prefix: 'karyoviewer', length: 5 }) : opt.id;

  //Save the ideogram class
  this._class = (typeof opt.class === 'undefined') ? 'jviz-modules-karyoviewer' : opt.class;

  //Parent element
  this._parent = opt.parent;

  //Default size
  this._width = 0; //Default width
  this._height = 0; //Default height

  //Margins
  //this._margin = { top: 30, bottom: 30, left: 40, right: 40 };

  //Orientation
  this._orientation = {};
  this._orientation.actual = ''; //Actual orientation name
  this._orientation.default = 'portrait'; //Default orientation
  this._orientation.values = [ 'portrait', 'landscape' ]; //Orientation values

  //Block configuration
  this._block = {};
  this._block.width = 0; //Block width
  this._block.height = 0; //Block height
  this._block.draw = { width: 0, height: 0 }; //Block draw zone
  this._block.margin = { top: 30, bottom: 30, left: 0, right: 0 }; //Block margins
  this._block.resized = false; //Block is resized

  //Block default values
  this._block.default = {};

  //Default values for protrait
  this._block.default.portrait = {};
  this._block.default.portrait.draw_width = 15; //Default portrait draw width
  this._block.default.portrait.draw_height = 70; //Default portrait draw height
  this._block.default.portrait.margin_top = 30; //Default portrait margin top
  this._block.default.portrait.margin_bottom = 30; //Default portrait margin bottom

  //Default values for landscape
  this._block.default.landscape = {};
  this._block.default.landscape.draw_width = 0; //Default landscape draw width
  this._block.default.landscape.draw_height = 20; //Default landscape draw height
  this._block.default.landscape.margin_top = 30; //Default landscape margin top
  this._block.default.landscape.margin_bottom = 30; //Default landscape margin bottom
  this._block.default.landscape.margin_left = 40; //Default landscape margin left
  this._block.default.landscape.margin_right = 40; //Default landscape margin right

  //Panel object
  this._panel = {};
  this._panel.el = null; //Panel element
  this._panel.id = this._id + '-panel'; //Panel id
  this._panel.parent = this._id; //Panel parent
  this._panel.title = (typeof opt.title === 'string') ? opt.title : 'Karyotype viewer'; //Panel title
  this._panel.detail = (typeof opt.detail === 'string') ? opt.detail : ''; //Panel detail
  this._panel.detail = ''; //Panel detail
  this._panel.visible = (typeof opt.panel === 'boolean') ? opt.panel : true; //Panel is visible

  //Canvas object
  this._canvas = {};
  this._canvas.id = this._id + '-canvas'; //Canvas ID
  this._canvas.parent = this._id; //Parent canvas ID
  this._canvas.width = '100%'; //Canvas width
  this._canvas.height = 0; //Canvas height
  this._canvas.layers = 3; //Number of layers
  this._canvas.el = null; //Canvas element

  //Check the chromosomes object
  if(typeof opt.chromosomes !== 'object'){ opt.chromosomes = {}; }

  //Chromosomes info
  this._chromosomes = {};
  this._chromosomes.width = 15; //Chromosome default width
  this._chromosomes.height = 20; //Chromosome default height
  this._chromosomes.layer = 1; //Chromosome layer
  this._chromosomes.list = []; //Chromosomes list
  this._chromosomes.names = {}; //Chromosome names
  this._chromosomes.max = 0; //Chromosome max length
  this._chromosomes.num = 0; //Number of chromosomes
  this._chromosomes.color = jviz.colors.blue2.hex; //Chromosome color
  this._chromosomes.opacity = 0.6; //Chromosome opacity
  this._chromosomes.resized = false; //Chromosome data is resized

  //Chromosome radius
  this._chromosomes.radius = {};
  this._chromosomes.radius.portrait = 6; //Chromosome radius for portrait
  this._chromosomes.radius.landscape = 10; //Chromosome radius for landscape

  //Chromosome name
  this._chromosomes.name = {};
  this._chromosomes.name.list = []; //List of chromosomes names
  this._chromosomes.name.visible = true; //Chromosome name is visible
  this._chromosomes.name.margin = 5; //Chromosomes name margin

  //Chromosome name circle
  this._chromosomes.name.circle = {};
  this._chromosomes.name.circle.width = 15; //Name circle width
  this._chromosomes.name.circle.opacity = 1.0; //Name circle opacity

  //Chromosome name text
  this._chromosomes.name.text = {};
  this._chromosomes.name.text.font = jviz.font.default; //Chromosome name text font
  this._chromosomes.name.text.color = jviz.colors.white.hex; //chromosome name text color
  this._chromosomes.name.text.size = '11px'; //Chromosome name text size
  this._chromosomes.name.text.align = 'center'; //Chromosome name text align
  this._chromosomes.name.text.margin = 5; //Chromosome name text margin

  //Centromere
  this._chromosomes.centromere = {};
  this._chromosomes.centromere.list = []; //List of centromere positions
  this._chromosomes.centromere.opacity = 0.9; //Centromere opacity

  //Check the features object
  if(typeof opt.features === 'undefined'){ opt.features = {}; }

  //Features object
  this._features = {};
  this._features.list = []; //List of features
  this._features.layer = 2; //Features layer
  this._features.color = (typeof opt.features.color === 'string') ? opt.features.color : jviz.colors.red.hex; //Features default color
  this._features.opacity = 0.8; //Features opacity
  this._features.resized = false; //Features data is resized

  //Features triangle
  this._features.triangle = {};
  this._features.triangle.width = 6; //Features triangle width
  this._features.triangle.height = 4; //Features triangle height
  this._features.triangle.margin = 1; //Features triangle mrgin
  this._features.triangle.opacity = 0.6; //Features triangle opacity
  this._features.triangle.visible = (typeof opt.features.triangle === 'boolean') ? opt.features.triangle : true; //Triangle visible

  //Features label
  this._features.label = {};
  this._features.label.opacity = 1.0; //Features label opacity
  this._features.label.visible = (typeof opt.features.label === 'boolean') ? opt.features.label : true; //Label visible

  //Features label rectangle
  this._features.label.rectangle = {};
  this._features.label.rectangle.width = 0; //Features label rectangle width
  this._features.label.rectangle.height = 0; //Features label rectangle height
  this._features.label.rectangle.radius = 5; //Features label rectangle radius

  //Chromosomes hover
  this._hover = {};
  this._hover.index = -1; //Hover chromosome index
  this._hover.margin = { top: 10, bottom: 20, left: 10, right: 10 }; //Hover margin
  this._hover.color = jviz.colors.white.hex; //Hover background color
  this._hover.opacity = 1.0; //Hover background color opacity
  this._hover.radius = 10; //Hover radius
  this._hover.layer = 0; //Hover layer

  //Check for undefined orientation
  if(typeof opt.orientation !== 'string'){ opt.orientation = 'portrait'; }

  //Build the karyotype element
  this.build();

  //Register the events
  this.events();

  //Parse the orientation
  this.orientation(opt.orientation);

  //Return this
  return this;
};
<commit_msg>js/karyoviewer.js: updated chromosomes name definitions<commit_after>//Karyoviewer object
jviz.modules.karyoviewer = function(opt)
{
  //Check the options
  if(typeof opt !== 'object'){ var opt = {}; }

  //Save the ideogram ID
  this._id = (typeof opt.id === 'undefined') ? jviz.misc.getID({ prefix: 'karyoviewer', length: 5 }) : opt.id;

  //Save the ideogram class
  this._class = (typeof opt.class === 'undefined') ? 'jviz-modules-karyoviewer' : opt.class;

  //Parent element
  this._parent = opt.parent;

  //Default size
  this._width = 0; //Default width
  this._height = 0; //Default height

  //Margins
  //this._margin = { top: 30, bottom: 30, left: 40, right: 40 };

  //Orientation
  this._orientation = {};
  this._orientation.actual = ''; //Actual orientation name
  this._orientation.default = 'portrait'; //Default orientation
  this._orientation.values = [ 'portrait', 'landscape' ]; //Orientation values

  //Block configuration
  this._block = {};
  this._block.width = 0; //Block width
  this._block.height = 0; //Block height
  this._block.draw = { width: 0, height: 0 }; //Block draw zone
  this._block.margin = { top: 30, bottom: 30, left: 0, right: 0 }; //Block margins
  this._block.resized = false; //Block is resized

  //Block default values
  this._block.default = {};

  //Default values for protrait
  this._block.default.portrait = {};
  this._block.default.portrait.draw_width = 15; //Default portrait draw width
  this._block.default.portrait.draw_height = 70; //Default portrait draw height
  this._block.default.portrait.margin_top = 30; //Default portrait margin top
  this._block.default.portrait.margin_bottom = 30; //Default portrait margin bottom

  //Default values for landscape
  this._block.default.landscape = {};
  this._block.default.landscape.draw_width = 0; //Default landscape draw width
  this._block.default.landscape.draw_height = 20; //Default landscape draw height
  this._block.default.landscape.margin_top = 30; //Default landscape margin top
  this._block.default.landscape.margin_bottom = 30; //Default landscape margin bottom
  this._block.default.landscape.margin_left = 40; //Default landscape margin left
  this._block.default.landscape.margin_right = 40; //Default landscape margin right

  //Panel object
  this._panel = {};
  this._panel.el = null; //Panel element
  this._panel.id = this._id + '-panel'; //Panel id
  this._panel.parent = this._id; //Panel parent
  this._panel.title = (typeof opt.title === 'string') ? opt.title : 'Karyotype viewer'; //Panel title
  this._panel.detail = (typeof opt.detail === 'string') ? opt.detail : ''; //Panel detail
  this._panel.detail = ''; //Panel detail
  this._panel.visible = (typeof opt.panel === 'boolean') ? opt.panel : true; //Panel is visible

  //Canvas object
  this._canvas = {};
  this._canvas.id = this._id + '-canvas'; //Canvas ID
  this._canvas.parent = this._id; //Parent canvas ID
  this._canvas.width = '100%'; //Canvas width
  this._canvas.height = 0; //Canvas height
  this._canvas.layers = 3; //Number of layers
  this._canvas.el = null; //Canvas element

  //Check the chromosomes object
  if(typeof opt.chromosomes !== 'object'){ opt.chromosomes = {}; }

  //Chromosomes info
  this._chromosomes = {};
  this._chromosomes.width = 15; //Chromosome default width
  this._chromosomes.height = 20; //Chromosome default height
  this._chromosomes.layer = 1; //Chromosome layer
  this._chromosomes.list = []; //Chromosomes list
  this._chromosomes.names = {}; //Chromosome names
  this._chromosomes.max = 0; //Chromosome max length
  this._chromosomes.num = 0; //Number of chromosomes
  this._chromosomes.color = jviz.colors.blue2.hex; //Chromosome color
  this._chromosomes.opacity = 0.6; //Chromosome opacity
  this._chromosomes.resized = false; //Chromosome data is resized

  //Chromosome radius
  this._chromosomes.radius = {};
  this._chromosomes.radius.portrait = 6; //Chromosome radius for portrait
  this._chromosomes.radius.landscape = 10; //Chromosome radius for landscape

  //Chromosome name
  this._chromosomes.name = {};
  this._chromosomes.name.list = []; //List of chromosomes names
  this._chromosomes.name.visible = true; //Chromosome name is visible
  this._chromosomes.name.margin = 7; //Chromosome name margin

  //Chromosome name text
  this._chromosomes.name.text = {};
  this._chromosomes.name.text.font = jviz.font.default; //Chromosome name text font
  this._chromosomes.name.text.size = '12px'; //Chromosome name text size
  this._chromosomes.name.text.align = 'center'; //Chromosome name text align

  //Centromere
  this._chromosomes.centromere = {};
  this._chromosomes.centromere.list = []; //List of centromere positions
  this._chromosomes.centromere.opacity = 0.9; //Centromere opacity

  //Check the features object
  if(typeof opt.features === 'undefined'){ opt.features = {}; }

  //Features object
  this._features = {};
  this._features.list = []; //List of features
  this._features.layer = 2; //Features layer
  this._features.color = (typeof opt.features.color === 'string') ? opt.features.color : jviz.colors.red.hex; //Features default color
  this._features.opacity = 0.8; //Features opacity
  this._features.resized = false; //Features data is resized

  //Features triangle
  this._features.triangle = {};
  this._features.triangle.width = 6; //Features triangle width
  this._features.triangle.height = 4; //Features triangle height
  this._features.triangle.margin = 1; //Features triangle mrgin
  this._features.triangle.opacity = 0.6; //Features triangle opacity
  this._features.triangle.visible = (typeof opt.features.triangle === 'boolean') ? opt.features.triangle : true; //Triangle visible

  //Features label
  this._features.label = {};
  this._features.label.opacity = 1.0; //Features label opacity
  this._features.label.visible = (typeof opt.features.label === 'boolean') ? opt.features.label : true; //Label visible

  //Features label rectangle
  this._features.label.rectangle = {};
  this._features.label.rectangle.width = 0; //Features label rectangle width
  this._features.label.rectangle.height = 0; //Features label rectangle height
  this._features.label.rectangle.radius = 5; //Features label rectangle radius

  //Chromosomes hover
  this._hover = {};
  this._hover.index = -1; //Hover chromosome index
  this._hover.margin = { top: 10, bottom: 20, left: 10, right: 10 }; //Hover margin
  this._hover.color = jviz.colors.white.hex; //Hover background color
  this._hover.opacity = 1.0; //Hover background color opacity
  this._hover.radius = 10; //Hover radius
  this._hover.layer = 0; //Hover layer

  //Check for undefined orientation
  if(typeof opt.orientation !== 'string'){ opt.orientation = 'portrait'; }

  //Build the karyotype element
  this.build();

  //Register the events
  this.events();

  //Parse the orientation
  this.orientation(opt.orientation);

  //Return this
  return this;
};
<|endoftext|>


<commit_before>/*
 * INumber.js - Parse a number in any locale
 *
 * Copyright © 2012-2015, JEDLSoft
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
!depends
ilib.js
Locale.js
isDigit.js
isSpace.js
LocaleInfo.js
Utils.js
Currency.js
*/

var ilib = require("./ilib.js");
var Utils = require("./Utils.js");

var Locale = require("./Locale.js");
var LocaleInfo = require("./LocaleInfo.js");

var CType = require("./CType.js");
var isDigit = require("./isDigit.js");
var isSpace = require("./isSpace.js");

var Currency = require("./Currency.js");

/**
 * @class
 * Parse a string as a number, ignoring all locale-specific formatting.

 *
 * This class is different from the standard Javascript parseInt() and parseFloat()
 * functions in that the number to be parsed can have formatting characters in it
 * that are not supported by those two
 * functions, and it handles numbers written in other locales properly. For example,
 * if you pass the string "203,231.23" to the parseFloat() function in Javascript, it
 * will return you the number 203. The INumber class will parse it correctly and
 * the value() function will return the number 203231.23. If you pass parseFloat() the
 * string "203.231,23" with the locale set to de-DE, it will return you 203 again. This
 * class will return the correct number 203231.23 again.

 *
 * The options object may contain any of the following properties:
 *
 *

 *
locale - specify the locale of the string to parse. This is used to
 * figure out what the decimal point character is. If not specified, the default locale
 * for the app or browser is used.
 *
type - specify whether this string should be interpretted as a number,
 * currency, or percentage amount. When the number is interpretted as a currency
 * amount, the getCurrency() method will return something useful, otherwise it will
 * return undefined. If
 * the number is to be interpretted as percentage amount and there is a percentage sign
 * in the string, then the number will be returned
 * as a fraction from the valueOf() method. If there is no percentage sign, then the
 * number will be returned as a regular number. That is "58.3%" will be returned as the
 * number 0.583 but "58.3" will be returned as 58.3. Valid values for this property
 * are "number", "currency", and "percentage". Default if this is not specified is
 * "number".
 *
onLoad - a callback function to call when the locale data is fully
 * loaded. When the onLoad option is given, this class will attempt to
 * load any missing locale data using the ilib loader callback.
 * When the constructor is done (even if the data is already preassembled), the
 * onLoad function is called with the current instance as a parameter, so this
 * callback can be used with preassembled or dynamic loading or a mix of the two.
 *
 *
sync - tell whether to load any missing locale data synchronously or
 * asynchronously. If this option is given as "false", then the "onLoad"
 * callback must be given, as the instance returned from this constructor will
 * not be usable for a while.
 *
 *
loadParams - an object containing parameters to pass to the
 * loader callback function when locale data is missing. The parameters are not
 * interpretted or modified in any way. They are simply passed along. The object
 * may contain any property/value pairs as long as the calling code is in
 * agreement with the loader callback function as to what those parameters mean.
 *

 *

 *
 * This class is named INumber ("ilib number") so as not to conflict with the
 * built-in Javascript Number class.
 *
 * @constructor
 * @param {string|number|INumber|Number|undefined} str a string to parse as a number, or a number value
 * @param {Object=} options Options controlling how the instance should be created
 */
var INumber = function (str, options) {
	var i, stripped = "",
		sync = true;

	this.locale = new Locale();
	this.type = "number";

	if (options) {
		if (options.locale) {
			this.locale = (typeof(options.locale) === 'string') ? new Locale(options.locale) : options.locale;
		}
		if (options.type) {
			switch (options.type) {
				case "number":
				case "currency":
				case "percentage":
					this.type = options.type;
					break;
				default:
					break;
			}
		}
		if (typeof(options.sync) !== 'undefined') {
			sync = (options.sync == true);
		}
	} else {
	    options = {sync: true};
	}

	isDigit._init(sync, options.loadParams, ilib.bind(this, function() {
		isSpace._init(sync, options.loadParams, ilib.bind(this, function() {
			new LocaleInfo(this.locale, {
				sync: sync,
				loadParams: options.loadParams,
				onLoad: ilib.bind(this, function (li) {
				    this.li = li;
					this.decimal = li.getDecimalSeparator();
					var nativeDecimal = this.li.getNativeDecimalSeparator() || "";

					switch (typeof(str)) {
					case 'string':
						// stripping should work for all locales, because you just ignore all the
						// formatting except the decimal char
						var unary = true; // looking for the unary minus still?
						var lastNumericChar = 0;
						this.str = str || "0";
						i = 0;
						for (i = 0; i < this.str.length; i++) {
							if (unary && this.str.charAt(i) === '-') {
								unary = false;
								stripped += this.str.charAt(i);
								lastNumericChar = i;
							} else if (isDigit(this.str.charAt(i))) {
								stripped += this.str.charAt(i);
								unary = false;
								lastNumericChar = i;
							} else if (this.str.charAt(i) === this.decimal || this.str.charAt(i) === nativeDecimal) {
								stripped += "."; // always convert to period
								unary = false;
								lastNumericChar = i;
							} // else ignore
						}
						// record what we actually parsed
						this.parsed = this.str.substring(0, lastNumericChar+1);

						/** @type {number} */
						this.value = parseFloat(this._mapToLatinDigits(stripped));
						break;
					case 'number':
						this.str = "" + str;
						this.value = str;
						break;

					case 'object':
						// call parseFloat to coerse the type to number
						this.value = parseFloat(str.valueOf());
						this.str = "" + this.value;
						break;

					case 'undefined':
						this.value = 0;
						this.str = "0";
						break;
					}

					switch (this.type) {
						default:
							// don't need to do anything special for other types
							break;
						case "percentage":
							if (this.str.indexOf(li.getPercentageSymbol()) !== -1) {
								this.value /= 100;
							}
							break;
						case "currency":
							stripped = "";
							i = 0;
							while (i < this.str.length &&
								   !isDigit(this.str.charAt(i)) &&
								   !isSpace(this.str.charAt(i))) {
								stripped += this.str.charAt(i++);
							}
							if (stripped.length === 0) {
								while (i < this.str.length &&
									   isDigit(this.str.charAt(i)) ||
									   isSpace(this.str.charAt(i)) ||
									   this.str.charAt(i) === '.' ||
									   this.str.charAt(i) === ',' ) {
									i++;
								}
								while (i < this.str.length &&
									   !isDigit(this.str.charAt(i)) &&
									   !isSpace(this.str.charAt(i))) {
									stripped += this.str.charAt(i++);
								}
							}
							new Currency({
								locale: this.locale,
								sign: stripped,
								sync: sync,
								loadParams: options.loadParams,
								onLoad: ilib.bind(this, function (cur) {
									this.currency = cur;
									if (options && typeof(options.onLoad) === 'function') {
										options.onLoad(this);
									}
								})
							});
							return;
					}

					if (options && typeof(options.onLoad) === 'function') {
						options.onLoad(this);
					}
				})
			});
		}));
	}));
};

INumber.prototype = {
    /**
     * @private
     */
    _mapToLatinDigits: function(str) {
        // only map if there are actual native digits
        var digits = this.li.getNativeDigits();
        if (!digits) return str;

        var digitMap = {};
        for (var i = 0; i < digits.length; i++) {
            digitMap[digits[i]] = String(i);
        }

        return str.split("").map(function(ch) {
            return digitMap[ch] || ch;
        }).join("");
    },

	/**
	 * Return the locale for this formatter instance.
	 * @return {Locale} the locale instance for this formatter
	 */
	getLocale: function () {
		return this.locale;
	},

	/**
	 * Return the original string that this number instance was created with.
	 * @return {string} the original string
	 */
	toString: function () {
		return this.str;
	},

	/**
	 * If the type of this INumber instance is "currency", then the parser will attempt
	 * to figure out which currency this amount represents. The amount can be written
	 * with any of the currency signs or ISO 4217 codes that are currently
	 * recognized by ilib, and the currency signs may occur before or after the
	 * numeric portion of the string. If no currency can be recognized, then the
	 * default currency for the locale is returned. If multiple currencies can be
	 * recognized (for example if the currency sign is "$"), then this method
	 * will prefer the one for the current locale. If multiple currencies can be
	 * recognized, but none are used in the current locale, then the first currency
	 * encountered will be used. This may produce random results, though the larger
	 * currencies occur earlier in the list. For example, if the sign found in the
	 * string is "$" and that is not the sign of the currency of the current locale
	 * then the US dollar will be recognized, as it is the largest currency that uses
	 * the "$" as its sign.
	 *
	 * @return {Currency|undefined} the currency instance for this amount, or
	 * undefined if this INumber object is not of type currency
	 */
	getCurrency: function () {
		return this.currency;
	},

	/**
	 * Return the value of this INumber object as a primitive number instance.
	 * @return {number} the value of this number instance
	 */
	valueOf: function () {
		return this.value;
	}
};

module.exports = INumber;<commit_msg>Use the JSUtils string mapper<commit_after>/*
 * INumber.js - Parse a number in any locale
 *
 * Copyright © 2012-2015, JEDLSoft
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
!depends
ilib.js
Locale.js
isDigit.js
isSpace.js
LocaleInfo.js
Utils.js
JSUtils.js
Currency.js
*/

var ilib = require("./ilib.js");
var Utils = require("./Utils.js");
var JSUtils = require("./JSUtils.js");

var Locale = require("./Locale.js");
var LocaleInfo = require("./LocaleInfo.js");

var CType = require("./CType.js");
var isDigit = require("./isDigit.js");
var isSpace = require("./isSpace.js");

var Currency = require("./Currency.js");

/**
 * @class
 * Parse a string as a number, ignoring all locale-specific formatting.

 *
 * This class is different from the standard Javascript parseInt() and parseFloat()
 * functions in that the number to be parsed can have formatting characters in it
 * that are not supported by those two
 * functions, and it handles numbers written in other locales properly. For example,
 * if you pass the string "203,231.23" to the parseFloat() function in Javascript, it
 * will return you the number 203. The INumber class will parse it correctly and
 * the value() function will return the number 203231.23. If you pass parseFloat() the
 * string "203.231,23" with the locale set to de-DE, it will return you 203 again. This
 * class will return the correct number 203231.23 again.

 *
 * The options object may contain any of the following properties:
 *
 *

 *
locale - specify the locale of the string to parse. This is used to
 * figure out what the decimal point character is. If not specified, the default locale
 * for the app or browser is used.
 *
type - specify whether this string should be interpretted as a number,
 * currency, or percentage amount. When the number is interpretted as a currency
 * amount, the getCurrency() method will return something useful, otherwise it will
 * return undefined. If
 * the number is to be interpretted as percentage amount and there is a percentage sign
 * in the string, then the number will be returned
 * as a fraction from the valueOf() method. If there is no percentage sign, then the
 * number will be returned as a regular number. That is "58.3%" will be returned as the
 * number 0.583 but "58.3" will be returned as 58.3. Valid values for this property
 * are "number", "currency", and "percentage". Default if this is not specified is
 * "number".
 *
onLoad - a callback function to call when the locale data is fully
 * loaded. When the onLoad option is given, this class will attempt to
 * load any missing locale data using the ilib loader callback.
 * When the constructor is done (even if the data is already preassembled), the
 * onLoad function is called with the current instance as a parameter, so this
 * callback can be used with preassembled or dynamic loading or a mix of the two.
 *
 *
sync - tell whether to load any missing locale data synchronously or
 * asynchronously. If this option is given as "false", then the "onLoad"
 * callback must be given, as the instance returned from this constructor will
 * not be usable for a while.
 *
 *
loadParams - an object containing parameters to pass to the
 * loader callback function when locale data is missing. The parameters are not
 * interpretted or modified in any way. They are simply passed along. The object
 * may contain any property/value pairs as long as the calling code is in
 * agreement with the loader callback function as to what those parameters mean.
 *

 *

 *
 * This class is named INumber ("ilib number") so as not to conflict with the
 * built-in Javascript Number class.
 *
 * @constructor
 * @param {string|number|INumber|Number|undefined} str a string to parse as a number, or a number value
 * @param {Object=} options Options controlling how the instance should be created
 */
var INumber = function (str, options) {
	var i, stripped = "",
		sync = true;

	this.locale = new Locale();
	this.type = "number";

	if (options) {
		if (options.locale) {
			this.locale = (typeof(options.locale) === 'string') ? new Locale(options.locale) : options.locale;
		}
		if (options.type) {
			switch (options.type) {
				case "number":
				case "currency":
				case "percentage":
					this.type = options.type;
					break;
				default:
					break;
			}
		}
		if (typeof(options.sync) !== 'undefined') {
			sync = (options.sync == true);
		}
	} else {
	    options = {sync: true};
	}

	isDigit._init(sync, options.loadParams, ilib.bind(this, function() {
		isSpace._init(sync, options.loadParams, ilib.bind(this, function() {
			new LocaleInfo(this.locale, {
				sync: sync,
				loadParams: options.loadParams,
				onLoad: ilib.bind(this, function (li) {
				    this.li = li;
					this.decimal = li.getDecimalSeparator();
					var nativeDecimal = this.li.getNativeDecimalSeparator() || "";

					switch (typeof(str)) {
					case 'string':
						// stripping should work for all locales, because you just ignore all the
						// formatting except the decimal char
						var unary = true; // looking for the unary minus still?
						var lastNumericChar = 0;
						this.str = str || "0";
						i = 0;
						for (i = 0; i < this.str.length; i++) {
							if (unary && this.str.charAt(i) === '-') {
								unary = false;
								stripped += this.str.charAt(i);
								lastNumericChar = i;
							} else if (isDigit(this.str.charAt(i))) {
								stripped += this.str.charAt(i);
								unary = false;
								lastNumericChar = i;
							} else if (this.str.charAt(i) === this.decimal || this.str.charAt(i) === nativeDecimal) {
								stripped += "."; // always convert to period
								unary = false;
								lastNumericChar = i;
							} // else ignore
						}
						// record what we actually parsed
						this.parsed = this.str.substring(0, lastNumericChar+1);

						/** @type {number} */
						this.value = parseFloat(this._mapToLatinDigits(stripped));
						break;
					case 'number':
						this.str = "" + str;
						this.value = str;
						break;

					case 'object':
						// call parseFloat to coerse the type to number
						this.value = parseFloat(str.valueOf());
						this.str = "" + this.value;
						break;

					case 'undefined':
						this.value = 0;
						this.str = "0";
						break;
					}

					switch (this.type) {
						default:
							// don't need to do anything special for other types
							break;
						case "percentage":
							if (this.str.indexOf(li.getPercentageSymbol()) !== -1) {
								this.value /= 100;
							}
							break;
						case "currency":
							stripped = "";
							i = 0;
							while (i < this.str.length &&
								   !isDigit(this.str.charAt(i)) &&
								   !isSpace(this.str.charAt(i))) {
								stripped += this.str.charAt(i++);
							}
							if (stripped.length === 0) {
								while (i < this.str.length &&
									   isDigit(this.str.charAt(i)) ||
									   isSpace(this.str.charAt(i)) ||
									   this.str.charAt(i) === '.' ||
									   this.str.charAt(i) === ',' ) {
									i++;
								}
								while (i < this.str.length &&
									   !isDigit(this.str.charAt(i)) &&
									   !isSpace(this.str.charAt(i))) {
									stripped += this.str.charAt(i++);
								}
							}
							new Currency({
								locale: this.locale,
								sign: stripped,
								sync: sync,
								loadParams: options.loadParams,
								onLoad: ilib.bind(this, function (cur) {
									this.currency = cur;
									if (options && typeof(options.onLoad) === 'function') {
										options.onLoad(this);
									}
								})
							});
							return;
					}

					if (options && typeof(options.onLoad) === 'function') {
						options.onLoad(this);
					}
				})
			});
		}));
	}));
};

INumber.prototype = {
    /**
     * @private
     */
    _mapToLatinDigits: function(str) {
        // only map if there are actual native digits
        var digits = this.li.getNativeDigits();
        if (!digits) return str;

        var digitMap = {};
        for (var i = 0; i < digits.length; i++) {
            digitMap[digits[i]] = String(i);
        }

        return JSUtils.mapString(str, digitMap);
    },

	/**
	 * Return the locale for this formatter instance.
	 * @return {Locale} the locale instance for this formatter
	 */
	getLocale: function () {
		return this.locale;
	},

	/**
	 * Return the original string that this number instance was created with.
	 * @return {string} the original string
	 */
	toString: function () {
		return this.str;
	},

	/**
	 * If the type of this INumber instance is "currency", then the parser will attempt
	 * to figure out which currency this amount represents. The amount can be written
	 * with any of the currency signs or ISO 4217 codes that are currently
	 * recognized by ilib, and the currency signs may occur before or after the
	 * numeric portion of the string. If no currency can be recognized, then the
	 * default currency for the locale is returned. If multiple currencies can be
	 * recognized (for example if the currency sign is "$"), then this method
	 * will prefer the one for the current locale. If multiple currencies can be
	 * recognized, but none are used in the current locale, then the first currency
	 * encountered will be used. This may produce random results, though the larger
	 * currencies occur earlier in the list. For example, if the sign found in the
	 * string is "$" and that is not the sign of the currency of the current locale
	 * then the US dollar will be recognized, as it is the largest currency that uses
	 * the "$" as its sign.
	 *
	 * @return {Currency|undefined} the currency instance for this amount, or
	 * undefined if this INumber object is not of type currency
	 */
	getCurrency: function () {
		return this.currency;
	},

	/**
	 * Return the value of this INumber object as a primitive number instance.
	 * @return {number} the value of this number instance
	 */
	valueOf: function () {
		return this.value;
	}
};

module.exports = INumber;<|endoftext|>


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

    function CreateTransparentImages(targetTransparentImagePaths, maskImagesSuffix) {
        var that = this;
        var suffix = maskImagesSuffix || 'mask';

        targetTransparentImagePaths.forEach(function (imagePath, i) {
            var maskImagePath = imagePath.replace(/\.jpg/, '-' + suffix + '.png');
            that.onLoadImage(imagePath, maskImagePath);
        });
    }

    CreateTransparentImages.prototype.onLoadImage = function (targetImageName, maskImageName) {
        var targetImage = document.createElement('img');
        targetImage.src = targetImageName;

        var maskImage = document.createElement('img');
        maskImage.src = maskImageName;

        targetImage.onload = function () { this.translateImage(targetImage, maskImage) };
        maskImage.onload = function () { this.translateImage(targetImage, maskImage) };
    };

    CreateTransparentImages.prototype.translateImage = function (targetImage, maskImage) {
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d');

        canvas.width = targetImage.naturalWidth;
        canvas.height = targetImage.naturalHeight;

        ctx.drawImage(targetImage, 0, 0);
        ctx.globalCompositeOperation = 'xor';
        ctx.drawImage(maskImage, 0, 0);

        return canvas;
    };

    CreateTransparentImages.prototype.appendCanvas = function (targetElement, canvas) {
        document.querySelector(targetElement).querySelector(canvas);
    };

    exports.CreateTransparentImages = CreateTransparentImages;
})(window);

document.addEventListener('DOMContentLoaded', function () {
    var images = ['//cdn.rawgit.com/o2project/sg-tokusetsu/master/img/okabe.jpg', '//cdn.rawgit.com/o2project/sg-tokusetsu/master/img/kurisu.jpg', '//cdn.rawgit.com/o2project/sg-tokusetsu/master/img/kokuban.jpg'];
    var transparentImages = new CreateTransparentImages(images);
});
<commit_msg>fix(main-visual): thisの代わりにthatを指定するようにした<commit_after>(function (exports) {
    'use strict';

    function CreateTransparentImages(targetTransparentImagePaths, maskImagesSuffix) {
        var that = this;
        var suffix = maskImagesSuffix || 'mask';

        targetTransparentImagePaths.forEach(function (imagePath, i) {
            var maskImagePath = imagePath.replace(/\.jpg/, '-' + suffix + '.png');
            that.onLoadImage(imagePath, maskImagePath);
        });
    }

    CreateTransparentImages.prototype.onLoadImage = function (targetImageName, maskImageName) {
        var that = this;

        var targetImage = document.createElement('img');
        targetImage.src = targetImageName;

        var maskImage = document.createElement('img');
        maskImage.src = maskImageName;

        targetImage.onload = function () { that.translateImage(targetImage, maskImage) };
        maskImage.onload = function () { that.translateImage(targetImage, maskImage) };
    };

    CreateTransparentImages.prototype.translateImage = function (targetImage, maskImage) {
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d');

        canvas.width = targetImage.naturalWidth;
        canvas.height = targetImage.naturalHeight;

        ctx.drawImage(targetImage, 0, 0);
        ctx.globalCompositeOperation = 'xor';
        ctx.drawImage(maskImage, 0, 0);

        return canvas;
    };

    CreateTransparentImages.prototype.appendCanvas = function (targetElement, canvas) {
        document.querySelector(targetElement).querySelector(canvas);
    };

    exports.CreateTransparentImages = CreateTransparentImages;
})(window);

document.addEventListener('DOMContentLoaded', function () {
    var images = ['//cdn.rawgit.com/o2project/sg-tokusetsu/master/img/okabe.jpg', '//cdn.rawgit.com/o2project/sg-tokusetsu/master/img/kurisu.jpg', '//cdn.rawgit.com/o2project/sg-tokusetsu/master/img/kokuban.jpg'];
    var transparentImages = new CreateTransparentImages(images);
});
<|endoftext|>