4cb14e3c0e77ddee4606a2b41a1727080e732024
[mediagoblin.git] / extlib / leaflet / src / layer / Popup.js
1
2 L.Popup = L.Class.extend({
3 includes: L.Mixin.Events,
4
5 options: {
6 maxWidth: 300,
7 autoPan: true,
8 closeButton: true,
9
10 offset: new L.Point(0, 2),
11 autoPanPadding: new L.Point(5, 5)
12 },
13
14 initialize: function(options) {
15 L.Util.setOptions(this, options);
16 },
17
18 onAdd: function(map) {
19 this._map = map;
20 if (!this._container) {
21 this._initLayout();
22 }
23 this._updateContent();
24
25 this._container.style.opacity = '0';
26
27 this._map._panes.popupPane.appendChild(this._container);
28 this._map.on('viewreset', this._updatePosition, this);
29 if (this._map.options.closePopupOnClick) {
30 this._map.on('preclick', this._close, this);
31 }
32 this._update();
33
34 this._container.style.opacity = '1'; //TODO fix ugly opacity hack
35
36 this._opened = true;
37 },
38
39 onRemove: function(map) {
40 map._panes.popupPane.removeChild(this._container);
41 map.off('viewreset', this._updatePosition, this);
42 map.off('click', this._close, this);
43
44 this._container.style.opacity = '0';
45
46 this._opened = false;
47 },
48
49 setLatLng: function(latlng) {
50 this._latlng = latlng;
51 if (this._opened) {
52 this._update();
53 }
54 return this;
55 },
56
57 setContent: function(content) {
58 this._content = content;
59 if (this._opened) {
60 this._update();
61 }
62 return this;
63 },
64
65 _close: function() {
66 if (this._opened) {
67 this._map.removeLayer(this);
68 }
69 },
70
71 _initLayout: function() {
72 this._container = L.DomUtil.create('div', 'leaflet-popup');
73
74 this._closeButton = L.DomUtil.create('a', 'leaflet-popup-close-button', this._container);
75 this._closeButton.href = '#close';
76 this._closeButton.onclick = L.Util.bind(this._onCloseButtonClick, this);
77
78 this._wrapper = L.DomUtil.create('div', 'leaflet-popup-content-wrapper', this._container);
79 L.DomEvent.disableClickPropagation(this._wrapper);
80 this._contentNode = L.DomUtil.create('div', 'leaflet-popup-content', this._wrapper);
81
82 this._tipContainer = L.DomUtil.create('div', 'leaflet-popup-tip-container', this._container);
83 this._tip = L.DomUtil.create('div', 'leaflet-popup-tip', this._tipContainer);
84 },
85
86 _update: function() {
87 this._container.style.visibility = 'hidden';
88
89 this._updateContent();
90 this._updateLayout();
91 this._updatePosition();
92
93 this._container.style.visibility = '';
94
95 this._adjustPan();
96 },
97
98 _updateContent: function() {
99 if (!this._content) return;
100
101 if (typeof this._content == 'string') {
102 this._contentNode.innerHTML = this._content;
103 } else {
104 this._contentNode.innerHTML = '';
105 this._contentNode.appendChild(this._content);
106 }
107 },
108
109 _updateLayout: function() {
110 this._container.style.width = '';
111 this._container.style.whiteSpace = 'nowrap';
112
113 var width = this._container.offsetWidth;
114
115 this._container.style.width = (width > this.options.maxWidth ? this.options.maxWidth : width) + 'px';
116 this._container.style.whiteSpace = '';
117
118 this._containerWidth = this._container.offsetWidth;
119 },
120
121 _updatePosition: function() {
122 var pos = this._map.latLngToLayerPoint(this._latlng);
123
124 this._containerBottom = -pos.y - this.options.offset.y;
125 this._containerLeft = pos.x - Math.round(this._containerWidth/2) + this.options.offset.x;
126
127 this._container.style.bottom = this._containerBottom + 'px';
128 this._container.style.left = this._containerLeft + 'px';
129 },
130
131 _adjustPan: function() {
132 if (!this.options.autoPan) { return; }
133
134 var containerHeight = this._container.offsetHeight,
135 layerPos = new L.Point(
136 this._containerLeft,
137 -containerHeight - this._containerBottom),
138 containerPos = this._map.layerPointToContainerPoint(layerPos),
139 adjustOffset = new L.Point(0, 0),
140 padding = this.options.autoPanPadding,
141 size = this._map.getSize();
142
143 if (containerPos.x < 0) {
144 adjustOffset.x = containerPos.x - padding.x;
145 }
146 if (containerPos.x + this._containerWidth > size.x) {
147 adjustOffset.x = containerPos.x + this._containerWidth - size.x + padding.x;
148 }
149 if (containerPos.y < 0) {
150 adjustOffset.y = containerPos.y - padding.y;
151 }
152 if (containerPos.y + containerHeight > size.y) {
153 adjustOffset.y = containerPos.y + containerHeight - size.y + padding.y;
154 }
155
156 if (adjustOffset.x || adjustOffset.y) {
157 this._map.panBy(adjustOffset);
158 }
159 },
160
161 _onCloseButtonClick: function(e) {
162 this._close();
163 L.DomEvent.stop(e);
164 }
165 });