maps.nyc.gov

Source: ol/control/layerswipe.js

var nyc = nyc || {};
nyc.ol = nyc.ol || {};
nyc.ol.control = nyc.ol.control || {};

/**
 * @desc Class that provides layer swiping effect
 * @public
 * @class
 * @extends {nyc.ol.control.LayerPicker}
 * @constructor
 * @param {nyc.ol.control.LayerPicker.Options} options Constructor options
 */
nyc.ol.control.LayerSwipe = function(options){
	nyc.ol.control.LayerPicker.call(this, options);
	this.container.append(nyc.ol.control.LayerSwipe.MENU_BUTTONS_HTML).trigger('create');
	this.getElem('input').change($.proxy(this.validate, this));
	this.getElem('.btn-ok').click($.proxy(this.makeChoices, this));
	this.getElem('.btn-cancel').click($.proxy(this.cancel, this));
	this.getElem('.btn-cancel').click($.proxy(this.toggleMenu, this));
	this.getElem('.btn-swipe').click($.proxy(this.reset, this));
	this.map.on('pointermove', $.proxy(this.swipe, this));
};

nyc.ol.control.LayerSwipe.prototype = {
	/**
	 * @private
	 * @member {boolean}
	 */
	active: false,
	/**
	 * @private
	 * @member {ol.layer.Base}
	 */
	leftLayer: null,
	/**
	 * @private
	 * @member {ol.layer.Base}
	 */
	rightLayer: null,
	/**
	 * @public
	 * @override
	 * @method
	 * @return {string}
	 */
	getMenuClass: function(){
		return 'mnu-swipe';
	},
	/**
	 * @public
	 * @override
	 * @method
	 * @return {string}
	 */
	getButtonHtml: function(){
		return nyc.ol.control.LayerSwipe.BUTTON_HTML;
	},
	/**
	 * @public
	 * @override
	 * @method
	 * @param {ol.Map} map
	 * @return {Array<nyc.ol.control.LayerPicker.LayerGroup>}
	 */
	getLayerGoupsFromMap: function(map){
		var layers = [], photos = {};
		if (map.getBaseLayers){
			var photos = map.getBaseLayers().photos;
			layers = map.sortedPhotos();
		}
		map.getLayers().forEach(function(layer){
			var name = layer.get('name'); 
			if (name && !photos[name]){
				layers.push(layer);
			}
		});
		return [{name: 'Swipe layers', layers: layers, expanded: true}];
	},
	/**
	 * @desc Set the left layer of the swipe
	 * @public
	 * @method
	 * @param {ol.layer.Base} layer The layer for the left side of a swipe
	 */
	setLeft: function(layer){
		this.setOriginalExtent(layer);
		this.setVisible(layer);
		this.leftLayer = layer;
	},
	/**
	 * @desc Set the right layer of the swipe
	 * @public
	 * @method
	 * @param {ol.layer.Base} layer The layer for the right side of a swipe
	 */
	setRight: function(layer){
		this.setOriginalExtent(layer);
		this.setVisible(layer);
		this.rightLayer = layer;
	},
	/**
	 * @desc Clear the display
	 * @public
	 * @method
	 */
	cancel: function(){
		this.setActive(false);
		this.reset();
	},
	/**
	 * @desc Set active state of swipe
	 * @public
	 * @method
	 * @param {boolean} active The active state
	 */
	setActive: function(active){
		this.active = active;
		this.map.getInteractions().forEach(function(interaction){
			if (interaction instanceof ol.interaction.DragPan){
				interaction.setActive(!active);
			}
		});
		if (!active){
			this.reset();
		}
	},
	/**
	 * @private
	 * @method
	 * @param {ol.layer.Base} layer
	 */
	setVisible: function(layer){
		if (layer){
			layer.setVisible(true);
			layer.setZIndex(999);
		}
	},
	/**
	 * @private
	 * @method
	 * @param {ol.layer.Base} layer
	 */
	setOriginalExtent: function(layer){
		if (layer){
			layer.set('originalExtent', ol.geom.Polygon.fromExtent(layer.get('originalExtent') || layer.getExtent() || nyc.ol.Basemap.UNIVERSE_EXTENT).getExtent());
		}
	},
	/**
	 * @private
	 * @method
	 */
	redraw: function(){
		this.triggerChange(this.leftLayer);
		this.triggerChange(this.rightLayer);
		this.map.render();
	},
	/**
	 * @private
	 * @method
	 * @param {ol.layer.Base} layer
	 */
	triggerChange: function(layer){
		if (layer){
			layer.getSource().dispatchEvent('change'); 
		}
	},
	/**
	 * @private
	 * @method
	 */
	reset: function(){
		this.resetExtent(this.leftLayer);
		this.resetExtent(this.rightLayer);
		$('.swipe-label').remove();
		this.redraw();
	},
	/**
	 * @private
	 * @method
	 * @param {ol.layer.Base} layer
	 */
	resetExtent: function(layer){
		if (layer){
			layer.setExtent(layer.get('originalExtent'));
			layer.setVisible(false);
		}
	},
	/**
	 * @private
	 * @method
	 * @param {ol.MapBrowserEvent} event
	 */
	swipe: function(event){
		if (this.active){
			this.setVisible(this.leftLayer);
			this.setVisible(this.rightLayer);
			var x = event.coordinate[0];
			this.swipeLeft(x);
			this.swipeRight(x);
			this.label(event.pixel);
			this.redraw();
		}
	},
	/**
	 * @private
	 * @method
	 * @param {number} x
	 */
	swipeLeft: function(x){
		if (this.leftLayer){
			var leftExtent = ol.geom.Polygon.fromExtent(this.leftLayer.getExtent()).getExtent();
			leftExtent[2] = x;
			this.leftLayer.setExtent(leftExtent);
		}
	},
	/**
	 * @private
	 * @method
	 * @param {number} x
	 */
	swipeRight: function(x){
		if (this.rightLayer){
			var rightExt = ol.geom.Polygon.fromExtent(this.rightLayer.getExtent()).getExtent();
			rightExt[0] = x;
			this.rightLayer.setExtent(rightExt);
		}
	},
	/**
	 * @private
	 * @method
	 * @param {JQuery.Event} event
	 */
	validate: function(event){
		var check = event.target;
		if (this.getElem('input:checked').length > 2 && check.checked){
			$(check).trigger('click');
		}
	},
	/**
	 * @private
	 * @method
	 */
	makeChoices: function(){
		this.toggleMenu();
		var choices = this.controls[0].val(), layers = this.getLayers();
		this.setLeft();
		this.setRight();
		if (choices.length){
			this.setLeft(layers[choices[0].value]);
			if (choices[1]) this.setRight(layers[choices[1].value]);
			this.setActive(true);
		}
	},
	/**
	 * @private
	 * @method
	 * @param {ol.Coordinate} pixel
	 */
	label: function(pixel){
		if (this.rightLayer){
			var label = $('.swipe-label');
			if (!label.length){
				label = $('<table class="swipe-label"><tbody><tr></tr></tbody></table>');
				$(this.map.getTarget()).append(label);
				label.find('tr').html('<td>' + this.leftLayer.get('name') + '</td><td>' + this.rightLayer.get('name') + '</td>').fadeIn();
				setTimeout(function(){
					label.fadeOut();
				}, 4000);
			}
			if (label.css('display') != 'none'){
				label.css({left: pixel[0] - label.width()/2 + 'px', top: pixel[1] - label.height() + 'px'});
			}
		}
	}
};

nyc.inherits(nyc.ol.control.LayerSwipe, nyc.ol.control.LayerPicker);

/**
 * @private
 * @const
 * @type {string}
 */
nyc.ol.control.LayerSwipe.BUTTON_HTML = '<a class="btn-swipe ctl ctl-btn" data-role="button" data-icon="none" data-iconpos="notext" title="Layer swipe">Layer swipe</a>';

/**
 * @private
 * @const
 * @type {string}
 */
nyc.ol.control.LayerSwipe.MENU_BUTTONS_HTML = '<div class="swipe-btns"><a class="btn-cancel" data-role="button">Cancel</a><a class="btn-ok" data-role="button">OK</a></div>';