text: /*
   * L.DomUtil contains various utility functions for working with DOM.
   */
  
  L.DomUtil = {
  	get: function (id) {
  		return (typeof id === 'string' ? document.getElementById(id) : id);
  	},
  
  	getStyle: function (el, style) {
  
  		var value = el.style[style];
  
  		if (!value && el.currentStyle) {
  			value = el.currentStyle[style];
  		}
  
  		if ((!value || value === 'auto') && document.defaultView) {
  			var css = document.defaultView.getComputedStyle(el, null);
  			value = css ? css[style] : null;
  		}
  
  		return value === 'auto' ? null : value;
  	},
  
  	getViewportOffset: function (element) {
  
  		var top = 0,
  		    left = 0,
  		    el = element,
  		    docBody = document.body,
  		    docEl = document.documentElement,
  		    pos,
  		    ie7 = L.Browser.ie7;
  
  		do {
  			top  += el.offsetTop  || 0;
  			left += el.offsetLeft || 0;
  
  			//add borders
  			top += parseInt(L.DomUtil.getStyle(el, 'borderTopWidth'), 10) || 0;
  			left += parseInt(L.DomUtil.getStyle(el, 'borderLeftWidth'), 10) || 0;
  
  			pos = L.DomUtil.getStyle(el, 'position');
  
  			if (el.offsetParent === docBody && pos === 'absolute') { break; }
  
  			if (pos === 'fixed') {
  				top  += docBody.scrollTop  || docEl.scrollTop  || 0;
  				left += docBody.scrollLeft || docEl.scrollLeft || 0;
  				break;
  			}
  			el = el.offsetParent;
  
  		} while (el);
  
  		el = element;
  
  		do {
  			if (el === docBody) { break; }
  
  			top  -= el.scrollTop  || 0;
  			left -= el.scrollLeft || 0;
  
  			// webkit (and ie <= 7) handles RTL scrollLeft different to everyone else
  			// https://code.google.com/p/closure-library/source/browse/trunk/closure/goog/style/bidi.js
  			if (!L.DomUtil.documentIsLtr() && (L.Browser.webkit || ie7)) {
  				left += el.scrollWidth - el.clientWidth;
  
  				// ie7 shows the scrollbar by default and provides clientWidth counting it, so we
  				// need to add it back in if it is visible; scrollbar is on the left as we are RTL
  				if (ie7 && L.DomUtil.getStyle(el, 'overflow-y') !== 'hidden' &&
  				           L.DomUtil.getStyle(el, 'overflow') !== 'hidden') {
  					left += 17;
  				}
  			}
  
  			el = el.parentNode;
  		} while (el);
  
  		return new L.Point(left, top);
  	},
  
  	documentIsLtr: function () {
  		if (!L.DomUtil._docIsLtrCached) {
  			L.DomUtil._docIsLtrCached = true;
  			L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === 'ltr';
  		}
  		return L.DomUtil._docIsLtr;
  	},
  
  	create: function (tagName, className, container) {
  
  		var el = document.createElement(tagName);
  		el.className = className;
  
  		if (container) {
  			container.appendChild(el);
  		}
  
  		return el;
  	},
  
  	disableTextSelection: function () {
  		if (document.selection && document.selection.empty) {
  			document.selection.empty();
  		}
  		if (!this._onselectstart) {
  			this._onselectstart = document.onselectstart || null;
  			document.onselectstart = L.Util.falseFn;
  		}
  	},
  
  	enableTextSelection: function () {
  		if (document.onselectstart === L.Util.falseFn) {
  			document.onselectstart = this._onselectstart;
  			this._onselectstart = null;
  		}
  	},
  
  	hasClass: function (el, name) {
  		return (el.className.length > 0) &&
  		        new RegExp('(^|\\s)' + name + '(\\s|$)').test(el.className);
  	},
  
  	addClass: function (el, name) {
  		if (!L.DomUtil.hasClass(el, name)) {
  			el.className += (el.className ? ' ' : '') + name;
  		}
  	},
  
  	removeClass: function (el, name) {
  
  		function replaceFn(w, match) {
  			if (match === name) { return ''; }
  			return w;
  		}
  
  		el.className = el.className
  		        .replace(/(\S+)\s*/g, replaceFn)
  		        .replace(/(^\s+|\s+$)/, '');
  	},
  
  	setOpacity: function (el, value) {
  
  		if ('opacity' in el.style) {
  			el.style.opacity = value;
  
  		} else if ('filter' in el.style) {
  
  			var filter = false,
  			    filterName = 'DXImageTransform.Microsoft.Alpha';
  
  			// filters collection throws an error if we try to retrieve a filter that doesn't exist
  			try {
  				filter = el.filters.item(filterName);
  			} catch (e) {
  				// don't set opacity to 1 if we haven't already set an opacity,
  				// it isn't needed and breaks transparent pngs.
  				if (value === 1) { return; }
  			}
  
  			value = Math.round(value * 100);
  
  			if (filter) {
  				filter.Enabled = (value !== 100);
  				filter.Opacity = value;
  			} else {
  				el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
  			}
  		}
  	},
  
  	testProp: function (props) {
  
  		var style = document.documentElement.style;
  
  		for (var i = 0; i < props.length; i++) {
  			if (props[i] in style) {
  				return props[i];
  			}
  		}
  		return false;
  	},
  
  	getTranslateString: function (point) {
  		// on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate
  		// makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care
  		// (same speed either way), Opera 12 doesn't support translate3d
  
  		var is3d = L.Browser.webkit3d,
  		    open = 'translate' + (is3d ? '3d' : '') + '(',
  		    close = (is3d ? ',0' : '') + ')';
  
  		return open + point.x + 'px,' + point.y + 'px' + close;
  	},
  
  	getScaleString: function (scale, origin) {
  
  		var preTranslateStr = L.DomUtil.getTranslateString(origin.add(origin.multiplyBy(-1 * scale))),
  		    scaleStr = ' scale(' + scale + ') ';
  
  		return preTranslateStr + scaleStr;
  	},
  
  	setPosition: function (el, point, disable3D) { // (HTMLElement, Point[, Boolean])
  
  		// jshint camelcase: false
  		el._leaflet_pos = point;
  
  		if (!disable3D && L.Browser.any3d) {
  			el.style[L.DomUtil.TRANSFORM] =  L.DomUtil.getTranslateString(point);
  
  			// workaround for Android 2/3 stability (https://github.com/CloudMade/Leaflet/issues/69)
  			if (L.Browser.mobileWebkit3d) {
  				el.style.WebkitBackfaceVisibility = 'hidden';
  			}
  		} else {
  			el.style.left = point.x + 'px';
  			el.style.top = point.y + 'px';
  		}
  	},
  
  	getPosition: function (el) {
  		// this method is only used for elements previously positioned using setPosition,
  		// so it's safe to cache the position for performance
  
  		// jshint camelcase: false
  		return el._leaflet_pos;
  	}
  };
  
  
  // prefix style property names
  
  L.DomUtil.TRANSFORM = L.DomUtil.testProp(
          ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
  
  // webkitTransition comes first because some browser versions that drop vendor prefix don't do
  // the same for the transitionend event, in particular the Android 4.1 stock browser
  
  L.DomUtil.TRANSITION = L.DomUtil.testProp(
          ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
  
  L.DomUtil.TRANSITION_END =
          L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ?
          L.DomUtil.TRANSITION + 'End' : 'transitionend';
  