(function (window) {
    "use strict";

    var $ = window.jQuery,
		google = window.google, // object
		view, // object

		uniqueMarkerIdNumber = 0, // number

		BaseObject = window.ListenerObject, // constuctor

		ListenerObject = window.ListenerObject, // constuctor

		MarkerClusterer, // constructor
		Cluster, // constructor
		ClusterIcon, // constructor

		CustomOverlay, // constructor
		GeneralMapMarkerConstructor,  // constructor
		MarkerObject, // constructor
		MarkerArray,  // constructor
		MapObject, // constructor

		EventMethods, // constructor

		ExecMethod, // constructor
		ExecQueue, // constructor

		Geocoder,

    /**
    * Checks if a string is a number with decimals
    */
		isFloat = function isFloat(str) {
		    var float = new RegExp(/^\d+\.\d+$/);

		    return (float).test(str);
		},
    /**
    * Checks if a string is an integer
    */
		isInt = function isInt(str) {
		    var int = new RegExp(/^\d+$/);

		    return (int).test(str);
		},
    /**
    * Checks if a string is a boolean
    */
		isBoolean = function (str) {
		    return (/^(true|false)$/i).test(str);
		},
    /**
    * A basic ForEach function
    *
    * @param array {Array||Object with a length property}
    * @param func {Function}
    * @param args {Array} (array||arguments)
    */
		each = function each(array, func, args) {
		    var index = 0,
				length = array.length || 0;

		    if (!args) {
		        args = [];
		    }

		    if (array.length && (func && typeof func === "function")) {
		        for (index = 0; index < length; index += 1) {
		            func.apply(array[index], args);
		        }
		    }
		};

    /* -- ExecMethod -- */
    ExecMethod = function ExecMethod(method, queue) {

        var execNextMethod = function execNextMethod() {

            var nextMethod = method.get("nextMethod"),
					ready = method.get("ready");

            if (nextMethod && ready) {
                nextMethod.apply(nextMethod);
            } else if (!nextMethod && ready) {
                queue.set("ready", true);
            }

        };

        ListenerObject.apply(method);

        method.addListener("ready", "change", execNextMethod);

        return method;
    };
    /* -- /ExecMethod -- */

    /* -- ExecQueue -- */

    ExecQueue = function ExecQueue(queueObject) {
        // get the "inheritFromPrototype" method from BaseObject
        BaseObject.apply(this);
        // copy the BaseObjects prototype to this (BaseCollection)
        this.copyPrototypeToProperty(BaseObject, this);
        this.set("length", 0);
        this.set("ready", false);

        var methods;
        for (methods in queueObject) {
            if (queueObject.hasOwnProperty(methods)) {
                this.addMethod(queueObject[methods]);
            }
        }
    };

    ExecQueue.prototype.addMethod = function addMethod(method) {
        var that = this;
        that[that.length] = new ExecMethod(method, that);
        that.length += 1;

        if (that.execWhenLength && (that.length >= that.execWhenLength)) {
            that.exec();
        }
    };

    ExecQueue.prototype.exec = function exec(options) {
        var that = this,
			i, // number (index)
			l = that.length, // number (length)
			opts = options || {};

        that.ready = false;

        for (i = 0; i < l; i += 1) {
            that[i].set("ready", false);
        }

        for (i = 0; i < l; i += 1) {
            if (that[i + 1] && !that[i].get("nextMethod")) {
                that[i].set("nextMethod", that[i + 1]);
            }
        }

        if (opts && opts.length) {
            that.execWhenLength = opts.length;
        } else if (that.length) {
            // exec the first method
            that[0].apply(that[0]);
        }
    };

    /* -- ExecQueue -- */

    /* -- MarkerClusterer -- */
    MarkerClusterer = function MarkerClusterer(map, opt_markers, opt_options) {

        var that = this,
			options = opt_options || {};

        this.extend(MarkerClusterer, google.maps.OverlayView);
        this.map = map; // object
        this.markers = []; // array
        this.clusters = []; // array
        this.sizes = [53, 56, 66, 78, 90]; // array
        this.styles = []; // array
        this.ready = false; // boolean
        this.mapContainerId = options.mapContainerId || ""; // string
        this.gridSize = options.gridSize || 60; // number
        this.minClusterSize = options.minimumClusterSize || 2;
        this.maxZoom = options.maxZoom || null; // number || null
        this.styles = options.styles || []; // array
        this.imagePath = options.imagePath || this.MARKER_CLUSTER_IMAGE_PATH; // string
        this.imageExtension = options.imageExtension || this.MARKER_CLUSTER_IMAGE_EXTENSION; // string
        this.zoomOnClick = true; // boolean
        this.averageCenter = false; // boolean
        this.prevZoom = this.map.getZoom(); // number

        if (options.zoomOnClick) {
            this.zoomOnClick = options.zoomOnClick;
        }

        if (options.averageCenter) {
            this.averageCenter = options.averageCenter;
        }

        this.setupStyles();
        this.setMap(map);

        /* -- addEvents -- */
        map.set("clusterReady", false);

        google.maps.event.addListener(map, "zoom_changed", function () {

            map.set("clusterReady", false);

            var mapType = map.mapTypes[map.getMapTypeId()],
				maxZoom = mapType ? mapType.maxZoom : 20,
				zoom = map.getZoom();

            if (zoom < 0 || zoom > maxZoom) {
                return;
            }

            if (that.prevZoom !== zoom) {
                that.prevZoom = map.getZoom();
            }
            that.resetViewport();
        });

        google.maps.event.addListener(map, 'idle', function () {
            that.redraw();
        });
        /* -- /addEvents -- */

        // Finally, add the markers
        if (opt_markers && opt_markers.length) {
            this.addMarkers(opt_markers, false);
        }
    };

    MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_PATH = 'http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/' + 'images/m';
    MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_EXTENSION = 'png';

    MarkerClusterer.prototype.extend = function (obj1, obj2) {
        var extractProperty = function extractProperty(Obj2, property) {
            var newInst = new Obj2();
            return newInst[property];
        },

			copyPrototype = function copyPrototype(object) {
			    var property;

			    for (property in object.prototype) {
			        if (object.prototype.hasOwnProperty(property)) {
			            this.prototype[property] = object.prototype[property];
			        } else {
			            this.prototype[property] = extractProperty(obj2, property);
			        }
			    }
			};

        return copyPrototype.apply(obj1, [obj2]);
    };

    MarkerClusterer.prototype.onAdd = function () {
        this.setReady(true);
    };

    MarkerClusterer.prototype.draw = function () { };

    MarkerClusterer.prototype.setupStyles = function () {
        if (this.styles.length) {
            return;
        }

        var i,
			size,
			l = this.sizes.length || 0;

        for (i = 0; i < l; i += 1) {

            size = this.sizes[i];

            this.styles.push({
                url: this.imagePath + (this.sizes[i] + 1) + '.' + this.imageExtension,
                height: size,
                width: size
            });
        }
    };

    MarkerClusterer.prototype.fitMapToMarkers = function () {
        var markers = this.getMarkers(),
			bounds = new google.maps.LatLngBounds(),
			i, // number
			marker,
			l = markers.length || 0;

        for (i = 0; i < l; i += 1) {
            marker = markers[i];
            bounds.extend(marker.getPosition());
        }

        this.map.fitBounds(bounds);
    };

    MarkerClusterer.prototype.setStyles = function (styles) {
        this.styles = styles;
    };

    MarkerClusterer.prototype.getStyles = function () {
        return this.styles;
    };

    MarkerClusterer.prototype.isZoomOnClick = function () {
        return this.zoomOnClick;
    };

    MarkerClusterer.prototype.isAverageCenter = function () {
        return this.averageCenter;
    };

    MarkerClusterer.prototype.getMarkers = function () {
        return this.markers;
    };

    MarkerClusterer.prototype.getTotalMarkers = function () {
        return this.markers.length;
    };

    MarkerClusterer.prototype.setMaxZoom = function (maxZoom) {
        this.maxZoom = maxZoom;
    };

    MarkerClusterer.prototype.getMaxZoom = function () {
        return this.maxZoom || this.map.mapTypes[this.map.getMapTypeId()].maxZoom;
    };

    MarkerClusterer.prototype.calculator = function (markers, numStyles) {
        var index = 0,
			count = markers.length,
			dv = count;

        while (dv !== 0) {
            dv = parseInt(dv / 10, 10);
            index += 1;
        }

        index = Math.min(index, numStyles);
        return {
            text: count,
            index: index
        };
    };

    MarkerClusterer.prototype.setCalculator = function (calculator) {
        this.calculator = calculator;
    };

    MarkerClusterer.prototype.getCalculator = function () {
        return this.calculator;
    };

    MarkerClusterer.prototype.addMarkers = function (markers, opt_nodraw) {
        var i,
			l = markers.length || 0;

        for (i = 0; i < l; i += 1) {
            this.pushMarkerTo(markers[i]);
        }

        if (!opt_nodraw) {
            this.redraw();
        }
    };

    MarkerClusterer.prototype.pushMarkerTo = function (marker) {
        marker.isAdded = false;
        if (marker.draggable) {
            // If the marker is draggable add a listener so we update the clusters on
            // the drag end.
            var that = this;

            google.maps.event.addListener(marker, 'dragend', function () {
                marker.isAdded = false;
                that.repaint();
            });
        }
        this.markers.push(marker);
    };

    MarkerClusterer.prototype.addMarker = function (marker, opt_nodraw) {

        this.pushMarkerTo(marker);
        if (!opt_nodraw) {
            this.redraw();
        }
    };

    MarkerClusterer.prototype.removeMarker = function (marker) {
        var index = -1,
			i,
			l = this.markers;

        if (this.markers.indexOf) {
            index = this.markers.indexOf(marker);
        } else {
            for (i = 0; i < l; i += 1) {
                if (this.markers[i] === marker) {
                    index = i;
                    break;
                }
            }
        }

        if (index === -1) {
            // Marker is not in our list of markers.
            return false;
        }

        marker.setMap(null);

        this.markers.splice(index, 1);

        return true;
    };

    MarkerClusterer.prototype.removeMarker = function (marker, opt_nodraw) {
        var removed = this.removeMarker(marker);

        if (!opt_nodraw && removed) {
            this.resetViewport();
            this.redraw();
            return true;
        } else {
            return false;
        }
    };

    MarkerClusterer.prototype.removeMarkers = function (markers, opt_nodraw) {
        var removed = false,
			i,
			l = markers.length || 0,
			r;

        for (i = 0; i < l; i += 1) {
            r = this.removeMarker(markers[i]);
            removed = removed || r;
        }

        if (!opt_nodraw && removed) {
            this.resetViewport();
            this.redraw();
            return true;
        }
    };

    MarkerClusterer.prototype.setReady = function (ready) {
        if ((typeof this.ready === "boolean") && !this.ready) {
            this.ready = ready;
            this.createClusters();
        } else {
            this.ready.set(ready);
            this.createClusters();
        }
    };

    MarkerClusterer.prototype.getTotalClusters = function () {
        var clusters = this.clusters.get ? this.clusters.get() : this.clusters;
        return clusters.length;
    };

    MarkerClusterer.prototype.getMap = function () {
        return this.map;
    };

    MarkerClusterer.prototype.setMap = function (map) {
        this.map = map;
    };

    MarkerClusterer.prototype.getGridSize = function () {
        return this.gridSize;
    };

    MarkerClusterer.prototype.setGridSize = function (size) {
        this.gridSize = size;
    };

    MarkerClusterer.prototype.getMinClusterSize = function () {
        return this.minClusterSize;
    };

    MarkerClusterer.prototype.setMinClusterSize = function (size) {
        this.minClusterSize = size;
    };

    MarkerClusterer.prototype.getExtendedBounds = function (bounds) {

        var projection = this.getProjection(),

        // Turn the bounds into latlng.
			tr = new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getNorthEast().lng()),
			bl = new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng()),

			trPix = projection.fromLatLngToDivPixel(tr),
			blPix = projection.fromLatLngToDivPixel(bl),
			ne,
			sw;

        // Convert the points to pixels and the extend out by the grid size.
        trPix.x += this.gridSize;
        trPix.y -= this.gridSize;

        blPix.x -= this.gridSize;
        blPix.y += this.gridSize;

        // Convert the pixel points back to LatLng
        ne = projection.fromDivPixelToLatLng(trPix);
        sw = projection.fromDivPixelToLatLng(blPix);

        // Extend the bounds to contain the new bounds.
        bounds.extend(ne);
        bounds.extend(sw);

        return bounds;
    };

    MarkerClusterer.prototype.isMarkerInBounds = function (marker, bounds) {
        return bounds.contains(marker.getPosition());
    };

    MarkerClusterer.prototype.clearMarkers = function () {
        this.resetViewport(true);

        // Set the markers a empty array.

        this.markers = [];
    };

    MarkerClusterer.prototype.resetViewport = function (opt_hide) {
        var clusters = this.clusters,

			i, // number (index)
			l = clusters.length || 0,

			markers = this.markers,
			j, // number (index)
			k = markers.length || 0;

        // Remove all the clusters
        for (i = 0; i < l; i += 1) {
            clusters[i].remove();
        }

        // Reset the markers to not be added and to be invisible.
        for (j = 0; j < k; j += 1) {
            markers[j].set("isAdded", false);
            if (opt_hide) {
                markers[j].setMap(null);
            }
        }

        if (this.clusters.set) {
            this.clusters.set([]);
        } else {
            this.clusters = [];
        }
    };

    MarkerClusterer.prototype.repaint = function () {
        var oldClusters = this.clusters.slice(),
			clusters = this.clusters;

        clusters.length = 0;
        this.resetViewport();
        this.redraw();

        // Remove the old clusters.
        // Do it in a timeout so the other clusters have been drawn first.
        window.setTimeout(function () {
            var i,
				l = oldClusters.length || 0;

            for (i = 0; i < l; i += 1) {
                oldClusters[i].remove();
            }

        }, 0);
    };

    MarkerClusterer.prototype.redraw = function () {
        this.createClusters();
    };

    MarkerClusterer.prototype.distanceBetweenPoints = function (p1, p2) {
        if (!p1 || !p2) {
            return 0;
        }

        var R = 6371, // Radius of the Earth in km
			dLat = (p2.lat() - p1.lat()) * Math.PI / 180,
			dLon = (p2.lng() - p1.lng()) * Math.PI / 180,
			a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2),
			c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)),
			d = R * c;
        return d;
    };

    MarkerClusterer.prototype.addToClosestCluster = function addToClosestCluster(marker) {
        var distance = 40000, // Some large number
			clusterToAddTo = null,
			clusters = this.clusters,
			center,
			i,
			l = clusters.length || 0,
			d,
			cluster;

        for (i = 0; i < l; i += 1) {
            center = clusters[i].getCenter();

            if (center) {
                d = this.distanceBetweenPoints(center, marker.getPosition());
                if (d < distance) {
                    distance = d;
                    clusterToAddTo = clusters[i];
                }
            }
        }

        if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {
            clusterToAddTo.addMarker(marker);
        } else {
            cluster = new Cluster(this);
            cluster.addMarker(marker);

            clusters.push(cluster);
        }
    };

    MarkerClusterer.prototype.createClusters = function createClusters() {
        var ready = this.ready,
			map = this.map,
			mapBounds,
			bounds,
			markers = this.markers,
			i,
			l = markers.length || 0;

        if (!ready) {
            return;
        }

        // Get our current map view bounds.
        // Create a new bounds object so we don't affect the map.
        mapBounds = new google.maps.LatLngBounds(this.map.getBounds().getSouthWest(), map.getBounds().getNorthEast());
        bounds = this.getExtendedBounds(mapBounds);

        for (i = 0; i < l; i += 1) {
            if (!markers[i].get("isAdded") && this.isMarkerInBounds(markers[i], bounds)) {
                this.addToClosestCluster(markers[i]);
            }
        }

        setTimeout(function () {
            map.set("clusterReady", true);
            view.loadedMaps[map.mapContainer.id].set("clusterReady", true);
        }, 0);
    };
    /* -- /MarkerClusterer -- */

    /* -- Cluster -- */
    Cluster = function Cluster(markerClusterer) {
        this.markerClusterer = markerClusterer;
        this.map = markerClusterer.getMap();
        this.gridSize = markerClusterer.getGridSize();
        this.minClusterSize = markerClusterer.getMinClusterSize();
        this.averageCenter = markerClusterer.isAverageCenter();
        this.center = null;
        this.markers = [];
        this.bounds = null;
        this.clusterIcon = new ClusterIcon(this, markerClusterer.getStyles(), markerClusterer.getGridSize());
    };

    Cluster.prototype.isMarkerAlreadyAdded = function (marker) {
        if (this.markers.indexOf) {
            return this.markers.indexOf(marker) !== -1;
        } else {
            var markers = this.markers,
				i,
				l = markers.length || 0;

            for (i = 0; i < l; i += 1) {
                if (markers[i] === marker) {
                    return true;
                }
            }
        }
        return false;
    };

    Cluster.prototype.addMarker = function (marker) {
        if (this.isMarkerAlreadyAdded(marker)) {
            return false;
        }

        var l,
			lat,
			lng,
			len,
			i;

        if (!this.center) {
            this.center = marker.getPosition();
            this.calculateBounds();
        } else {
            if (this.averageCenter) {
                l = this.markers.length + 1;
                lat = (this.center.lat() * (l - 1) + marker.getPosition().lat()) / l;
                lng = (this.center.lng() * (l - 1) + marker.getPosition().lng()) / l;

                this.center = new google.maps.LatLng(lat, lng);
                this.calculateBounds();
            }
        }

        marker.isAdded = true;
        this.markers.push(marker);

        len = this.markers.length;
        if (len < this.minClusterSize && marker.getMap() !== this.map) {
            // Min cluster size not reached so show the marker.
            marker.setMap(this.map);
        }

        if (len === this.minClusterSize) {
            // Hide the markers that were showing.
            for (i = 0; i < len; i += 1) {
                this.markers[i].setMap(null);
            }
        }

        if (len >= this.minClusterSize) {
            marker.setMap(null);
        }

        this.updateIcon();
        return true;
    };

    Cluster.prototype.getMarkerClusterer = function () {
        return this.markerClusterer;
    };

    Cluster.prototype.getBounds = function () {
        var bounds = new google.maps.LatLngBounds(this.center, this.center),
			markers = this.getMarkers(),
			i,
			l = markers.length;

        for (i = 0; i < l; i += 1) {
            bounds.extend(markers[i].getPosition());
        }

        return bounds;
    };

    Cluster.prototype.remove = function () {

        this.clusterIcon.remove();
        this.markers.length = 0;
        delete this.markers;
    };

    Cluster.prototype.getSize = function () {
        return this.markers.length;
    };

    Cluster.prototype.getMarkers = function () {
        return this.markers;
    };

    Cluster.prototype.getCenter = function () {
        return this.center;
    };

    Cluster.prototype.calculateBounds = function () {
        var bounds = new google.maps.LatLngBounds(this.center, this.center);
        this.bounds = this.markerClusterer.getExtendedBounds(bounds);
    };

    Cluster.prototype.isMarkerInClusterBounds = function (marker) {
        return this.bounds.contains(marker.getPosition());
    };

    Cluster.prototype.getMap = function () {
        return this.map;
    };

    Cluster.prototype.updateIcon = function () {
        var zoom = this.map.getZoom(),
			mz = this.markerClusterer.getMaxZoom(),
			markers = this.markers,
			i,
			l = markers.length,
			numStyles,
			sums;

        if (zoom > mz) {
            // The zoom is greater than our max zoom so show all the markers in cluster.
            for (i = 0; i < l; i += 1) {
                markers[i].setMap(this.map);
            }
            return;
        }

        if (this.markers.length < this.minClusterSize) {
            // Min cluster size not yet reached.
            this.clusterIcon.hide();
            return;
        }

        numStyles = this.markerClusterer.getStyles().length;
        sums = this.markerClusterer.getCalculator()(this.markers, numStyles);

        this.clusterIcon.setCenter(this.center);
        this.clusterIcon.setSums(sums);
        this.clusterIcon.show();
    };

    /* -- /Cluster -- */

    /* -- ClusterIcon -- */
    ClusterIcon = function ClusterIcon(cluster, styles, opt_padding) {
        cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);

        this.styles = styles;
        this.padding = opt_padding || 0;
        this.cluster = cluster;
        this.center = null;
        this.map = cluster.getMap();
        this.div = null;
        this.sums = null;
        this.visible = false;

        this.setMap(this.map);
    };

    ClusterIcon.prototype.triggerClusterClick = function () {
        var markerClusterer = this.cluster.getMarkerClusterer();

        // Trigger the clusterclick event.
        google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster);

        if (markerClusterer.isZoomOnClick()) {
            // Zoom into the cluster.
            this.map.fitBounds(this.cluster.getBounds());
        }
    };

    ClusterIcon.prototype.onAdd = function () {
        this.div = document.createElement('DIV');

        var pos,
			panes,
			that;

        if (this.visible) {
            pos = this.getPosFromLatLng(this.center);
            this.div.style.cssText = this.createCss(pos);
            this.div.innerHTML = this.sums.text;
        }

        panes = this.getPanes();
        panes.overlayMouseTarget.appendChild(this.div);

        that = this;
        google.maps.event.addDomListener(this.div, 'click', function () {
            that.triggerClusterClick();
        });
    };

    ClusterIcon.prototype.getPosFromLatLng = function (latlng) {
        var pos = this.getProjection().fromLatLngToDivPixel(latlng);
        pos.x -= parseInt(this.width / 2, 10);
        pos.y -= parseInt(this.height / 2, 10);
        return pos;
    };

    ClusterIcon.prototype.draw = function () {
        if (this.visible) {
            var pos = this.getPosFromLatLng(this.center);
            this.div.style.top = pos.y + 'px';
            this.div.style.left = pos.x + 'px';
        }
    };

    ClusterIcon.prototype.hide = function () {
        if (this.div) {
            this.div.style.display = 'none';
        }
        this.visible = false;
    };

    ClusterIcon.prototype.show = function () {
        if (this.div) {
            var pos = this.getPosFromLatLng(this.center);
            this.div.style.cssText = this.createCss(pos);
            this.div.style.display = '';
        }
        this.visible = true;
    };

    ClusterIcon.prototype.remove = function () {
        this.setMap(null);
    };

    ClusterIcon.prototype.onRemove = function () {
        if (this.div && this.div.parentNode) {
            this.hide();
            this.div.parentNode.removeChild(this.div);
            this.div = null;
        }
    };

    ClusterIcon.prototype.setSums = function (sums) {
        this.sums = sums;
        this.text = sums.text;
        this.index = sums.index;
        if (this.div) {
            this.div.innerHTML = sums.text;
        }

        this.useStyle();
    };

    ClusterIcon.prototype.useStyle = function () {
        var index = Math.max(0, this.sums.index - 1),
			style;

        index = Math.min(this.styles.length - 1, index);
        style = this.styles[index];

        this.url = style.url;
        this.height = style.height;
        this.width = style.width;
        this.textColor = style.textColor;
        this.anchor = style.anchor;
        this.textSize = style.textSize;
        this.backgroundPosition = style.backgroundPosition;
    };

    ClusterIcon.prototype.setCenter = function (center) {
        this.center = center;
    };

    ClusterIcon.prototype.createCss = function (pos) {
        var style = [],
			backgroundPosition,
			txtColor,
			txtSize,
			textLength;

        style.push('background-image:url(' + this.url + ');');

        backgroundPosition = this.backgroundPosition || '0 0';
        style.push('background-position:' + backgroundPosition + ';');

        if (typeof this.anchor === 'object') {
            if (typeof this.anchor[0] === 'number' && this.anchor[0] > 0 && this.anchor[0] < this.height) {
                style.push('height:' + (this.height - this.anchor[0]) + 'px; padding-top:' + this.anchor[0] + 'px;');
            } else {
                style.push('height:' + this.height + 'px; line-height:' + this.height + 'px;');
            }

            if (typeof this.anchor[1] === 'number' && this.anchor[1] > 0 && this.anchor[1] < this.width) {
                style.push('width:' + (this.width - this.anchor[1]) + 'px; padding-left:' + this.anchor[1] + 'px;');
            } else {
                style.push('width:' + this.width + 'px; text-align:center;');
            }
        } else {
            style.push('height:' + this.height + 'px; line-height:' + this.height + 'px; width:' + this.width + 'px; text-align:center;');
        }

        txtColor = this.textColor || 'black';
        txtSize = this.textSize || 11;

        style.push('cursor:pointer; top:' + pos.y + 'px; left:' +
			pos.x + 'px; color:' + txtColor + '; position:absolute; font-size:' +
			txtSize + 'px; font-family:Arial,sans-serif; font-weight:bold');

        if (this.sums && this.sums.text) {
            textLength = this.sums.text.toString().match(/\d/g).length;
            this.div.className = "clusterMarker clusterSize_" + textLength.toString();
        }

        return style.join('');
    };
    /* -- /ClusterIcon -- */

    /* -- GeneralMapMarkerConstructor -- */

    GeneralMapMarkerConstructor = function GeneralMapMarkerConstructor() {

        // get the "inheritFromPrototype" method from BaseObject
        BaseObject.apply(this);
        // copy the BaseObjects prototype to this (BaseCollection)
        this.copyPrototypeToProperty(BaseObject, this);

        ListenerObject.apply(this);

        this.setValues = function setValues(options) {
            var that = this,
				k;

            for (k in options) {
                if (options.hasOwnProperty(k)) {
                    that.set(k, options[k]);

                    if (k === "mapContainer") {
                        that.set("mapContainerId", options[k].id);
                    }
                }
            }
        };
    };

    /* -- /GeneralMapMarkerConstructor -- */

    /* -- MarkerObject -- */

    MarkerObject = function MarkerObject(newMarkerObject) {
        GeneralMapMarkerConstructor.apply(this);

        var that = this,
			jqMapContainer = $(newMarkerObject.mapObject.mapContainer),
			overlay = jqMapContainer.data("overlay"),
			newDomMarker = jqMapContainer.data("customPoiHTML").cloneNode(true);

        that.setValues(newMarkerObject.marker);

        that.set("mapContainerId", newMarkerObject.mapObject.mapContainer.id);

        // add a reference to the domElement to the marketObject
        that.set("domElement", newDomMarker);

        that.set("overlay", overlay);

        // Set "Id", "Label text" and other stuff
        that.setMarkerProperties(newMarkerObject);

        // set the marker dimensions
        that.setDimensions();

        that.set("loadedMap", view.loadedMaps[that.get("mapContainerId")]);
        that.set("map", that.get("loadedMap").map);
    };

    MarkerObject.prototype.getMarkerLatLng = function getMarkerLatLng(lat, lng) {
        return new google.maps.LatLng(parseFloat(lat), parseFloat(lng));
    };

    MarkerObject.prototype.getMarkerPixelPosition = function getMarkerPixelPosition(markerLatLng) {
        var getProjection = this.get("overlay").getProjection(),
			pixelLatLng = getProjection ? getProjection.fromLatLngToDivPixel(markerLatLng) : {
			    y: 0,
			    x: 0
			};

        return pixelLatLng;
    };

    MarkerObject.prototype.getDimensions = function getDimensions() {
        var that = this,
			domElement = that.get("domElement"), // HTMLElement
			height, // number
			width; // number

        domElement.style.visibility = "hidden";
        domElement.style.position = "absolute";

        document.body.appendChild(domElement);

        height = domElement.offsetHeight;
        width = domElement.offsetWidth;

        document.body.removeChild(domElement);

        return {
            height: height,
            width: width
        };
    };

    MarkerObject.prototype.setDimensions = function getDimensions() {
        var that = this,
			dimensions = that.getDimensions();

        that.set("width", dimensions.width);
        that.set("height", dimensions.height);
    };

    MarkerObject.prototype.getUniqueMarkerId = function getUniqueMarkerId(mapContainerId) {
        uniqueMarkerIdNumber += 1;

        return "customPoi_" + uniqueMarkerIdNumber + "_" + mapContainerId;
    };

    MarkerObject.prototype.addClasses = function addClasses(markerObject) {

        var that = this,
			jqDomElement = $(that.domElement),

			typeClass = markerObject.Type ? "type_" + markerObject.Type : "",

			formatCategoryClass = function (categoryName) {
			    var category = $.trim(categoryName.toLowerCase().replace(/\s/g, "_")),
					replaceAA = category.replace(/(\u00E4|\u00E5)/g, "a"), // replace "åä",
					replaceO = replaceAA.replace(/\u00F6/g, "o"), // replace ö
					categoryClass = replaceO;

			    return categoryClass;
			},

			categoryClasses = (function () {

			    var classStr = "",
					categories = markerObject.CategoryDic,
					k;

			    for (k in categories) {
			        if (categories.hasOwnProperty(k)) {
			            if (!classStr) {
			                classStr = formatCategoryClass(categories[k]);
			            } else {
			                classStr += " " + formatCategoryClass(categories[k]);
			            }
			        }
			    }

			    return $.trim(classStr);
			} ());

        if (typeClass) {
            jqDomElement.addClass(typeClass);
        }

        if (categoryClasses) {
            jqDomElement.addClass(categoryClasses);
        }
    };

    MarkerObject.prototype.setMarkerProperties = function setMarkerProperties() {
        var that = this,
			domMarker = that.get("domElement"),
			jqDomMarker = $(domMarker);

        // set the marker ID
        if (that.ID) {
            that.get("domElement").id = "customPoi_" + that.ID + "_" + that.get("mapContainerId");
        } else {
            that.get("domElement").id = that.getUniqueMarkerId(that.get("mapContainerId"));
        }

        // If the marker has an "CampaignUrl" add a clickEvent and link top that url.
        if (that.CampaignUrl) {
            if(that.IsNewWindow) {
                jqDomMarker.click(function () {
                    window.open(that.CampaignUrl);
                });
            } else {
                jqDomMarker.click(function () {
                    document.location = that.CampaignUrl;
                });
            }
        }

        that.addClasses(that);

        // if the marker has a "Title" property add that text to the customPoi labelText
        if (that.Title) {

            if (jqDomMarker.hasClass("weather")) {

                jqDomMarker.addClass("weatherIcon_" + that.Icon);
                jqDomMarker.find(".labelText").text(that.Title + "\u00B0");
            } else {

                jqDomMarker.find(".labelText").text(that.Title);
            }
        } else {
            jqDomMarker.find(".label").remove();
        }
    };

    MarkerObject.prototype.show = function show() {

        var that = this,
			loadedMap = view.loadedMaps[that.mapContainerId],
			overlay = document.getElementById("topOverlay_" + that.mapContainerId),
			geoMarker = loadedMap.get("geoMarker"),
			overlayAdded = function overlayAdded(property, value) {
			    if (property && value) {
			        overlay = document.getElementById("topOverlay_" + that.mapContainerId);

			        overlay.appendChild(that.domElement);

			        if (geoMarker) {
			            overlay.appendChild(geoMarker.get("domElement"));
			        }
			    }
			};

        if (loadedMap.get("overlayAdded")) {
            overlayAdded("prop", 1);
        } else {
            loadedMap.addListener("overlayAdded", "isset", overlayAdded);
        }
    };

    MarkerObject.prototype.hide = function hide() {
        if (this.domElement.parentNode) {
            this.domElement.parentNode.removeChild(this.domElement);
        }
    };

    MarkerObject.prototype.getPosition = function getPosition() {
        return this.getMarkerLatLng(this.Latitude, this.Longitude);
    };

    MarkerObject.prototype.getMap = function getMap() {
        return view.loadedMaps[this.mapContainerId].get("map");
    };

    MarkerObject.prototype.getVisible = function getVisible() {
        var that = this,
			domElementIsAdded = that.domElement ? that.domElement.parentNode : null;

        return (domElementIsAdded ? true : false);
    };

    MarkerObject.prototype.setVisible = function setVisible(show) {
        if (!show) {
            this.hide();
        } else {
            this.show();
        }
    };

    MarkerObject.prototype.setMap = function (map) {
        if (map) {
            this.show();
        } else {
            this.hide();
        }
    };

    MarkerObject.prototype.setMarkerPosition = function setMarkerPosition(map) {

        var domMarker = this.domElement,

			lat = parseFloat(this.Latitude),
			lng = parseFloat(this.Longitude),

			markerLatLng = this.getMarkerLatLng(lat, lng),
			pixelPoition = this.getMarkerPixelPosition(markerLatLng, map),

			markerWidth = this.width,
			markerHeight = this.height,

			top = Math.round(pixelPoition.y - markerHeight),
			left = Math.round(pixelPoition.x - Math.round(markerWidth / 2));

        $(domMarker).css({
            top: top + "px",
            left: left + "px",
            visibility: "visible"
        });
    };

    MarkerObject.prototype.isInBounds = function isInBounds(map) {
        var bounds = map.getBounds(),
			inBounds = bounds.contains(this.getPosition());

        if (!bounds || !inBounds) {
            this.hide();
            return false;
        }
        return inBounds;
    };

    /* -- /MarkerObject -- */


    /* -- MarkerArray -- */

    /* -- EventMethods -- */
    EventMethods = function EventMethods(additionalMethods) {
        var that = this,
			addMeth;

        that.getMapContainer = function getMapContainer(map) {
            this.mapContainer = map.mapContainer;
        };

        that.getMapContainerId = function getMapContainerId() {
            this.mapContainerId = this.mapContainer.id;
        };

        that.getLoadedMap = function getLoadedMap() {
            this.loadedMap = view.loadedMaps[this.mapContainerId];
            this.loadedMap.set("clusterReady", false);
        };

        that.setGeoMarker = function setGeoMarker() {
            if (this.loadedMap.get("geoMarker")) {
                this.loadedMap.get("geoMarker").setMarkerPosition();
            }
        };

        for (addMeth in additionalMethods) {
            if (additionalMethods.hasOwnProperty(addMeth) && typeof additionalMethods[addMeth] === "function") {
                that[addMeth] = additionalMethods[addMeth];
            }
        }
    };
    /* -- /EventMethods -- */

    MarkerArray = google.maps.MVCArray;

    MarkerArray.prototype.bounds_changed = function bounds_changed() {
        this.eventHandlers.handleEvent(this, this.map, "bounds_changed");
    };

    MarkerArray.prototype.zoom_changed = function zoom_changed() {
        this.eventHandlers.handleEvent(this, this.map, "zoom_changed");
    };

    MarkerArray.prototype.eventHandlers = {
        events: {
            zoom_changed: new EventMethods({
                setClusterSizeByZoomLevel: function setClusterSizeByZoomLevel(map) {

                    var zoom = map.getZoom();

                    if (zoom >= 17) {
                        map.set("showMarkersInBounds", true);
                    } else {
                        map.set("showMarkersInBounds", false);
                    }
                }
            }),

            bounds_changed: new EventMethods({
                getMarkers: function getMarkers() {
                    this.markers = this.loadedMap.get("markers");
                },
                setMarkers: function setMarkers(map) {
                    var setMarker = function setMarker(marker) {
                        var updatePosition = marker.isInBounds(map);

                        if (updatePosition) {
                            marker.setMarkerPosition(map);
                        } else {
                            marker.hide();
                        }
                    };

                    this.markers.forEach(setMarker);
                },
                showMarkersNotInCluster: function showMarkersNotInCluster(map) {
                    var that = this,
						loadedMap = view.loadedMaps[map.mapContainer.id],

						showMarkers = function showMarkers(property, value) {

						    if (property && value) {
						        var i, // number (index)
									clusters = loadedMap.markerClusterer ? loadedMap.markerClusterer.clusters : [], // array 
									l = clusters.length, // number (length)
									showMarkerIfInBounds = function showMarkerIfInBounds() {
									    var updatePosition = this.isInBounds(map);
									    if (updatePosition) {
									        this.show();
									    }
									};

						        for (i = 0; i < l; i += 1) {
						            if (clusters[i].markers.length < clusters[i].minClusterSize) {
						                each(clusters[i].markers, showMarkerIfInBounds);
						            }
						        }

						        that.loadedMap.set("markersReady", true);

						        if (map.get("showMarkersInBounds")) {
						            loadedMap.showMarkersInBounds();
						        }

						        loadedMap.removeListener("clusterReady", "change", showMarkers);
						    }
						};

                    loadedMap.addListener("clusterReady", "change", showMarkers);
                }
            })
        },
        runAll: function runAll(that, map, eventName) {
            var k,
				eventObject = that.eventHandlers.events[eventName];
            if (eventObject) {

                for (k in eventObject) {
                    if (eventObject.hasOwnProperty(k) && (typeof eventObject[k] === "function")) {
                        eventObject[k](map);
                    }
                }
            }
        },

        handleEvent: function handleEvent(that, map, eventName) {
            that.eventHandlers.runAll(that, map, eventName);
        }
    };

    MarkerArray.prototype.getMarkersArray = function getMarkersArray() {
        var that = this,
			markersArray = [],
			addMarkerToArray = function (marker) {
			    markersArray.push(marker);
			};

        that.forEach(addMarkerToArray);

        return markersArray;
    };

    /* -- /MarkerArray -- */


    /* -- MapObject -- */

    MapObject = function MapObject(options) {
        var that = this;

        GeneralMapMarkerConstructor.apply(this);

        this.set("mapVars", new ListenerObject());
        this.set("markers", new MarkerArray());

        this.setValues(options);

        this.set("hasMap", false);

        this.addListener("hasMap", "change", function (property, value) {
            if (property && value) {

                that.set("map", $(options.mapContainer).data("map"));

                that.get("map").set("clusterReady", false);

                that.get("markers").set("map", that.map);
                that.get("markers").bindTo('zoom', that.map);
                that.get("markers").bindTo('bounds', that.map);
            }
        });
    };

    MapObject.prototype.showMarkersInBounds = function showMarkersInBounds() {
        var markers = this.get("markers"),
			map = this.get("map"),
			markerClusterer = this.get("markerClusterer"),
			showMarkerInBounds = function showMarkerInBounds(marker) {
			    if (marker.isInBounds(map)) {
			        marker.show();
			    }
			};

        markerClusterer.resetViewport();
        markers.forEach(showMarkerInBounds);
    };

    MapObject.prototype.setMapVar = function setMapVar(property, value) {
        this.mapVars.set(property, value);
    };

    MapObject.prototype.getMapVar = function getMapVar(property) {
        return this.mapVars.get(property);
    };

    MapObject.prototype.setGeoMarker = function setGeoMarker(newMarker) {
        var that = this,
			loadedMap = view.loadedMaps[that.mapContainerId],
			geoMarker = new MarkerObject({
			    mapObject: that,
			    marker: newMarker
			}),
			overlay = document.getElementById("topOverlay_" + that.mapContainerId),
			checkOverlayAdded = function checkOverlayAdded() {
			    overlay = document.getElementById("topOverlay_" + that.mapContainerId);

			    that.set("geoMarker", geoMarker);

			    overlay.appendChild(that.get("geoMarker").domElement);

			    that.get("geoMarker").setMarkerPosition();
			    that.get("geoMarker").show();

			    loadedMap.set("hasGeoMarker", true);

			    loadedMap.removeListener("overlayAdded", "change", checkOverlayAdded);
			};

        if (overlay) {
            $(overlay).find(".geo_marker").remove();
        }

        if (!loadedMap.get("overlayAdded")) {
            loadedMap.addListener("overlayAdded", "change", checkOverlayAdded);
        } else {
            checkOverlayAdded.apply(loadedMap.get("overlayAdded"));
        }
    };

    MapObject.prototype.getGeoMarker = function getGeoMarker(fromFormat) {
        if (fromFormat) {
            var FromFormat = function FromFormat(geomarker) {
                this.latLng = view.util.getMarkerLatLng(geomarker.Latitude, geomarker.Longitude);
                this.title = geomarker.Title;
            };

            return new FromFormat(this.get("geoMarker"));
        } else {
            return this.get("geoMarker");
        }
    };

    MapObject.prototype.addMarker = function addMarker(markerObject) {
        var that = this,
			currentMarkers = that.get("markers"),
			newMarker = new MarkerObject({
			    mapObject: that,
			    marker: markerObject
			});
        currentMarkers.push(newMarker);
    };

    MapObject.prototype.addMarkers = function addMarkers(markers) {
        var that = this, // object
			i, // number
			l = markers.length; // number
        for (i = 0; i < l; i += 1) {
            that.addMarker(markers[i]);
        }
    };

    /* -- /MapObject -- */


    /* -- CustomOverlay-- */

    /**
    * CustomOverlay constructor
    * @param {Object} options Options object to be bound to GMapMM
    * @constructor
    */
    CustomOverlay = function CustomOverlay(options) {
        this.setValues(options);

        var div = this.divOverlay = document.createElement('div'),
			map = this.get("map");

        if (typeof this.overlayOnTop !== "boolean") {
            this.overlayOnTop = true;
            map.set("overlayAdded", false);
        }

        if (options.className) {
            div.className = "overlay " + options.className;
        } else {
            div.className = "overlay";
        }
    };

    /**
    * Inherites from google.maps.OverlayView
    */
    CustomOverlay.prototype = new google.maps.OverlayView();

    /**
    * When added set zIndex
    */
    CustomOverlay.prototype.onAdd = function onAdd() {
        var pane = this.getPanes().overlayLayer;
        pane.appendChild(this.divOverlay);
        this.addTopOverlay();
    };

    /**
    * When removed, remove DOM node
    */
    CustomOverlay.prototype.onRemove = function onRemove() {
        this.divOverlay.parentNode.removeChild(this.divOverlay);
        this.removeTopOverlay();
    };

    /**
    * When drawn, set correct css left and top
    */
    CustomOverlay.prototype.draw = function draw() {
        var projection = this.getProjection(),
			position = projection.fromLatLngToDivPixel(this.getMap().getCenter()),
			div = this.divOverlay;

        div.style.left = position.x + 'px';
        div.style.top = position.y + 'px';
        div.style.display = 'block';

        this.drawTopOverlay(position);
    };

    CustomOverlay.prototype.addTopOverlay = function addTopOverlay() {
        var topDiv, // HTMLElement
			map = this.get("map"),
			loadedMap = view.loadedMaps[map.mapContainer.id];

        if (this.overlayOnTop) {
            topDiv = document.createElement("div");
            topDiv.id = "topOverlay_" + map.mapContainer.id;

            this.set("topOverlay", topDiv);

            this.divOverlay.parentNode.parentNode.appendChild(topDiv);

            setTimeout(function () {
                map.set("overlayAdded", true);
                loadedMap.set("overlayAdded", true);
            }, 10);
        }
    };

    CustomOverlay.prototype.removeTopOverlay = function addTopOverlay() {
        if (this.overlayOnTop) {
            var topDiv = this.get("topOverlay");
            topDiv.parentNode.removeChild(topDiv);
        }
    };

    CustomOverlay.prototype.drawTopOverlay = function drawTopOverlay(position) {
        var topDiv = this.get("topOverlay");

        if (this.overlayOnTop) {
            topDiv.style.left = position.x + 'px';
            topDiv.style.top = position.y + 'px';
            topDiv.style.display = 'block';
        }
    };

    /* -- /CustomOverlay-- */

    view = {
        mapContainers: $(".googleMap"),
        loadedMaps: {},
        util: {
            getMapLatLng: function getLatLng(mapContainer) {
                var mapVars = view.loadedMaps[mapContainer.id].mapVars,
					lat = mapVars.lat,
					lng = mapVars.lng;
                return new google.maps.LatLng(lat, lng);
            },
            getMarkerLatLng: function getMarkerLatLng(lat, lng) {
                return new google.maps.LatLng(parseFloat(lat), parseFloat(lng));
            },
            getMarkerPixelPosition: function getMarkerPixelPosition(markerLatLng, map) {
                var jqMapContainer = $(map.mapContainer),
					getProjection = jqMapContainer.data("overlay").getProjection(),
					pixelLatLng = getProjection ? getProjection.fromLatLngToDivPixel(markerLatLng) : {
					    y: 0,
					    x: 0
					};
                return pixelLatLng;
            },
            getlatLngBounds: function getlatLngBounds(lat, lng) {
                return new google.maps.LatLngBounds(parseFloat(lat), parseFloat(lng));
            },
            getZoom: function getZoom(mapContainer) {
                var zoom = view.loadedMaps[mapContainer.id].mapVars.zoom || 4;
                return zoom;
            },
            removeMarkersWithoutCoords: function removeMarkersWithoutCoords(orgMarkersArray) {
                var markersArray = [], // array
					i, // number
					l = orgMarkersArray.length;

                for (i = 0; i < l; i += 1) {
                    if (orgMarkersArray[i].Type !== 8 && (parseFloat(orgMarkersArray[i].Latitude) && parseFloat(orgMarkersArray[i].Longitude))) {
                        markersArray.push(orgMarkersArray[i]);
                    }
                }
                return markersArray;
            },

            gerDestinationMarker: function gerDestinationMarker(destinationMarkerId, markers) {

                var i, // number (index)
					l = markers.length, // number (length)
					destinationMarker; // object

                for (i = 0; i < l; i += 1) {
                    if (markers[i].ID === destinationMarkerId) {
                        destinationMarker = markers[i];
                        break;
                    }
                }

                return destinationMarker;
            },

            calcRoute: function calcRoute(routeObject) {
                var from = routeObject.from,
					destination = routeObject.destination,
					directionsService = new google.maps.DirectionsService(),
					directionsDisplay = routeObject.directionsDisplay,

					loadedMap = routeObject.loadedMap,
					jqDirectionsPanel = loadedMap ? $("#directionsPanel_" + loadedMap.mapContainerId) : null,
					distanceSpan = jqDirectionsPanel.find("span.distance"),

					request = {
					    origin: from,
					    destination: destination,
					    travelMode: google.maps.TravelMode.DRIVING
					},

					distance; // string


                directionsService.route(request, function (result, status) {

                    if (status === google.maps.DirectionsStatus.OK) {

                        distance = result.routes[0].legs[0].distance.text;

                        distanceSpan.text(" " + distance + " ");

                        if (directionsDisplay) {
                            directionsDisplay.setDirections(result);
                        }

                        jqDirectionsPanel.find(".zeroResult").hide();
                        jqDirectionsPanel.find(".result").show();

                        loadedMap.set("routeIsCalculated", true);
                    }

                    if (status === google.maps.DirectionsStatus.ZERO_RESULTS) {

                        jqDirectionsPanel.find(".zeroResult").show();
                        jqDirectionsPanel.find(".result").hide();

                        loadedMap.set("routeIsCalculated", true);
                    }
                });
            },
            getFrom: function getFrom(loadedMap) {
                var geoMarker = loadedMap.geoMarker,
					latLng = view.util.getMarkerLatLng(geoMarker.Latitude, geoMarker.Longitude);
                return {
                    title: geoMarker.get("Title") || "Nuvarande plats",
                    latLng: latLng
                };
            },

            getDestination: function getDestination(loadedMap) {
                var destinationMarker = loadedMap.markers.getMarkersArray()[0],
					latLng = view.util.getMarkerLatLng(destinationMarker.Latitude, destinationMarker.Longitude);
                return {
                    title: destinationMarker.Title,
                    latLng: latLng
                };
            },
            getRegionName: function getRegionName(data, loadedMap) {

                var i, // number
					l = (data && data.length) ? data.length : 0, // number
					isLocalType, // boolean
					isPostalCode, // boolean
					fallBackRegionName, // string
					hasType = function getType(obj, type) {
					    var j, // number
							m = obj.types.length; // number
					    for (j = 0; j < m; j += 1) {
					        if (obj.types[j] === type) {
					            return true;
					        }
					    }
					    return false;
					},
					regionName; // string

                for (i = 0; i < l; i += 1) {
                    isLocalType = hasType(data[i], "locality");
                    isPostalCode = hasType(data[i], "postal_code");

                    if (isLocalType) {
                        regionName = data[i].formatted_address.toString();
                        break;
                    }

                    if (isPostalCode) {
                        fallBackRegionName = data[i].formatted_address.toString();
                    }
                }

                if (!regionName) {
                    regionName = fallBackRegionName;
                }

                if (!regionName) {
                    regionName = "\\u003f"; // \u003f = ?
                }

                loadedMap.set("regionName", regionName);

                return regionName;
            },
            /*setDestinationMethods : {
            geoLocationCallback : function geoLocationCallback() {
				
            } 
            },*/
            setDestination: function setDestination(loadedMap) {

                var jqDirectionsPanel = $("#directionsPanel_" + loadedMap.mapContainerId),
					geoMarker = loadedMap.get("geoMarker");

                loadedMap.set("routeIsCalculated", false);

                if (jqDirectionsPanel) {
                    loadedMap.set("hasDirectionsPanel", true);
                }

                $.runWhenTrue(function () {
                    jqDirectionsPanel = $("#directionsPanel_" + loadedMap.mapContainerId);
                    geoMarker = loadedMap.get("geoMarker");

                    return (jqDirectionsPanel.length && geoMarker && loadedMap.markers.getMarkersArray()[0]);
                }, function () {
                    var fromInput = jqDirectionsPanel.find("input.dirFrom"),
						destinationInput = jqDirectionsPanel.find("input.dirDestination"),

						fromSpan = jqDirectionsPanel.find("span.from"),
						destinationSpan = jqDirectionsPanel.find("span.destination"),

						fromObj = view.util.getFrom(loadedMap),
						destObj = view.util.getDestination(loadedMap),

						location = new google.maps.Geocoder(),

						directionsService = new google.maps.DirectionsService(),

						geoSearchResultList = document.getElementById("geoSearchResultList");

                    location.geocode({
                        location: fromObj.latLng
                    }, function (data) {

                        if (!data) {
                            setTimeout(function () {
                                view.util.setDestination(loadedMap);
                            }, 1000);
                            return;
                        }

                        var region, // string
							showSearchResults = new ExecQueue({
							    getRegion: (function (localData) {
							        return function getRegion() {
							            var that = this,
											getRegionName = function getRegionName(property, value) {
											    if (property && value) {
											        region = value;

											        if (region !== "no_name") {
											            that.set("ready", true);
											        }
											    }
											};

							            loadedMap.addListener("regionName", "change", getRegionName);

							            loadedMap.set("regionName", "no_name");

							            view.util.getRegionName(localData, loadedMap);
							        };
							    } (data)),
							    setFrom: function setFrom() {
							        var that = this;
							        fromInput.data("latLng", fromObj.latLng);
							        fromInput.val(region);

							        fromSpan.text(region + " ");

							        setTimeout(function () {
							            that.set("ready", true);
							        }, 0);

							    },
							    setDestination: function setDestination() {
							        var that = this;
							        destinationInput.data("latLng", destObj.latLng);
							        destinationInput.val(destObj.title);

							        destinationSpan.text(destObj.title + " ");

							        setTimeout(function () {
							            that.set("ready", true);
							        }, 0);
							    },
							    calcRoute: function calcRoute() {
							        var that = this;

							        view.util.calcRoute({
							            "loadedMap": loadedMap,
							            "from": fromObj.latLng,
							            "destination": destObj.latLng,
							            "directionsService": directionsService
							        });

							        setTimeout(function () {
							            that.set("ready", true);
							        }, 0);
							    }
							});

                        showSearchResults.exec();

                    });

                    if (geoSearchResultList) {
                        $(geoSearchResultList).remove();
                    }

                });
            },
            getDirections: function getDirections(e) {
                var that = this,
					mapContainerId = that.id.replace(/^[a-zA-Z]+\_/, ""),
					jqMapContainer = $("#" + mapContainerId),
					directionsPanel = jqMapContainer.parent().find(".directionsPanel"),

					from = directionsPanel.find(".dirFrom").data("latLng") || directionsPanel.find(".dirFrom").val(),
					destination = directionsPanel.find(".dirDestination").data("latLng") || directionsPanel.find(".dirDestination").val(),

					directionsService = jqMapContainer.data("directionsService"),
					directionsDisplay = jqMapContainer.data("directionsDisplay");

                e.preventDefault();

                view.util.calcRoute({
                    "from": from,
                    "destination": destination,
                    "directionsService": directionsService,
                    "directionsDisplay": directionsDisplay
                });
            },

            destinationGeoMarker: function destinationGeoMarker(loadedMap, position) {
                var geoMarker = {
                    CategoryDic: {
                        "geoMarker": "geo_marker"
                    },
                    Latitude: position.coords.latitude,
                    Longitude: position.coords.longitude,
                    Title: "You are here!"
                };

                loadedMap.setGeoMarker(geoMarker);
            },
            setManualFrom: {
                hide: function hide(selector) {
                    view.util.setManualFrom.jqDirectionsPanel.find(selector).hide();
                },
                show: function show(selector) {
                    view.util.setManualFrom.jqDirectionsPanel.find(selector).show();
                },
                get: function get(selector) {
                    return view.util.setManualFrom.jqDirectionsPanel.find(selector);
                },
                geoLocationEnabled: function geoLocationEnabled(jqDirectionsPanel) {
                    var panel = jqDirectionsPanel || view.util.setManualFrom.jqDirectionsPanel;
                    panel.find(".noGeoLocation").hide();
                },
                geoSearch: {
                    geoCoder: new google.maps.Geocoder(),
                    removePreviousResults: function removePreviousResults() {
                        var geoSearchResultList = document.getElementById("geoSearchResultList");

                        if (geoSearchResultList) {
                            geoSearchResultList.parentNode.removeChild(geoSearchResultList);
                        }
                    },
                    navigateSearchResults: {
                        getCurrentActiveLi: function currentActiveLi() {
                            return view.util.setManualFrom.geoSearch.getSearchResultList(true).find("li.focus");
                        },
                        getCurrentDirectionsPanel: function getCurrentDirectionsPanel(element) {
                            return $(element).closest(".directionsPanel");
                        },
                        setFrom: function setFrom(that) {
                            var currentActiveLi = view.util.setManualFrom.geoSearch.navigateSearchResults.getCurrentActiveLi(),
								name = currentActiveLi.find("input.name").val(),
								lat = parseFloat(currentActiveLi.find("input.lat").val()),
								lng = parseFloat(currentActiveLi.find("input.lng").val()),

								panel = view.util.setManualFrom.geoSearch.navigateSearchResults.getCurrentDirectionsPanel(that),

								loadedMap = view.loadedMaps[$.trim(panel.attr("id").match(/googleMap_\d+/g).join())];

                            if (name && lat && lng) {
                                loadedMap.setGeoMarker({
                                    CategoryDic: {
                                        geoMarker: "geo_marker"
                                    },
                                    Latitude: lat,
                                    Longitude: lng,
                                    Title: name
                                });

                                that.searchResultListHasFocus = false;

                                view.util.setDestination(loadedMap);
                            }
                        },
                        up: function up(that) {
                            var currentActiveLi = view.util.setManualFrom.geoSearch.navigateSearchResults.getCurrentActiveLi(),
								previous = currentActiveLi.get(0) ? currentActiveLi.get(0).previousSibling : null;

                            currentActiveLi.removeClass("focus");

                            if (previous) {
                                $(previous).addClass("focus");
                            } else {
                                that.searchResultListHasFocus = false;
                            }

                        },
                        down: function down() {
                            var currentActiveLi = view.util.setManualFrom.geoSearch.navigateSearchResults.getCurrentActiveLi(),
								next = currentActiveLi.get(0) ? currentActiveLi.get(0).nextSibling : null;

                            if (next) {
                                currentActiveLi.removeClass("focus");
                                $(next).addClass("focus");
                            }

                        },
                        moveToResultList: function moveToResultList() {
                            var that = this;

                            that.searchResultListHasFocus = true;

                            view.util.setManualFrom.geoSearch.getSearchResultList(true).find("li:first-child").addClass("focus");
                        },
                        eventHandler: function eventHandler(e) {
                            var that = this,
								keyCode = e.keyCode || 13;

                            if (!(/(13|38|40)/).test(keyCode)) {
                                that.searchResultListHasFocus = false;
                                view.util.setManualFrom.geoSearch.navigateSearchResults.getCurrentActiveLi().removeClass("focus");
                            }

                            switch (keyCode) {
                                case 40: // arrow down
                                    if (that.searchResultListHasFocus) {
                                        view.util.setManualFrom.geoSearch.navigateSearchResults.down();
                                    } else {
                                        view.util.setManualFrom.geoSearch.navigateSearchResults.moveToResultList.apply(that);
                                    }
                                    break;
                                case 38: // arrow up
                                    if (that.searchResultListHasFocus) {
                                        view.util.setManualFrom.geoSearch.navigateSearchResults.up(that);
                                    }
                                    break;
                                case 13:
                                    e.preventDefault();
                                    that.value = "";
                                    view.util.setManualFrom.geoSearch.navigateSearchResults.setFrom(that);
                                    view.util.setManualFrom.geoSearch.removePreviousResults();
                                    break;
                            }
                        },
                        addEventHandler: function addEventHandler(textInput) {
                            textInput.bind("keydown", view.util.setManualFrom.geoSearch.navigateSearchResults.eventHandler);
                        },
                        removeEventHandler: function removeEventHandler(textInput) {
                            textInput.unbind("keydown", view.util.setManualFrom.geoSearch.navigateSearchResults.eventHandler);
                        },
                        initNavigation: function (textInput) {
                            view.util.setManualFrom.geoSearch.navigateSearchResults.addEventHandler(textInput);
                        }
                    },

                    /**
                    * If jq is true return a jQueryCollection, if false return the element
                    * @param: jq {boolean}
                    */
                    getSearchResultList: function (jq) {
                        if (jq) {
                            return $("#geoSearchResultList");
                        } else {
                            return document.getElementById("geoSearchResultList");
                        }
                    },

                    createLi: function createLi(dataItem) {
                        var li = document.createElement("li"),
							lat = dataItem.geometry.location.lat(),
							lng = dataItem.geometry.location.lng(),
							inputClassValues = [
								["name", dataItem.formatted_address],
								["lat", lat],
								["lng", lng]
							],
							addInput = function addInput(element, classname, value) {
							    var newInput = document.createElement("input");
							    newInput.type = "hidden";
							    newInput.className = classname;
							    newInput.value = value;

							    element.appendChild(newInput);
							},
							addInputEach = function addInputEach() {
							    addInput(li, this[0], this[1]);
							};

                        li.innerHTML = dataItem.formatted_address;

                        each(inputClassValues, addInputEach);

                        return li;
                    },
                    setResult: function setResult(data) {
                        var ul = document.createElement("ul"),
							i, // number (index)
							l = data ? (data.length || 0) : 0, // number (length)
							textInput = $(view.util.setManualFrom.textInput),
							top = Math.round(textInput.offset().top + textInput.height() + 5), // number
							left = textInput.offset().left,

							triggerKeyDown = function () {
							    this.className = "focus";
							    textInput.trigger("keydown");
							};

                        view.util.setManualFrom.geoSearch.removePreviousResults();

                        ul.id = "geoSearchResultList";

                        $(ul).css({
                            position: "absolute",
                            top: top + "px",
                            left: left + "px",
                            zIndex: "1000000"
                        });

                        for (i = 0; i < l; i += 1) {
                            ul.appendChild(view.util.setManualFrom.geoSearch.createLi(data[i]));
                        }

                        if (ul.childNodes.length) {
                            document.body.appendChild(ul);
                        }

                        $(ul).find("li").click(triggerKeyDown);

                    },

                    search: function search(addressString) {

                        var geoCoder = view.util.setManualFrom.geoSearch.geoCoder;

                        geoCoder.geocode({
                            address: addressString
                        }, function (data) {
                            view.util.setManualFrom.geoSearch.setResult(data);
                        });
                    }
                },

                steps: new ExecQueue({
                    showManualForm: function showManualForm() {
                        var that = this;

                        view.util.setManualFrom.hide(".whereAreYou");
                        view.util.setManualFrom.hide(".shortDescription");

                        view.util.setManualFrom.show(".noGeoLocation");
                        view.util.setManualFrom.show(".hereIAm");

                        setTimeout(function () {
                            that.set("ready", true);
                        }, 0);
                    },
                    addGeoSearch: function addGeoSearch() {
                        var that = this,
							textInput = view.util.setManualFrom.get(".hereIAm input[type=text]"),
							keyDown = function (e) {
							    if ((/(13)/).test(e.keyCode)) {
							        e.preventDefault();
							    }
							},
							keyUp = function (e) {
							    var addressString = this.value;

							    if ((/(38|39|40|41)/).test(e.keyCode)) {
							        return;
							    }
							    view.util.setManualFrom.geoSearch.search(addressString);
							};

                        view.util.setManualFrom.textInput = textInput;

                        textInput.focus();

                        if (!textInput.data("hasSearchNav")) {

                            textInput.keydown(keyDown);
                            textInput.keyup(keyUp);

                            view.util.setManualFrom.geoSearch.navigateSearchResults.initNavigation(textInput);

                            textInput.data("hasSearchNav", true);
                        }

                        setTimeout(function () {
                            that.set("ready", true);
                        }, 0);
                    }
                }),

                initManualFrom: function initManualFrom(jqDirectionsPanel) {
                    view.util.setManualFrom.jqDirectionsPanel = jqDirectionsPanel;

                    var steps = view.util.setManualFrom.steps;

                    steps.exec();
                }
            },

            noGeolocation: function noGeolocation(jqDirectionsPanel, loadedMap) {
                jqDirectionsPanel.find(".loader").remove();

                jqDirectionsPanel.find(".whereAreYou").show().find("a").click(function (e) {
                    e.preventDefault();
                    view.util.setManualFrom.initManualFrom(jqDirectionsPanel, loadedMap);
                });
            },

            cancelSearch: {
                getJQDirectionsPanel: function getJQDirectionsPanel(that) {
                    return $(that).closest(".directionsPanel");
                },
                cancelWidthGeoLocation: function cancelWidthGeoLocation(e) {
                    e.preventDefault();
                    var jqDirectionsPanel = view.util.cancelSearch.getJQDirectionsPanel(this);

                    jqDirectionsPanel.find(".hereIAm").hide();
                    jqDirectionsPanel.find(".shortDescription").show();
                },
                cancelWidthoutGeoLocation: function cancelWidthoutGeoLocation(e) {
                    e.preventDefault();
                    var jqDirectionsPanel = view.util.cancelSearch.getJQDirectionsPanel(this);

                    jqDirectionsPanel.find(".hereIAm").hide();
                    jqDirectionsPanel.find(".whereAreYou").show();
                },
                addGeoEvent: function addGeoEvent(jqDirectionsPanel) {
                    jqDirectionsPanel.find(".hereIAm a").click(view.util.cancelSearch.cancelWidthGeoLocation);
                },
                addNoGeoEvent: function addNoGeoEvent(jqDirectionsPanel) {
                    jqDirectionsPanel.find(".hereIAm a").click(view.util.cancelSearch.cancelWidthoutGeoLocation);
                }
            },

            addGeolocation: function addGeolocation(mapHTMLElement) {
                var geo = window.navigator.geolocation,
					loadedMap = view.loadedMaps[mapHTMLElement.id], // object
					jqDirectionsPanel = $("#directionsPanel_" + mapHTMLElement.id);

                jqDirectionsPanel.find(".shortDescription").find("a").click(function (e) {
                    e.preventDefault();
                    view.util.setManualFrom.initManualFrom(jqDirectionsPanel, loadedMap);
                });

                if (geo) {

                    geo.getCurrentPosition(function (position) {

                        view.util.cancelSearch.addGeoEvent(jqDirectionsPanel);

                        view.util.destinationGeoMarker(loadedMap, position);

                        jqDirectionsPanel.find("loader").show();
                    }, function () {

                        view.util.cancelSearch.addNoGeoEvent(jqDirectionsPanel);

                        view.util.noGeolocation(jqDirectionsPanel, loadedMap);
                    }, {
                        maximumAge: Infinity,
                        timeout: 5000
                    });

                } else {
                    view.util.cancelSearch.addNoGeoEvent(jqDirectionsPanel);
                    view.util.noGeolocation(jqDirectionsPanel, loadedMap);
                }
            }
        },
        loader: {
            minutes: 0,
            waitMinutes: 3,
            countMinutes: function countMinutes() {
                var minute = 0.05,
					iv,
					count = function count() {
					    var currentMinutes = view.loader.get("minutes");

					    view.loader.set("minutes", parseInt(currentMinutes + 1, 10));

					    if (currentMinutes === view.loader.waitMinutes) {
					        clearInterval(iv);
					    }
					};

                iv = setInterval(count, (minute * 60000));

            },
            animateLoader: function animateLoader() {
                var that = this,
					t = $(that),
					spans = t.find("span"),
					currentSpan = 1,
					iv,
					anim = function anim() {

					    if (!that.parentNode) {
					        clearInterval(iv);
					    }

					    t.find("span:nth-child(" + currentSpan + ")").removeClass("active");

					    currentSpan += 1;

					    if (currentSpan === parseInt(spans.length + 1, 10)) {
					        currentSpan = 1;
					    }

					    t.find("span:nth-child(" + currentSpan + ")").addClass("active");

					};

                t.find("span:first-child").addClass("active");

                iv = setInterval(anim, 300);

            },

            initLoader: function initLoader(newDirectionsPanel) {
                if (!this.addListener) {
                    ListenerObject.apply(this);
                }

                view.loader.addListener("minutes", "change", function (property, value) {

                    if (property && value === view.loader.waitMinutes) {

                        var panel = $(newDirectionsPanel),
							loader = panel.find(".loader");

                        if (loader.length) {
                            view.util.noGeolocation(panel);
                        }
                    }
                });

                view.loader.countMinutes();

                $(newDirectionsPanel).find(".loader").each(view.loader.animateLoader);
            }
        },
        initMap: {
            addOverlay: function addOverlay(mapContainer, newMap) {
                $(mapContainer).data("overlay", new CustomOverlay({
                    map: newMap
                }));
            },
            checkCalculatedRoute: function checkCalculatedRoute(property, value) {
                if (property && value) {
                    var that = this,
						panel = $(that.get("directionsPanel"));

                    panel.addClass("hasGeoLocation");

                    panel.find(".noGeoLocation").hide();

                    panel.find(".loader").remove();
                    panel.find(".shortDescription").show();

                    this.set("routeIsCalculated", false);
                }
            },
            addDirectionsPanel: function addDirectionsPanel(mapContainer, newMap) {
                var jqMapContainer = $(mapContainer),
					directionsService = new google.maps.DirectionsService(),
					directionsDisplay = new google.maps.DirectionsRenderer({
					    draggable: true,
					    map: newMap,
					    suppressMarkers: true
					}),
					loadedMap = view.loadedMaps[mapContainer.id],
					mapVars = loadedMap.mapVars,
					directionsPanel, // HTMLElement
					newDirectionsPanel; // HTMLElement


                jqMapContainer.data("directionsService", directionsService);
                jqMapContainer.data("directionsDisplay", directionsDisplay);

                /* -- routeIsCalculated -- */
                loadedMap.set("routeIsCalculated", false);

                loadedMap.addListener("routeIsCalculated", "change", view.initMap.checkCalculatedRoute);

                /* -- /routeIsCalculated -- */

                if (mapVars.showDirectionsPanel) {

                    setTimeout(function () {
                        directionsPanel = mapVars.directionsPanelHTML;
                        newDirectionsPanel = directionsPanel.cloneNode(true);
                        newDirectionsPanel.id = "directionsPanel_" + mapContainer.id;

                        loadedMap.set("directionsPanel", newDirectionsPanel);

                        mapContainer.parentNode.appendChild(newDirectionsPanel);

                        $(newDirectionsPanel).find(".hereIAm input[type=text]").attr("id", "hereIAmInput_" + mapContainer.id);

                        view.loader.initLoader(newDirectionsPanel);
                        view.util.addGeolocation(mapContainer);

                        directionsDisplay.setMap(newMap);
                        directionsDisplay.setPanel(newDirectionsPanel);

                        if (loadedMap.mapVars.destination) {
                            view.util.setDestination(loadedMap);
                        }

                        $(newDirectionsPanel).find("button").attr("id", "directionsPanelButton_" + mapContainer.id).click(view.util.getDirections);

                    }, 0);
                }
            },
            addMouseEvents: function addMouseEvents(mapContainer, newMap) {
                newMap.mapMouseState = null;
                $(mapContainer).mousedown(function () {
                    newMap.mapMouseState = 'DOWN';
                }).mouseup(function () {
                    newMap.mapMouseState = 'UP';
                });
            }
        },
        markers: {
            callback: function callback(data, loadedMap) {
                var filterMarkers = view.util.removeMarkersWithoutCoords(data.Markers),
					destinationMarker, // object (marker)
					clusterSize = 2,
					destinationMarkerSet = false,
					triggerChangeEventOnMarkersReady = function triggerChangeEventOnMarkersReady(property, value) {
					    if (property && value) {
					        google.maps.event.trigger(loadedMap.map, "zoom_changed");
					        google.maps.event.trigger(loadedMap.map, "bounds_changed");

					        $(loadedMap.mapContainer).addClass("ready");

					        loadedMap.removeListener("markersReady", "change", triggerChangeEventOnMarkersReady);
					    }
					},
					setDestinationMarker = function setDestinationMarker(marker) {
					    var destinationLatLng = marker.getPosition();

					    if (!destinationMarkerSet) {
					        loadedMap.map.setCenter(destinationLatLng);
					    }
					};

                loadedMap.set("markersReady", false);

                if (loadedMap.mapVars.destination && filterMarkers.length > 1) {
                    destinationMarker = view.util.gerDestinationMarker(loadedMap.mapVars.destination, filterMarkers);

                    loadedMap.addMarkers([destinationMarker]);
                } else {
                    loadedMap.addMarkers(filterMarkers);
                }

                if (!loadedMap.getMapVar("clustermarkers")) {
                    clusterSize = Math.round(filterMarkers.length * 2);
                }

                if (MarkerClusterer) {
                    loadedMap.set("markerClusterer", new MarkerClusterer(loadedMap.map, loadedMap.get("markers").getMarkersArray(), {
                        mapContainerId: loadedMap.mapContainerId
                    }));

                    loadedMap.get("markerClusterer").setMinClusterSize(clusterSize);
                }

                if (loadedMap.mapVars.destination) {
                    loadedMap.markers.forEach(setDestinationMarker);
                }

                loadedMap.addListener("markersReady", "change", triggerChangeEventOnMarkersReady);
            },
            loadedMapVars: function loadedMapVars(loadedMap) {
                var mapVars = loadedMap.mapVars,
					newMapVars = {},
					k;
                for (k in mapVars) {
                    if (mapVars.hasOwnProperty(k)) {
                        newMapVars[k] = mapVars[k];
                    }
                }
                return newMapVars;
            },
            ajaxRequest: function ajaxRequest(mapVars, loadedMap) {
                $.model.addToQueue(false, ["LoadSpecificMarkers", {
                    poiIds: mapVars.destination || mapVars.markerIds,
                    lat: mapVars.lat.toString(),
                    lng: mapVars.lng.toString(),
                    zoom: mapVars.zoom,
                    lang: mapVars.language
                }], function (data) {
                    view.markers.callback(data, loadedMap);
                });
            },
            ajaxRequest_0: function ajaxRequest(mapVars, loadedMap) {
                $.model.addToQueue(false, ["LoadMarkers", {
                    pageId: 150,
                    lang: mapVars.language
                }], function (data) {
                    view.markers.callback(data, loadedMap);
                });
            },
            get: function get(mapContainer) {
                var loadedMap = view.loadedMaps[mapContainer.id],
					mapVars = view.markers.loadedMapVars(loadedMap);

                view.markers.ajaxRequest(mapVars, loadedMap);
            }
        },

        createMap: function createMap(mapContainer) {
            var newMap = new google.maps.Map(mapContainer, {
                zoom: view.util.getZoom(mapContainer),
                center: view.util.getMapLatLng(mapContainer),
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                mapContainer: mapContainer,
                maxZoom: 20
            });

            $(mapContainer).data("map", newMap);

            view.loadedMaps[mapContainer.id].set("map", newMap);

            view.loadedMaps[mapContainer.id].set("hasMap", true);

            view.initMap.addOverlay(mapContainer, newMap);
            view.markers.get(mapContainer);

            view.initMap.addDirectionsPanel(mapContainer, newMap);
        },
        init: {
            setMapsProperties: function setMapsProperties() {
                var t = this,
					setMapProperties = function () {
					    var that = this,
							newId = $.uniqueId("googleMap_");

					    that.id = newId;

					    view.loadedMaps[newId] = new MapObject({
					        mapContainer: that
					    });
					};

                view.mapContainers.each(setMapProperties);

                setTimeout(function () {
                    t.set("ready", true);
                }, 0);
            },
            storeMapsVars: function storeMapsVars() {
                var t = this,

					storeMapVars = function storeMapVars() {
					    var that = this,
							t = $(this),

							loadedMap = view.loadedMaps[that.id],
							inputs = t.find("> input[type=hidden]"),

							getMapVarsFromInputs = function getMapVarsFromInputs() {
							    var input = this,
									propertyName = input.className.replace(/(\s)?(string|number|boolean)(\s)?/g, "").replace(/(^\s+|\s+$)/g, ""),
									propertyTypeCheck = input.className.match(/(\s)?(string|number|boolean)(\s)?/g),
									propertyType = propertyTypeCheck ? propertyTypeCheck.join().replace(/(^\s+|\s+$)/g, "") : "";

							    t.data(propertyName, input.value);

							    // add the property value as the appropriate type (boolean, number or string)
							    if (propertyType && propertyType === "string") {
							        loadedMap.setMapVar(propertyName, input.value);
							    } else if (propertyType && propertyType === "number") {
							        if (isFloat(input.value)) {
							            loadedMap.setMapVar(propertyName, parseFloat(input.value));
							        } else {
							            loadedMap.setMapVar(propertyName, parseInt(input.value, 10));
							        }
							    } else if (isFloat(input.value)) {
							        loadedMap.setMapVar(propertyName, parseFloat(input.value));
							    } else if (isInt(input.value)) {
							        loadedMap.setMapVar(propertyName, parseInt(input.value, 10));
							    } else if (isBoolean(input.value) || (propertyType && propertyType === "boolean")) {
							        if ((/^true$/i).test(input.value)) {
							            loadedMap.setMapVar(propertyName, true);
							        } else {
							            loadedMap.setMapVar(propertyName, false);
							        }
							    } else {
							        loadedMap.setMapVar(propertyName, input.value);
							    }

							};


					    inputs.each(getMapVarsFromInputs);
					};

                view.mapContainers.each(storeMapVars);

                setTimeout(function () {
                    t.set("ready", true);
                }, 0);
            },
            getCustomPoisHTML: function getCustomPoisHTML() {
                var t = this,
					getCustomPoiHTML = function getCustomPoiHTML() {
					    var that = this,
							t = $(that),
							poiHTML = t.find(".customPoi");

					    if (poiHTML.length) {
					        t.data("customPoiHTML", poiHTML.get(0));
					    }
					};

                view.mapContainers.each(getCustomPoiHTML);

                setTimeout(function () {
                    t.set("ready", true);
                }, 0);
            },
            getDirectionsPanels: function getDirectionsPanels() {
                var t = this,
					getDirectionsPanel = function getDirectionsPanel() {
					    var that = this,
							t = $(that),
							poiHTML = t.find(".directionsPanel");

					    if (poiHTML.length) {
					        view.loadedMaps[that.id].mapVars.directionsPanelHTML = poiHTML.get(0);
					    }
					};

                view.mapContainers.each(getDirectionsPanel);

                setTimeout(function () {
                    t.set("ready", true);
                }, 0);
            },
            createMaps: function createMaps() {
                var t = this,
					mapQueueObject = {},
					mapQueue,
					createMap = function createMap() {
					    var that = this;

					    mapQueueObject[that.id] = function createMap() {
					        var ths = this,
								mapContainerId = that.id,
								loadedMap = view.loadedMaps[mapContainerId],
								nextMap = function nextMap(property, value) {
								    if (property && value) {
								        loadedMap.removeListener("markersReady", "change", nextMap);

								        setTimeout(function () {
								            ths.set("ready", true);
								        }, 500);
								    }
								};

					        loadedMap.addListener("markersReady", "change", nextMap);

					        view.createMap(that);
					    };
					};

                view.mapContainers.each(createMap);

                mapQueue = new ExecQueue(mapQueueObject);
                ListenerObject.apply(mapQueue);

                mapQueue.addListener("ready", "change", function () {
                    setTimeout(function () {
                        t.set("ready", true);
                    }, 0);
                });

                mapQueue.exec();
            },
            hoverLabel: function () {
                var t = this,
					setLabelWidthInIE7 = function setLabelWidthInIE7(that) {
					    var getLabelWidth = function getLabelWidth() {
					        var label = this,
								clone = label.cloneNode(true),
								labelWidth; // number

					        clone.className = "testClone";
					        document.body.appendChild(clone);

					        labelWidth = clone.offsetWidth;

					        $(label).closest(".text").css("width", labelWidth + "px");

					        document.body.removeChild(clone);
					    };

					    $(that).find(".labelText").each(getLabelWidth);
					},
					mouseover = function mouseover() {
					    setLabelWidthInIE7(this);
					    $(this).addClass("hover");
					},
					mouseout = function mouseout() {
					    $(this).removeClass("hover");
					};

                if ($.isIE7) {
                    $("div.googleMap").delegate("div.customPoi", "mouseover", mouseover).delegate("div.customPoi", "mouseout", mouseout);
                }

                setTimeout(function () {
                    t.set("ready", true);
                }, 0);
            }
        }
    };

    $(document).ready(function () {
        var initQueue = new ExecQueue(view.init);

        initQueue.exec();

        if (document.domain === "visit.local") {
            window.AAA_loadedMaps = view.loadedMaps;
        }
    });
} (window));
