aboutsummaryrefslogtreecommitdiffstats
path: root/extlib/leaflet/src/layer/Popup.js
blob: 4cb14e3c0e77ddee4606a2b41a1727080e732024 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
L.Popup = L.Class.extend({
	includes: L.Mixin.Events,
	
	options: {
		maxWidth: 300,
		autoPan: true,
		closeButton: true,
		
		offset: new L.Point(0, 2),
		autoPanPadding: new L.Point(5, 5)
	},
	
	initialize: function(options) {
		L.Util.setOptions(this, options);
	},
	
	onAdd: function(map) {
		this._map = map;
		if (!this._container) {
			this._initLayout();
		}
		this._updateContent();
		
		this._container.style.opacity = '0';

		this._map._panes.popupPane.appendChild(this._container);
		this._map.on('viewreset', this._updatePosition, this);
		if (this._map.options.closePopupOnClick) {
			this._map.on('preclick', this._close, this);
		}
		this._update();
		
		this._container.style.opacity = '1'; //TODO fix ugly opacity hack
		
		this._opened = true;
	},
	
	onRemove: function(map) {
		map._panes.popupPane.removeChild(this._container);
		map.off('viewreset', this._updatePosition, this);
		map.off('click', this._close, this);

		this._container.style.opacity = '0';
		
		this._opened = false;
	},
	
	setLatLng: function(latlng) {
		this._latlng = latlng;
		if (this._opened) {
			this._update();
		}
		return this;
	},
	
	setContent: function(content) {
		this._content = content;
		if (this._opened) {
			this._update();
		}
		return this;
	},
	
	_close: function() {
		if (this._opened) {
			this._map.removeLayer(this);
		}
	},
	
	_initLayout: function() {
		this._container = L.DomUtil.create('div', 'leaflet-popup');
		
		this._closeButton = L.DomUtil.create('a', 'leaflet-popup-close-button', this._container);
		this._closeButton.href = '#close';
		this._closeButton.onclick = L.Util.bind(this._onCloseButtonClick, this);
		
		this._wrapper = L.DomUtil.create('div', 'leaflet-popup-content-wrapper', this._container);
		L.DomEvent.disableClickPropagation(this._wrapper);
		this._contentNode = L.DomUtil.create('div', 'leaflet-popup-content', this._wrapper);
		
		this._tipContainer = L.DomUtil.create('div', 'leaflet-popup-tip-container', this._container);
		this._tip = L.DomUtil.create('div', 'leaflet-popup-tip', this._tipContainer);
	},
	
	_update: function() {
		this._container.style.visibility = 'hidden';
		
		this._updateContent();
		this._updateLayout();
		this._updatePosition();
		
		this._container.style.visibility = '';

		this._adjustPan();
	},
	
	_updateContent: function() {
		if (!this._content) return;
		
		if (typeof this._content == 'string') {
			this._contentNode.innerHTML = this._content;
		} else {
			this._contentNode.innerHTML = '';
			this._contentNode.appendChild(this._content);
		}
	},
	
	_updateLayout: function() {
		this._container.style.width = '';
		this._container.style.whiteSpace = 'nowrap';

		var width = this._container.offsetWidth;
		
		this._container.style.width = (width > this.options.maxWidth ? this.options.maxWidth : width) + 'px';
		this._container.style.whiteSpace = '';
		
		this._containerWidth = this._container.offsetWidth;
	},
	
	_updatePosition: function() {
		var pos = this._map.latLngToLayerPoint(this._latlng);
		
		this._containerBottom = -pos.y - this.options.offset.y;
		this._containerLeft = pos.x - Math.round(this._containerWidth/2) + this.options.offset.x;
		
		this._container.style.bottom = this._containerBottom + 'px';
		this._container.style.left = this._containerLeft + 'px';
	},
	
	_adjustPan: function() {
		if (!this.options.autoPan) { return; }
		
		var containerHeight = this._container.offsetHeight,
			layerPos = new L.Point(
				this._containerLeft, 
				-containerHeight - this._containerBottom),
			containerPos = this._map.layerPointToContainerPoint(layerPos),
			adjustOffset = new L.Point(0, 0),
			padding = this.options.autoPanPadding,
			size = this._map.getSize();
		
		if (containerPos.x < 0) {
			adjustOffset.x = containerPos.x - padding.x;
		}
		if (containerPos.x + this._containerWidth > size.x) {
			adjustOffset.x = containerPos.x + this._containerWidth - size.x + padding.x;
		}
		if (containerPos.y < 0) {
			adjustOffset.y = containerPos.y - padding.y;
		}
		if (containerPos.y + containerHeight > size.y) {
			adjustOffset.y = containerPos.y + containerHeight - size.y + padding.y;
		}
		
		if (adjustOffset.x || adjustOffset.y) {
			this._map.panBy(adjustOffset);
		}
	},
	
	_onCloseButtonClick: function(e) {
		this._close();
		L.DomEvent.stop(e);
	}
});