maptoolkit
Version:
Utilidades para trabajar con el mapa de google web.
1,690 lines (1,434 loc) • 368 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("MapTk", [], factory);
else if(typeof exports === 'object')
exports["MapTk"] = factory();
else
root["MapTk"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MtEventSource; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_ts_eventemitter__ = __webpack_require__(4);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_ts_eventemitter___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_ts_eventemitter__);
var MtEventSource = (function () {
function MtEventSource() {
this.eventDispatcher = __WEBPACK_IMPORTED_MODULE_0_ts_eventemitter___default.a.create();
}
MtEventSource.prototype.event = function (name) {
return this.eventDispatcher.event(name);
};
MtEventSource.prototype.removeAllListeners = function () {
this.eventDispatcher.removeAllListeners();
};
MtEventSource.prototype.setMaxListeners = function (n) {
this.eventDispatcher.setMaxListeners(n);
};
return MtEventSource;
}());
MtEventSource.EVT_MAP_IDLE = "onMapIdle";
MtEventSource.EVT_MAP_CLICK = "onMapClick";
MtEventSource.EVT_MAP_ZOOM_CHANGED = "onZoomChanged";
MtEventSource.EVT_MAP_MARKER_CLICK = "onMarkerClick";
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__maptoolkit__ = __webpack_require__(2);
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MapToolkit", function() { return __WEBPACK_IMPORTED_MODULE_0__maptoolkit__["a"]; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__mtmarker__ = __webpack_require__(8);
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MtMarker", function() { return __WEBPACK_IMPORTED_MODULE_1__mtmarker__["a"]; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__mteventsource__ = __webpack_require__(0);
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MtEventSource", function() { return __WEBPACK_IMPORTED_MODULE_2__mteventsource__["a"]; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math__ = __webpack_require__(9);
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MapMath", function() { return __WEBPACK_IMPORTED_MODULE_3__math__["a"]; });
/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MapToolkit; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_js_info_bubble__ = __webpack_require__(3);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_js_info_bubble___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_js_info_bubble__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__mteventsource__ = __webpack_require__(0);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__mkcollection__ = __webpack_require__(6);
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var _noop = function () {
};
var _defRouteOptions = {
travelMode: 'TRANSIT',
strokeColor: 'pink',
strokeOpacity: 1,
strokeWeight: 6
};
var _defBubbleInfoOptions = {
content: '',
position: null,
shadowStyle: 1,
padding: 0,
backgroundColor: "#fff",
borderRadius: 2,
arrowSize: 0,
borderWidth: 1,
borderColor: "#f3f3f3",
disableAutoPan: false,
hideCloseButton: false,
arrowPosition: 50,
backgroundClassName: '',
minWidth: 300,
minHeight: 50,
arrowStyle: 0,
};
var MapToolkit = (function (_super) {
__extends(MapToolkit, _super);
function MapToolkit(nativeMap, _options) {
var _this = _super.call(this) || this;
_this.nativeMap = nativeMap;
_this._bubbleMarkup = "<div>{{name}}</div>";
var self = _this;
_this._options = _options || {};
google.maps.event.addListener(self.nativeMap, 'idle', function () {
self.event(MapToolkit.EVT_MAP_IDLE).emit({ source: self, evt: {} });
});
google.maps.event.addListener(self.nativeMap, 'click', function (event) {
self.event(MapToolkit.EVT_MAP_CLICK).emit({ source: self, evt: event });
});
google.maps.event.addListener(self.nativeMap, "zoom_changed", function () {
self.event(MapToolkit.EVT_MAP_ZOOM_CHANGED).emit({ source: self, evt: {} });
if (self._markerSelected) {
self._ubicarInfoBubble(self.nativeMap.getZoom(), self._markerSelected);
}
});
_this._markerGroupCollection = new __WEBPACK_IMPORTED_MODULE_2__mkcollection__["a" /* MtMarkerGroupCollection */]();
return _this;
}
MapToolkit.prototype.option = function (name, defValue) {
return this._options[name] != void 0 ? this._options[name] : defValue;
};
MapToolkit.prototype.getSelectedMarker = function () {
return this._markerSelected;
};
MapToolkit.prototype.addMarker = function (marker, group) {
if (marker) {
this.addAllMarkers([marker], group);
}
return this;
};
MapToolkit.prototype.addAllMarkers = function (markers, group) {
var _this = this;
if (markers && markers.length) {
this._markerGroupCollection.addAllMarkers(markers, group).forEach(function (mk) {
mk.event(MapToolkit.EVT_MAP_MARKER_CLICK).addListener(function (args) {
_this._markerSelected = args.source;
_this.event(MapToolkit.EVT_MAP_MARKER_CLICK).emit({
source: _this,
marker: args.source,
evt: args.evt
});
});
if (_this.option("markerIconSelector")) {
mk.setIcon(_this.option("markerIconSelector")(mk.model));
}
mk.show(_this.nativeMap);
});
}
return this;
};
MapToolkit.prototype.setMarker = function (marker, group) {
this.setAllMarkers([marker], group);
};
/**
* Elimina los markers que no estan mostrandose y adiciona los nuevos.
* @param markers
* @param group
*/
MapToolkit.prototype.setAllMarkers = function (markers, group) {
if (markers && markers.length) {
var toRemove = [], toUpdate = [], toAdd = [];
var currMarkers = this._markerGroupCollection.getGroup(group);
var setMkIds = {};
//busco los markers que no estan en el mapa y los pongo para adicionar
//ademas hago un map de los ids para luego verificar los q no estan en currMarkers y eliminarlos
markers.forEach(function (m) {
setMkIds[m.getId()] = true;
if (!currMarkers.containsKey(m.getId())) {
toAdd.push(m);
}
else {
toUpdate.push(m);
}
});
currMarkers.forEach(function (id, mk) {
if (!setMkIds[mk.getId()]) {
toRemove.push(mk);
}
});
//actualizo los markers
toUpdate.forEach(function (m) {
var actualMk = currMarkers.getValue(m.getId());
actualMk.setPosition(m.getPosition());
actualMk.setModel(m.model);
});
//elimino los que no estan en markers
this.removeAllMarkers(toRemove, group);
//adiciono los que no estan en currMarkers
this.addAllMarkers(toAdd, group);
}
return this;
};
MapToolkit.prototype.removeMarker = function (id, group) {
var mk = this._markerGroupCollection.removeMarker(id, group);
if (mk) {
mk.remove();
return mk;
}
};
MapToolkit.prototype.removeAllMarkers = function (markers, group) {
if (markers && markers.length) {
this._markerGroupCollection.removeMarkers(markers, group).forEach(function (m) {
m.remove();
});
}
};
MapToolkit.prototype.removeGroup = function (group) {
var markers = this._markerGroupCollection.removeGroup(group);
if (markers) {
markers.forEach(function (mk) {
mk.remove();
});
}
};
MapToolkit.prototype.centerMapToMarkers = function () {
var markers = this._markerGroupCollection.toArray();
if (markers.length > 0) {
var latMin = markers[0].getPosition().lat(), latMax = markers[0].getPosition().lat(), lngMin = markers[0].getPosition().lng(), lngMax = markers[0].getPosition().lng();
var i;
for (i = 1; i < markers.length; i++) {
latMin = markers[i].getPosition().lat() < latMin ? markers[i].getPosition().lat() : latMin;
latMax = markers[i].getPosition().lat() > latMax ? markers[i].getPosition().lat() : latMax;
lngMin = markers[i].getPosition().lng() < lngMin ? markers[i].getPosition().lng() : lngMin;
lngMax = markers[i].getPosition().lng() > lngMax ? markers[i].getPosition().lng() : lngMax;
}
var mediaLat = (latMin + latMax) / 2, mediaLng = (lngMin + lngMax) / 2;
//busco el rig mas cercano a la media
var markerMiddle = markers[0];
var difCentro = Math.abs(Math.abs(markerMiddle.getPosition().lat()) - Math.abs(mediaLat)) +
Math.abs(Math.abs(markerMiddle.getPosition().lng() - Math.abs(mediaLng)));
for (i = 1; i < markers.length; i++) {
var difRig = Math.abs(Math.abs(markers[i].getPosition().lat()) - Math.abs(mediaLat)) +
Math.abs(Math.abs(markers[i].getPosition().lng()) - Math.abs(mediaLng));
if (difRig < difCentro) {
markerMiddle = markers[i];
difCentro = difRig;
}
}
this.centerMap(markerMiddle.getPosition(), 5);
}
};
MapToolkit.prototype.centerMap = function (pos, zoom) {
if (typeof (pos) == "string") {
var vals = pos.split(",");
pos = new google.maps.LatLng(parseFloat(vals[0]), parseFloat(vals[1]));
}
this.nativeMap.setCenter(pos);
this.nativeMap.setZoom(zoom);
};
MapToolkit.prototype.centerAndZoomToMarkers = function (positions) {
positions = positions || this._markerGroupCollection.toArray().map(function (mk) {
return mk.getPosition();
});
var latlngbounds = new google.maps.LatLngBounds();
for (var i = 0; i < positions.length; i++) {
latlngbounds.extend(new google.maps.LatLng(positions[i].lat(), positions[i].lng()));
}
var zprev = this.nativeMap.getZoom();
this.nativeMap.fitBounds(latlngbounds);
this.nativeMap.setZoom(zprev);
};
MapToolkit.prototype.getZoom = function () {
return this.nativeMap.getZoom();
};
MapToolkit.prototype.getCenter = function () {
return this.nativeMap.getCenter();
};
MapToolkit.prototype.getBounds = function () {
return this.nativeMap.getBounds();
};
MapToolkit.prototype.paintCircle = function (radio, center, circleOpts, clickListener) {
var self = this;
if (self._radioSearchPaint)
self._radioSearchPaint.setMap(null);
// Add the circle for this city to the map.
self._radioSearchPaint = new google.maps.Circle(circleOpts);
if (clickListener)
google.maps.event.addListener(self._radioSearchPaint, 'click', function (event) {
clickListener(event);
});
return self._radioSearchPaint;
};
MapToolkit.prototype.showInfoBubble = function (options) {
options = Object.assign({}, _defBubbleInfoOptions, options, {
map: this.nativeMap,
position: this._getInfoBubblePositionForMarkerPosition(this.nativeMap.getZoom(), options.position)
});
this.closeInfoBubble();
var infoBubble = new __WEBPACK_IMPORTED_MODULE_0_js_info_bubble__["InfoBubble"](options);
infoBubble.open();
this._infoBubbleOpened = infoBubble;
};
MapToolkit.prototype.closeInfoBubble = function () {
this._infoBubbleOpened && this._infoBubbleOpened.close();
};
MapToolkit.prototype.showRoute = function (start, end, options) {
var self = this;
options = Object.assign({}, _defRouteOptions, options);
return new Promise(function (resolve, reject) {
var request = {
origin: start,
destination: end,
travelMode: options.travelMode
};
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer({
polylineOptions: { strokeColor: options.strokeColor },
suppressMarkers: true
});
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
directionsDisplay.setMap(self.nativeMap);
self._routeDrawed = directionsDisplay;
resolve(self._routeDrawed);
}
else {
reject({ response: response, status: status });
}
});
});
};
MapToolkit.prototype.clearRoute = function () {
if (this._routeDrawed) {
this._routeDrawed.setMap(null);
this._routeDrawed = null;
}
};
MapToolkit.prototype._getInfoBubblePositionForMarkerPosition = function (zoom, pos) {
var newLat = pos.lat() + (0.00004 * Math.pow(2, (19 - zoom)));
return new google.maps.LatLng(newLat, pos.lng());
};
MapToolkit.prototype._ubicarInfoBubble = function (zoom, marker) {
if (this._infoBubbleOpened) {
//position infoBubble for each zoom level change, based on arithmetic logic (notice the power of 2)
this._infoBubbleOpened.setPosition(this._getInfoBubblePositionForMarkerPosition(zoom, marker.getPosition()));
}
};
return MapToolkit;
}(__WEBPACK_IMPORTED_MODULE_1__mteventsource__["a" /* MtEventSource */]));
/***/ }),
/* 3 */
/***/ (function(module, exports) {
// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @externs_url https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/maps/google_maps_api_v3_16.js
// ==/ClosureCompiler==
/**
* @name CSS3 InfoBubble with tabs for Google Maps API V3
* @version 0.8
* @author Luke Mahe
* @fileoverview
* This library is a CSS Infobubble with tabs. It uses css3 rounded corners and
* drop shadows and animations. It also allows tabs
*/
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* A CSS3 InfoBubble v0.8
* @param {Object.<string, *>=} opt_options Optional properties to set.
* @extends {google.maps.OverlayView}
* @constructor
*/
function InfoBubble(opt_options) {
this.extend(InfoBubble, google.maps.OverlayView);
this.tabs_ = [];
this.activeTab_ = null;
this.baseZIndex_ = 100;
this.isOpen_ = false;
var options = opt_options || {};
if (options['backgroundColor'] == undefined) {
options['backgroundColor'] = this.BACKGROUND_COLOR_;
}
if (options['borderColor'] == undefined) {
options['borderColor'] = this.BORDER_COLOR_;
}
if (options['borderRadius'] == undefined) {
options['borderRadius'] = this.BORDER_RADIUS_;
}
if (options['borderWidth'] == undefined) {
options['borderWidth'] = this.BORDER_WIDTH_;
}
if (options['padding'] == undefined) {
options['padding'] = this.PADDING_;
}
if (options['arrowPosition'] == undefined) {
options['arrowPosition'] = this.ARROW_POSITION_;
}
if (options['disableAutoPan'] == undefined) {
options['disableAutoPan'] = false;
}
if (options['disableAnimation'] == undefined) {
options['disableAnimation'] = false;
}
if (options['minWidth'] == undefined) {
options['minWidth'] = this.MIN_WIDTH_;
}
if (options['shadowStyle'] == undefined) {
options['shadowStyle'] = this.SHADOW_STYLE_;
}
if (options['arrowSize'] == undefined) {
options['arrowSize'] = this.ARROW_SIZE_;
}
if (options['arrowStyle'] == undefined) {
options['arrowStyle'] = this.ARROW_STYLE_;
}
if (options['closeSrc'] == undefined) {
options['closeSrc'] = this.CLOSE_SRC_;
}
this.buildDom_();
this.setValues(options);
}
window['InfoBubble'] = InfoBubble;
/**
* Default arrow size
* @const
* @private
*/
InfoBubble.prototype.ARROW_SIZE_ = 15;
/**
* Default arrow style
* @const
* @private
*/
InfoBubble.prototype.ARROW_STYLE_ = 0;
/**
* Default shadow style
* @const
* @private
*/
InfoBubble.prototype.SHADOW_STYLE_ = 1;
/**
* Default min width
* @const
* @private
*/
InfoBubble.prototype.MIN_WIDTH_ = 50;
/**
* Default arrow position
* @const
* @private
*/
InfoBubble.prototype.ARROW_POSITION_ = 50;
/**
* Default padding
* @const
* @private
*/
InfoBubble.prototype.PADDING_ = 10;
/**
* Default border width
* @const
* @private
*/
InfoBubble.prototype.BORDER_WIDTH_ = 1;
/**
* Default border color
* @const
* @private
*/
InfoBubble.prototype.BORDER_COLOR_ = '#ccc';
/**
* Default border radius
* @const
* @private
*/
InfoBubble.prototype.BORDER_RADIUS_ = 10;
/**
* Default background color
* @const
* @private
*/
InfoBubble.prototype.BACKGROUND_COLOR_ = '#fff';
/**
* Default close image source
* @const
* @private
*/
InfoBubble.prototype.CLOSE_SRC_ = 'https://maps.gstatic.com/intl/en_us/mapfiles/iw_close.gif';
/**
* Extends a objects prototype by anothers.
*
* @param {Object} obj1 The object to be extended.
* @param {Object} obj2 The object to extend with.
* @return {Object} The new extended object.
* @ignore
*/
InfoBubble.prototype.extend = function(obj1, obj2) {
return (function(object) {
for (var property in object.prototype) {
this.prototype[property] = object.prototype[property];
}
return this;
}).apply(obj1, [obj2]);
};
/**
* Builds the InfoBubble dom
* @private
*/
InfoBubble.prototype.buildDom_ = function() {
var bubble = this.bubble_ = document.createElement('DIV');
bubble.style['position'] = 'absolute';
bubble.style['zIndex'] = this.baseZIndex_;
var tabsContainer = this.tabsContainer_ = document.createElement('DIV');
tabsContainer.style['position'] = 'relative';
// Close button
var close = this.close_ = document.createElement('IMG');
close.style['position'] = 'absolute';
close.style['border'] = 0;
close.style['zIndex'] = this.baseZIndex_ + 1;
close.style['cursor'] = 'pointer';
close.src = this.get('closeSrc');
var that = this;
google.maps.event.addDomListener(close, 'click', function() {
that.close();
google.maps.event.trigger(that, 'closeclick');
});
// Content area
var contentContainer = this.contentContainer_ = document.createElement('DIV');
contentContainer.style['overflowX'] = 'auto';
contentContainer.style['overflowY'] = 'auto';
contentContainer.style['cursor'] = 'default';
contentContainer.style['clear'] = 'both';
contentContainer.style['position'] = 'relative';
var content = this.content_ = document.createElement('DIV');
contentContainer.appendChild(content);
// Arrow
var arrow = this.arrow_ = document.createElement('DIV');
arrow.style['position'] = 'relative';
var arrowOuter = this.arrowOuter_ = document.createElement('DIV');
var arrowInner = this.arrowInner_ = document.createElement('DIV');
var arrowSize = this.getArrowSize_();
arrowOuter.style['position'] = arrowInner.style['position'] = 'absolute';
arrowOuter.style['left'] = arrowInner.style['left'] = '50%';
arrowOuter.style['height'] = arrowInner.style['height'] = '0';
arrowOuter.style['width'] = arrowInner.style['width'] = '0';
arrowOuter.style['marginLeft'] = this.px(-arrowSize);
arrowOuter.style['borderWidth'] = this.px(arrowSize);
arrowOuter.style['borderBottomWidth'] = 0;
// Shadow
var bubbleShadow = this.bubbleShadow_ = document.createElement('DIV');
bubbleShadow.style['position'] = 'absolute';
// Hide the InfoBubble by default
bubble.style['display'] = bubbleShadow.style['display'] = 'none';
bubble.appendChild(this.tabsContainer_);
bubble.appendChild(close);
bubble.appendChild(contentContainer);
arrow.appendChild(arrowOuter);
arrow.appendChild(arrowInner);
bubble.appendChild(arrow);
var stylesheet = document.createElement('style');
stylesheet.setAttribute('type', 'text/css');
/**
* The animation for the infobubble
* @type {string}
*/
this.animationName_ = '_ibani_' + Math.round(Math.random() * 10000);
var css = '.' + this.animationName_ + '{-webkit-animation-name:' +
this.animationName_ + ';-webkit-animation-duration:0.5s;' +
'-webkit-animation-iteration-count:1;}' +
'@-webkit-keyframes ' + this.animationName_ + ' {from {' +
'-webkit-transform: scale(0)}50% {-webkit-transform: scale(1.2)}90% ' +
'{-webkit-transform: scale(0.95)}to {-webkit-transform: scale(1)}}';
stylesheet.textContent = css;
document.getElementsByTagName('head')[0].appendChild(stylesheet);
};
/**
* Sets the background class name
*
* @param {string} className The class name to set.
*/
InfoBubble.prototype.setBackgroundClassName = function(className) {
this.set('backgroundClassName', className);
};
InfoBubble.prototype['setBackgroundClassName'] = InfoBubble.prototype.setBackgroundClassName;
/**
* changed MVC callback
*/
InfoBubble.prototype.backgroundClassName_changed = function() {
this.content_.className = this.get('backgroundClassName');
};
InfoBubble.prototype['backgroundClassName_changed'] = InfoBubble.prototype.backgroundClassName_changed;
/**
* Sets the class of the tab
*
* @param {string} className the class name to set.
*/
InfoBubble.prototype.setTabClassName = function(className) {
this.set('tabClassName', className);
};
InfoBubble.prototype['setTabClassName'] = InfoBubble.prototype.setTabClassName;
/**
* tabClassName changed MVC callback
*/
InfoBubble.prototype.tabClassName_changed = function() {
this.updateTabStyles_();
};
InfoBubble.prototype['tabClassName_changed'] = InfoBubble.prototype.tabClassName_changed;
/**
* Gets the style of the arrow
*
* @private
* @return {number} The style of the arrow.
*/
InfoBubble.prototype.getArrowStyle_ = function() {
return parseInt(this.get('arrowStyle'), 10) || 0;
};
/**
* Sets the style of the arrow
*
* @param {number} style The style of the arrow.
*/
InfoBubble.prototype.setArrowStyle = function(style) {
this.set('arrowStyle', style);
};
InfoBubble.prototype['setArrowStyle'] = InfoBubble.prototype.setArrowStyle;
/**
* Arrow style changed MVC callback
*/
InfoBubble.prototype.arrowStyle_changed = function() {
this.arrowSize_changed();
};
InfoBubble.prototype['arrowStyle_changed'] = InfoBubble.prototype.arrowStyle_changed;
/**
* Gets the size of the arrow
*
* @private
* @return {number} The size of the arrow.
*/
InfoBubble.prototype.getArrowSize_ = function() {
return parseInt(this.get('arrowSize'), 10) || 0;
};
/**
* Sets the size of the arrow
*
* @param {number} size The size of the arrow.
*/
InfoBubble.prototype.setArrowSize = function(size) {
this.set('arrowSize', size);
};
InfoBubble.prototype['setArrowSize'] = InfoBubble.prototype.setArrowSize;
/**
* Arrow size changed MVC callback
*/
InfoBubble.prototype.arrowSize_changed = function() {
this.borderWidth_changed();
};
InfoBubble.prototype['arrowSize_changed'] = InfoBubble.prototype.arrowSize_changed;
/**
* Set the position of the InfoBubble arrow
*
* @param {number} pos The position to set.
*/
InfoBubble.prototype.setArrowPosition = function(pos) {
this.set('arrowPosition', pos);
};
InfoBubble.prototype['setArrowPosition'] = InfoBubble.prototype.setArrowPosition;
/**
* Get the position of the InfoBubble arrow
*
* @private
* @return {number} The position..
*/
InfoBubble.prototype.getArrowPosition_ = function() {
return parseInt(this.get('arrowPosition'), 10) || 0;
};
/**
* arrowPosition changed MVC callback
*/
InfoBubble.prototype.arrowPosition_changed = function() {
var pos = this.getArrowPosition_();
this.arrowOuter_.style['left'] = this.arrowInner_.style['left'] = pos + '%';
this.redraw_();
};
InfoBubble.prototype['arrowPosition_changed'] = InfoBubble.prototype.arrowPosition_changed;
/**
* Set the zIndex of the InfoBubble
*
* @param {number} zIndex The zIndex to set.
*/
InfoBubble.prototype.setZIndex = function(zIndex) {
this.set('zIndex', zIndex);
};
InfoBubble.prototype['setZIndex'] = InfoBubble.prototype.setZIndex;
/**
* Get the zIndex of the InfoBubble
*
* @return {number} The zIndex to set.
*/
InfoBubble.prototype.getZIndex = function() {
return parseInt(this.get('zIndex'), 10) || this.baseZIndex_;
};
/**
* zIndex changed MVC callback
*/
InfoBubble.prototype.zIndex_changed = function() {
var zIndex = this.getZIndex();
this.bubble_.style['zIndex'] = this.baseZIndex_ = zIndex;
this.close_.style['zIndex'] = zIndex + 1;
};
InfoBubble.prototype['zIndex_changed'] = InfoBubble.prototype.zIndex_changed;
/**
* Set the style of the shadow
*
* @param {number} shadowStyle The style of the shadow.
*/
InfoBubble.prototype.setShadowStyle = function(shadowStyle) {
this.set('shadowStyle', shadowStyle);
};
InfoBubble.prototype['setShadowStyle'] = InfoBubble.prototype.setShadowStyle;
/**
* Get the style of the shadow
*
* @private
* @return {number} The style of the shadow.
*/
InfoBubble.prototype.getShadowStyle_ = function() {
return parseInt(this.get('shadowStyle'), 10) || 0;
};
/**
* shadowStyle changed MVC callback
*/
InfoBubble.prototype.shadowStyle_changed = function() {
var shadowStyle = this.getShadowStyle_();
var display = '';
var shadow = '';
var backgroundColor = '';
switch (shadowStyle) {
case 0:
display = 'none';
break;
case 1:
shadow = '40px 15px 10px rgba(33,33,33,0.3)';
backgroundColor = 'transparent';
break;
case 2:
shadow = '0 0 2px rgba(33,33,33,0.3)';
backgroundColor = 'rgba(33,33,33,0.35)';
break;
}
this.bubbleShadow_.style['boxShadow'] =
this.bubbleShadow_.style['webkitBoxShadow'] =
this.bubbleShadow_.style['MozBoxShadow'] = shadow;
this.bubbleShadow_.style['backgroundColor'] = backgroundColor;
if (this.isOpen_) {
this.bubbleShadow_.style['display'] = display;
this.draw();
}
};
InfoBubble.prototype['shadowStyle_changed'] = InfoBubble.prototype.shadowStyle_changed;
/**
* Show the close button
*/
InfoBubble.prototype.showCloseButton = function() {
this.set('hideCloseButton', false);
};
InfoBubble.prototype['showCloseButton'] = InfoBubble.prototype.showCloseButton;
/**
* Hide the close button
*/
InfoBubble.prototype.hideCloseButton = function() {
this.set('hideCloseButton', true);
};
InfoBubble.prototype['hideCloseButton'] = InfoBubble.prototype.hideCloseButton;
/**
* hideCloseButton changed MVC callback
*/
InfoBubble.prototype.hideCloseButton_changed = function() {
this.close_.style['display'] = this.get('hideCloseButton') ? 'none' : '';
};
InfoBubble.prototype['hideCloseButton_changed'] = InfoBubble.prototype.hideCloseButton_changed;
/**
* Set the background color
*
* @param {string} color The color to set.
*/
InfoBubble.prototype.setBackgroundColor = function(color) {
if (color) {
this.set('backgroundColor', color);
}
};
InfoBubble.prototype['setBackgroundColor'] = InfoBubble.prototype.setBackgroundColor;
/**
* backgroundColor changed MVC callback
*/
InfoBubble.prototype.backgroundColor_changed = function() {
var backgroundColor = this.get('backgroundColor');
this.contentContainer_.style['backgroundColor'] = backgroundColor;
this.arrowInner_.style['borderColor'] = backgroundColor +
' transparent transparent';
this.updateTabStyles_();
};
InfoBubble.prototype['backgroundColor_changed'] = InfoBubble.prototype.backgroundColor_changed;
/**
* Set the border color
*
* @param {string} color The border color.
*/
InfoBubble.prototype.setBorderColor = function(color) {
if (color) {
this.set('borderColor', color);
}
};
InfoBubble.prototype['setBorderColor'] = InfoBubble.prototype.setBorderColor;
/**
* borderColor changed MVC callback
*/
InfoBubble.prototype.borderColor_changed = function() {
var borderColor = this.get('borderColor');
var contentContainer = this.contentContainer_;
var arrowOuter = this.arrowOuter_;
contentContainer.style['borderColor'] = borderColor;
arrowOuter.style['borderColor'] = borderColor +
' transparent transparent';
contentContainer.style['borderStyle'] =
arrowOuter.style['borderStyle'] =
this.arrowInner_.style['borderStyle'] = 'solid';
this.updateTabStyles_();
};
InfoBubble.prototype['borderColor_changed'] = InfoBubble.prototype.borderColor_changed;
/**
* Set the radius of the border
*
* @param {number} radius The radius of the border.
*/
InfoBubble.prototype.setBorderRadius = function(radius) {
this.set('borderRadius', radius);
};
InfoBubble.prototype['setBorderRadius'] = InfoBubble.prototype.setBorderRadius;
/**
* Get the radius of the border
*
* @private
* @return {number} The radius of the border.
*/
InfoBubble.prototype.getBorderRadius_ = function() {
return parseInt(this.get('borderRadius'), 10) || 0;
};
/**
* borderRadius changed MVC callback
*/
InfoBubble.prototype.borderRadius_changed = function() {
var borderRadius = this.getBorderRadius_();
var borderWidth = this.getBorderWidth_();
this.contentContainer_.style['borderRadius'] =
this.contentContainer_.style['MozBorderRadius'] =
this.contentContainer_.style['webkitBorderRadius'] =
this.bubbleShadow_.style['borderRadius'] =
this.bubbleShadow_.style['MozBorderRadius'] =
this.bubbleShadow_.style['webkitBorderRadius'] = this.px(borderRadius);
this.tabsContainer_.style['paddingLeft'] =
this.tabsContainer_.style['paddingRight'] =
this.px(borderRadius + borderWidth);
this.redraw_();
};
InfoBubble.prototype['borderRadius_changed'] = InfoBubble.prototype.borderRadius_changed;
/**
* Get the width of the border
*
* @private
* @return {number} width The width of the border.
*/
InfoBubble.prototype.getBorderWidth_ = function() {
return parseInt(this.get('borderWidth'), 10) || 0;
};
/**
* Set the width of the border
*
* @param {number} width The width of the border.
*/
InfoBubble.prototype.setBorderWidth = function(width) {
this.set('borderWidth', width);
};
InfoBubble.prototype['setBorderWidth'] = InfoBubble.prototype.setBorderWidth;
/**
* borderWidth change MVC callback
*/
InfoBubble.prototype.borderWidth_changed = function() {
var borderWidth = this.getBorderWidth_();
this.contentContainer_.style['borderWidth'] = this.px(borderWidth);
this.tabsContainer_.style['top'] = this.px(borderWidth);
this.updateArrowStyle_();
this.updateTabStyles_();
this.borderRadius_changed();
this.redraw_();
};
InfoBubble.prototype['borderWidth_changed'] = InfoBubble.prototype.borderWidth_changed;
/**
* Update the arrow style
* @private
*/
InfoBubble.prototype.updateArrowStyle_ = function() {
var borderWidth = this.getBorderWidth_();
var arrowSize = this.getArrowSize_();
var arrowStyle = this.getArrowStyle_();
var arrowOuterSizePx = this.px(arrowSize);
var arrowInnerSizePx = this.px(Math.max(0, arrowSize - borderWidth));
var outer = this.arrowOuter_;
var inner = this.arrowInner_;
this.arrow_.style['marginTop'] = this.px(-borderWidth);
outer.style['borderTopWidth'] = arrowOuterSizePx;
inner.style['borderTopWidth'] = arrowInnerSizePx;
// Full arrow or arrow pointing to the left
if (arrowStyle == 0 || arrowStyle == 1) {
outer.style['borderLeftWidth'] = arrowOuterSizePx;
inner.style['borderLeftWidth'] = arrowInnerSizePx;
} else {
outer.style['borderLeftWidth'] = inner.style['borderLeftWidth'] = 0;
}
// Full arrow or arrow pointing to the right
if (arrowStyle == 0 || arrowStyle == 2) {
outer.style['borderRightWidth'] = arrowOuterSizePx;
inner.style['borderRightWidth'] = arrowInnerSizePx;
} else {
outer.style['borderRightWidth'] = inner.style['borderRightWidth'] = 0;
}
if (arrowStyle < 2) {
outer.style['marginLeft'] = this.px(-(arrowSize));
inner.style['marginLeft'] = this.px(-(arrowSize - borderWidth));
} else {
outer.style['marginLeft'] = inner.style['marginLeft'] = 0;
}
// If there is no border then don't show thw outer arrow
if (borderWidth == 0) {
outer.style['display'] = 'none';
} else {
outer.style['display'] = '';
}
};
/**
* Set the padding of the InfoBubble
*
* @param {number} padding The padding to apply.
*/
InfoBubble.prototype.setPadding = function(padding) {
this.set('padding', padding);
};
InfoBubble.prototype['setPadding'] = InfoBubble.prototype.setPadding;
/**
* Set the close image url
*
* @param {string} src The url of the image used as a close icon
*/
InfoBubble.prototype.setCloseSrc = function(src) {
if (src && this.close_) {
this.close_.src = src;
}
};
InfoBubble.prototype['setCloseSrc'] = InfoBubble.prototype.setCloseSrc;
/**
* Set the padding of the InfoBubble
*
* @private
* @return {number} padding The padding to apply.
*/
InfoBubble.prototype.getPadding_ = function() {
return parseInt(this.get('padding'), 10) || 0;
};
/**
* padding changed MVC callback
*/
InfoBubble.prototype.padding_changed = function() {
var padding = this.getPadding_();
this.contentContainer_.style['padding'] = this.px(padding);
this.updateTabStyles_();
this.redraw_();
};
InfoBubble.prototype['padding_changed'] = InfoBubble.prototype.padding_changed;
/**
* Add px extention to the number
*
* @param {number} num The number to wrap.
* @return {string|number} A wrapped number.
*/
InfoBubble.prototype.px = function(num) {
if (num) {
// 0 doesn't need to be wrapped
return num + 'px';
}
return num;
};
/**
* Add events to stop propagation
* @private
*/
InfoBubble.prototype.addEvents_ = function() {
// We want to cancel all the events so they do not go to the map
var events = ['mousedown', 'mousemove', 'mouseover', 'mouseout', 'mouseup',
'mousewheel', 'DOMMouseScroll', 'touchstart', 'touchend', 'touchmove',
'dblclick', 'contextmenu', 'click'];
var bubble = this.bubble_;
this.listeners_ = [];
for (var i = 0, event; event = events[i]; i++) {
this.listeners_.push(
google.maps.event.addDomListener(bubble, event, function(e) {
e.cancelBubble = true;
if (e.stopPropagation) {
e.stopPropagation();
}
})
);
}
};
/**
* On Adding the InfoBubble to a map
* Implementing the OverlayView interface
*/
InfoBubble.prototype.onAdd = function() {
if (!this.bubble_) {
this.buildDom_();
}
this.addEvents_();
var panes = this.getPanes();
if (panes) {
panes.floatPane.appendChild(this.bubble_);
panes.floatShadow.appendChild(this.bubbleShadow_);
}
/* once the infoBubble has been added to the DOM, fire 'domready' event */
google.maps.event.trigger(this, 'domready');
};
InfoBubble.prototype['onAdd'] = InfoBubble.prototype.onAdd;
/**
* Draw the InfoBubble
* Implementing the OverlayView interface
*/
InfoBubble.prototype.draw = function() {
var projection = this.getProjection();
if (!projection) {
// The map projection is not ready yet so do nothing
return;
}
var latLng = /** @type {google.maps.LatLng} */ (this.get('position'));
if (!latLng) {
this.close();
return;
}
var tabHeight = 0;
if (this.activeTab_) {
tabHeight = this.activeTab_.offsetHeight;
}
var anchorHeight = this.getAnchorHeight_();
var arrowSize = this.getArrowSize_();
var arrowPosition = this.getArrowPosition_();
arrowPosition = arrowPosition / 100;
var pos = projection.fromLatLngToDivPixel(latLng);
var width = this.contentContainer_.offsetWidth;
var height = this.bubble_.offsetHeight;
if (!width) {
return;
}
// Adjust for the height of the info bubble
var top = pos.y - (height + arrowSize);
if (anchorHeight) {
// If there is an anchor then include the height
top -= anchorHeight;
}
var left = pos.x - (width * arrowPosition);
this.bubble_.style['top'] = this.px(top);
this.bubble_.style['left'] = this.px(left);
var shadowStyle = parseInt(this.get('shadowStyle'), 10);
switch (shadowStyle) {
case 1:
// Shadow is behind
this.bubbleShadow_.style['top'] = this.px(top + tabHeight - 1);
this.bubbleShadow_.style['left'] = this.px(left);
this.bubbleShadow_.style['width'] = this.px(width);
this.bubbleShadow_.style['height'] =
this.px(this.contentContainer_.offsetHeight - arrowSize);
break;
case 2:
// Shadow is below
width = width * 0.8;
if (anchorHeight) {
this.bubbleShadow_.style['top'] = this.px(pos.y);
} else {
this.bubbleShadow_.style['top'] = this.px(pos.y + arrowSize);
}
this.bubbleShadow_.style['left'] = this.px(pos.x - width * arrowPosition);
this.bubbleShadow_.style['width'] = this.px(width);
this.bubbleShadow_.style['height'] = this.px(2);
break;
}
};
InfoBubble.prototype['draw'] = InfoBubble.prototype.draw;
/**
* Removing the InfoBubble from a map
*/
InfoBubble.prototype.onRemove = function() {
if (this.bubble_ && this.bubble_.parentNode) {
this.bubble_.parentNode.removeChild(this.bubble_);
}
if (this.bubbleShadow_ && this.bubbleShadow_.parentNode) {
this.bubbleShadow_.parentNode.removeChild(this.bubbleShadow_);
}
for (var i = 0, listener; listener = this.listeners_[i]; i++) {
google.maps.event.removeListener(listener);
}
};
InfoBubble.prototype['onRemove'] = InfoBubble.prototype.onRemove;
/**
* Is the InfoBubble open
*
* @return {boolean} If the InfoBubble is open.
*/
InfoBubble.prototype.isOpen = function() {
return this.isOpen_;
};
InfoBubble.prototype['isOpen'] = InfoBubble.prototype.isOpen;
/**
* Close the InfoBubble
*/
InfoBubble.prototype.close = function() {
if (this.bubble_) {
this.bubble_.style['display'] = 'none';
// Remove the animation so we next time it opens it will animate again
this.bubble_.className =
this.bubble_.className.replace(this.animationName_, '');
}
if (this.bubbleShadow_) {
this.bubbleShadow_.style['display'] = 'none';
this.bubbleShadow_.className =
this.bubbleShadow_.className.replace(this.animationName_, '');
}
this.isOpen_ = false;
};
InfoBubble.prototype['close'] = InfoBubble.prototype.close;
/**
* Open the InfoBubble (asynchronous).
*
* @param {google.maps.Map=} opt_map Optional map to open on.
* @param {google.maps.MVCObject=} opt_anchor Optional anchor to position at.
*/
InfoBubble.prototype.open = function(opt_map, opt_anchor) {
var that = this;
window.setTimeout(function() {
that.open_(opt_map, opt_anchor);
}, 0);
};
/**
* Open the InfoBubble
* @private
* @param {google.maps.Map=} opt_map Optional map to open on.
* @param {google.maps.MVCObject=} opt_anchor Optional anchor to position at.
*/
InfoBubble.prototype.open_ = function(opt_map, opt_anchor) {
this.updateContent_();
if (opt_map) {
this.setMap(opt_map);
}
if (opt_anchor) {
this.set('anchor', opt_anchor);
this.bindTo('anchorPoint', opt_anchor);
this.bindTo('position', opt_anchor);
}
// Show the bubble and the show
this.bubble_.style['display'] = this.bubbleShadow_.style['display'] = '';
var animation = !this.get('disableAnimation');
if (animation) {
// Add the animation
this.bubble_.className += ' ' + this.animationName_;
this.bubbleShadow_.className += ' ' + this.animationName_;
}
this.redraw_();
this.isOpen_ = true;
var pan = !this.get('disableAutoPan');
if (pan) {
var that = this;
window.setTimeout(function() {
// Pan into view, done in a time out to make it feel nicer :)
that.panToView();
}, 200);
}
};
InfoBubble.prototype['open'] = InfoBubble.prototype.open;
/**
* Set the position of the InfoBubble
*
* @param {google.maps.LatLng} position The position to set.
*/
InfoBubble.prototype.setPosition = function(position) {
if (position) {
this.set('position', position);
}
};
InfoBubble.prototype['setPosition'] = InfoBubble.prototype.setPosition;
/**
* Returns the position of the InfoBubble
*
* @return {google.maps.LatLng} the position.
*/
InfoBubble.prototype.getPosition = function() {
return /** @type {google.maps.LatLng} */ (this.get('position'));
};
InfoBubble.prototype['getPosition'] = InfoBubble.prototype.getPosition;
/**
* position changed MVC callback
*/
InfoBubble.prototype.position_changed = function() {
this.draw();
};
InfoBubble.prototype['position_changed'] = InfoBubble.prototype.position_changed;
/**
* Pan the InfoBubble into view
*/
InfoBubble.prototype.panToView = function() {
var projection = this.getProjection();
if (!projection) {
// The map projection is not ready yet so do nothing
return;
}
if (!this.bubble_) {
// No Bubble yet so do nothing
return;
}
var anchorHeight = this.getAnchorHeight_();
var height = this.bubble_.offsetHeight + anchorHeight;
var map = this.get('map');
var mapDiv = map.getDiv();
var mapHeight = mapDiv.offsetHeight;
var latLng = this.getPosition();
var centerPos = projection.fromLatLngToContainerPixel(map.getCenter());
var pos = projection.fromLatLngToContainerPixel(latLng);
// Find out how much space at the top is free
var spaceTop = centerPos.y - height;
// Fine out how much space at the bottom is free
var spaceBottom = mapHeight - centerPos.y;
var needsTop = spaceTop < 0;
var deltaY = 0;
if (needsTop) {
spaceTop *= -1;
deltaY = (spaceTop + spaceBottom) / 2;
}
pos.y -= deltaY;
latLng = projection.fromContainerPixelToLatLng(pos);
if (map.getCenter() != latLng) {
map.panTo(latLng);
}
};
InfoBubble.prototype['panToView'] = InfoBubble.prototype.panToView;
/**
* Converts a HTML string to a document fragment.
*
* @param {string} htmlString The HTML string to convert.
* @return {Node} A HTML document fragment.
* @private
*/
InfoBubble.prototype.htmlToDocumentFragment_ = function(htmlString) {
htmlString = htmlString.replace(/^\s*([\S\s]*)\b\s*$/, '$1');
var tempDiv = document.createElement('DIV');
tempDiv.innerHTML = htmlString;
if (tempDiv.childNodes.length == 1) {
return /** @type {!Node} */ (tempDiv.removeChild(tempDiv.firstChild));
} else {
var fragment = document.createDocumentFragment();
while (tempDiv.firstChild) {
fragment.appendChild(tempDiv.firstChild);
}
return fragment;
}
};
/**
* Removes all children from the node.
*
* @param {Node} node The node to remove all children from.
* @private
*/
InfoBubble.prototype.removeChildren_ = function(node) {
if (!node) {
return;
}
var child;
while (child = node.firstChild) {
node.removeChild(child);
}
};
/**
* Sets the content of the infobubble.
*
* @param {string|Node} content The content to set.
*/
InfoBubble.prototype.setContent = function(content) {
this.set('content', content);
};
InfoBubble.prototype['setContent'] = InfoBubble.prototype.setContent;
/**
* Get the content of the infobubble.
*
* @return {string|Node} The marker content.
*/
InfoBubble.prototype.getContent = function() {
return /** @type {Node|string} */ (this.get('content'));
};
InfoBubble.prototype['getContent'] = InfoBubble.prototype.getContent;
/**
* Sets the marker content and adds loading events to images
*/
InfoBubble.prototype.updateContent_ = function() {
if (!this.content_) {
// The Content area doesnt exist.
return;
}
this.removeChildren_(this.content_);
var content = this.getContent();
if (content) {
if (typeof content == 'string') {
content = this.htmlToDocumentFragment_(content);
}
this.content_.appendChild(content);
var that = this;
var images = this.content_.getElementsByTagName('IMG');
for (var i = 0, image; image = images[i]; i++) {
// Because we don't know the size of an image till it loads, add a
// listener to the image load so the marker can resize and reposition
// itself to be the correct height.
google.maps.event.addDomListener(image, 'load', function() {
that.imageLoaded_();
});
}
}
this.redraw_();
};
/**
* Image loaded
* @private
*/
InfoBubble.prototype.imageLoaded_ = function() {
var pan = !this.get('disableAutoPan');
this.redraw_();
if (pan && (this.tabs_.length == 0 || this.activeTab_.index == 0)) {
this.panToView();
}
};
/**
* Updates the styles of the tabs
* @private
*/
InfoBubble.prototype.updateTabStyles_ = function() {
if (this.tabs_ && this.tabs_.length) {
for (var i = 0, tab; tab = this.tabs_[i]; i++) {
this.setTabStyle_(tab.tab);
}
this.activeTab_.style['zIndex'] = this.baseZIndex_;
var borderWidth = this.getBorderWidth_();
var padding = this.getPadding_() / 2;
this.activeTab_.style['borderBottomWidth'] = 0;
this.activeTab_.style['paddingBottom'] = this.px(padding + borderWidth);
}
};
/**
* Sets the style of a tab
* @private
* @param {Element} tab The tab to style.
*/
InfoBubble.prototype.setTabStyle_ = function(tab) {
var backgroundColor = this.get('backgroundColor');
var borderColor = this.get('borderColor');
var borderRadius = this.getBorderRadius_();
var borderWidth = this.getBorderWidth_();
var padd