+ // @option sticky: Boolean = false
+ // If true, the tooltip will follow the mouse instead of being fixed at the feature center.
+ sticky: false,
+
+ // @option interactive: Boolean = false
+ // If true, the tooltip will listen to the feature events.
+ interactive: false,
+
+ // @option opacity: Number = 0.9
+ // Tooltip container opacity.
+ opacity: 0.9
+ },
+
+ onAdd: function (map) {
+ DivOverlay.prototype.onAdd.call(this, map);
+ this.setOpacity(this.options.opacity);
+
+ // @namespace Map
+ // @section Tooltip events
+ // @event tooltipopen: TooltipEvent
+ // Fired when a tooltip is opened in the map.
+ map.fire('tooltipopen', {tooltip: this});
+
+ if (this._source) {
+ // @namespace Layer
+ // @section Tooltip events
+ // @event tooltipopen: TooltipEvent
+ // Fired when a tooltip bound to this layer is opened.
+ this._source.fire('tooltipopen', {tooltip: this}, true);
+ }
+ },
+
+ onRemove: function (map) {
+ DivOverlay.prototype.onRemove.call(this, map);
+
+ // @namespace Map
+ // @section Tooltip events
+ // @event tooltipclose: TooltipEvent
+ // Fired when a tooltip in the map is closed.
+ map.fire('tooltipclose', {tooltip: this});
+
+ if (this._source) {
+ // @namespace Layer
+ // @section Tooltip events
+ // @event tooltipclose: TooltipEvent
+ // Fired when a tooltip bound to this layer is closed.
+ this._source.fire('tooltipclose', {tooltip: this}, true);
+ }
+ },
+
+ getEvents: function () {
+ var events = DivOverlay.prototype.getEvents.call(this);
+
+ if (touch && !this.options.permanent) {
+ events.preclick = this._close;
+ }
+
+ return events;
+ },
+
+ _close: function () {
+ if (this._map) {
+ this._map.closeTooltip(this);
+ }
+ },
+
+ _initLayout: function () {
+ var prefix = 'leaflet-tooltip',
+ className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');
+
+ this._contentNode = this._container = create$1('div', className);
+ },
+
+ _updateLayout: function () {},
+
+ _adjustPan: function () {},
+
+ _setPosition: function (pos) {
+ var map = this._map,
+ container = this._container,
+ centerPoint = map.latLngToContainerPoint(map.getCenter()),
+ tooltipPoint = map.layerPointToContainerPoint(pos),
+ direction = this.options.direction,
+ tooltipWidth = container.offsetWidth,
+ tooltipHeight = container.offsetHeight,
+ offset = toPoint(this.options.offset),
+ anchor = this._getAnchor();
+
+ if (direction === 'top') {
+ pos = pos.add(toPoint(-tooltipWidth / 2 + offset.x, -tooltipHeight + offset.y + anchor.y, true));
+ } else if (direction === 'bottom') {
+ pos = pos.subtract(toPoint(tooltipWidth / 2 - offset.x, -offset.y, true));
+ } else if (direction === 'center') {
+ pos = pos.subtract(toPoint(tooltipWidth / 2 + offset.x, tooltipHeight / 2 - anchor.y + offset.y, true));
+ } else if (direction === 'right' || direction === 'auto' && tooltipPoint.x < centerPoint.x) {
+ direction = 'right';
+ pos = pos.add(toPoint(offset.x + anchor.x, anchor.y - tooltipHeight / 2 + offset.y, true));
+ } else {
+ direction = 'left';
+ pos = pos.subtract(toPoint(tooltipWidth + anchor.x - offset.x, tooltipHeight / 2 - anchor.y - offset.y, true));
+ }
+
+ removeClass(container, 'leaflet-tooltip-right');
+ removeClass(container, 'leaflet-tooltip-left');
+ removeClass(container, 'leaflet-tooltip-top');
+ removeClass(container, 'leaflet-tooltip-bottom');
+ addClass(container, 'leaflet-tooltip-' + direction);
+ setPosition(container, pos);
+ },
+
+ _updatePosition: function () {
+ var pos = this._map.latLngToLayerPoint(this._latlng);
+ this._setPosition(pos);
+ },
+
+ setOpacity: function (opacity) {
+ this.options.opacity = opacity;
+
+ if (this._container) {
+ setOpacity(this._container, opacity);
+ }
+ },
+
+ _animateZoom: function (e) {
+ var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
+ this._setPosition(pos);
+ },
+
+ _getAnchor: function () {
+ // Where should we anchor the tooltip on the source layer?
+ return toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
+ }
+
+});
+
+// @namespace Tooltip
+// @factory L.tooltip(options?: Tooltip options, source?: Layer)
+// Instantiates a Tooltip object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers.
+var tooltip = function (options, source) {
+ return new Tooltip(options, source);
+};
+
+// @namespace Map
+// @section Methods for Layers and Controls
+Map.include({
+
+ // @method openTooltip(tooltip: Tooltip): this
+ // Opens the specified tooltip.
+ // @alternative
+ // @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this
+ // Creates a tooltip with the specified content and options and open it.
+ openTooltip: function (tooltip, latlng, options) {
+ if (!(tooltip instanceof Tooltip)) {
+ tooltip = new Tooltip(options).setContent(tooltip);
+ }
+
+ if (latlng) {
+ tooltip.setLatLng(latlng);
+ }
+
+ if (this.hasLayer(tooltip)) {
+ return this;
+ }
+
+ return this.addLayer(tooltip);
+ },
+
+ // @method closeTooltip(tooltip?: Tooltip): this
+ // Closes the tooltip given as parameter.
+ closeTooltip: function (tooltip) {
+ if (tooltip) {
+ this.removeLayer(tooltip);
+ }
+ return this;
+ }
+
+});
+
+/*
+ * @namespace Layer
+ * @section Tooltip methods example
+ *
+ * All layers share a set of methods convenient for binding tooltips to it.
+ *
+ * ```js
+ * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
+ * layer.openTooltip();
+ * layer.closeTooltip();
+ * ```
+ */
+
+// @section Tooltip methods
+Layer.include({
+
+ // @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this
+ // Binds a tooltip to the layer with the passed `content` and sets up the
+ // necessary event listeners. If a `Function` is passed it will receive
+ // the layer as the first argument and should return a `String` or `HTMLElement`.
+ bindTooltip: function (content, options) {
+
+ if (content instanceof Tooltip) {
+ setOptions(content, options);
+ this._tooltip = content;
+ content._source = this;
+ } else {
+ if (!this._tooltip || options) {
+ this._tooltip = new Tooltip(options, this);