2012-01-25 23:42:04 +01:00

165 lines
4.3 KiB
JavaScript

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);
}
});