

;

/** * @name MarkerClusterer * @version 1.0 * @author Xiaoxi Wu * @copyright (c) 2009 Xiaoxi Wu * @fileoverview * This javascript library creates and manages per-zoom-level  * clusters for large amounts of markers (hundreds or thousands). * This library was inspired by the <a href="http://www.maptimize.com"> * Maptimize</a> hosted clustering solution. * <br /><br/> * <b>How it works</b>:<br/> * The <code>MarkerClusterer</code> will group markers into clusters according to * their distance from a cluster's center. When a marker is added, * the marker cluster will find a position in all the clusters, and  * if it fails to find one, it will create a new cluster with the marker. * The number of markers in a cluster will be displayed * on the cluster marker. When the map viewport changes, * <code>MarkerClusterer</code> will destroy the clusters in the viewport  * and regroup them into new clusters. * *//* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//** * @name MarkerClustererOptions * @class This class represents optional arguments to the {@link MarkerClusterer} * constructor. * @property {Number} [maxZoom] The max zoom level monitored by a * marker cluster. If not given, the marker cluster assumes the maximum map * zoom level. When maxZoom is reached or exceeded all markers will be shown * without cluster. * @property {Number} [gridSize=60] The grid size of a cluster in pixel. Each * cluster will be a square. If you want the algorithm to run faster, you can set * this value larger. * @property {Array of MarkerStyleOptions} [styles] * Custom styles for the cluster markers. * The array should be ordered according to increasing cluster size, * with the style for the smallest clusters first, and the style for the * largest clusters last. *//** * @name MarkerStyleOptions * @class An array of these is passed into the {@link MarkerClustererOptions} * styles option. * @property {String} [url] Image url. * @property {Number} [height] Image height. * @property {Number} [height] Image width. * @property {Array of Number} [opt_anchor] Anchor for label text, like [24, 12].  *    If not set, the text will align center and middle. * @property {String} [opt_textColor="black"] Text color. *//** * Creates a new MarkerClusterer to cluster markers on the map. * * @constructor * @param {GMap2} map The map that the markers should be added to. * @param {Array of GMarker} opt_markers Initial set of markers to be clustered. * @param {MarkerClustererOptions} opt_opts A container for optional arguments. */function MarkerClusterer(map, opt_markers, opt_opts) {  // private members  var clusters_ = [];  var map_ = map;  var maxZoom_ = 7;  var me_ = this;  var gridSize_ = 30;  var sizes = [53, 56, 66, 78, 90];  var styles_ = [];  var leftMarkers_ = [];  var mcfn_ = null;  var i = 0;  for (i = 1; i <= 5; ++i) {    styles_.push({      'url': "/static/img/b" + 1 + ".png",      'height': 45,      'width': 58    });  }//sizes[i - 1]  if (typeof opt_opts === "object" && opt_opts !== null) {    if (typeof opt_opts.gridSize === "number" && opt_opts.gridSize > 0) {      gridSize_ = opt_opts.gridSize;    }    if (typeof opt_opts.maxZoom === "number") {      maxZoom_ = opt_opts.maxZoom;    }    if (typeof opt_opts.styles === "object" && opt_opts.styles !== null && opt_opts.styles.length !== 0) {      styles_ = opt_opts.styles;    }  }  /**   * When we add a marker, the marker may not in the viewport of map, then we don't deal with it, instead   * we add the marker into a array called leftMarkers_. When we reset MarkerClusterer we should add the   * leftMarkers_ into MarkerClusterer.   */  function addLeftMarkers_() {    if (leftMarkers_.length === 0) {      return;    }    var leftMarkers = [];    for (i = 0; i < leftMarkers_.length; ++i) {      me_.addMarker(leftMarkers_[i], true, null, null, true);    }    leftMarkers_ = leftMarkers;  }  /**   * Get cluster marker images of this marker cluster. Mostly used by {@link Cluster}   * @private   * @return {Array of String}   */  this.getStyles_ = function () {    return styles_;  };  /**   * Remove all markers from MarkerClusterer.   */  this.clearMarkers = function () {    for (var i = 0; i < clusters_.length; ++i) {      if (typeof clusters_[i] !== "undefined" && clusters_[i] !== null) {        clusters_[i].clearMarkers();      }    }    clusters_ = [];    leftMarkers_ = [];    GEvent.removeListener(mcfn_);  };  /**   * Check a marker, whether it is in current map viewport.   * @private   * @return {Boolean} if it is in current map viewport   */  function isMarkerInViewport_(marker) {    return map_.getBounds().containsLatLng(marker.getLatLng());  }  /**   * When reset MarkerClusterer, there will be some markers get out of its cluster.   * These markers should be add to new clusters.   * @param {Array of GMarker} markers Markers to add.   */  function reAddMarkers_(markers) {    var len = markers.length;    var clusters = [];    for (var i = len - 1; i >= 0; --i) {      me_.addMarker(markers[i].marker, true, markers[i].isAdded, clusters, true);    }    addLeftMarkers_();  }  /**   * Add a marker.   * @private   * @param {GMarker} marker Marker you want to add   * @param {Boolean} opt_isNodraw Whether redraw the cluster contained the marker   * @param {Boolean} opt_isAdded Whether the marker is added to map. Never use it.   * @param {Array of Cluster} opt_clusters Provide a list of clusters, the marker   *     cluster will only check these cluster where the marker should join.   */  this.addMarker = function (marker, opt_isNodraw, opt_isAdded, opt_clusters, opt_isNoCheck) {    if (opt_isNoCheck !== true) {      if (!isMarkerInViewport_(marker)) {        leftMarkers_.push(marker);        return;      }    }    var isAdded = opt_isAdded;    var clusters = opt_clusters;    var pos = map_.fromLatLngToDivPixel(marker.getLatLng());    if (typeof isAdded !== "boolean") {      isAdded = false;    }    if (typeof clusters !== "object" || clusters === null) {      clusters = clusters_;    }    var length = clusters.length;    var cluster = null;    for (var i = length - 1; i >= 0; i--) {      cluster = clusters[i];      var center = cluster.getCenter();      if (center === null) {        continue;      }      center = map_.fromLatLngToDivPixel(center);      // Found a cluster which contains the marker.      if (pos.x >= center.x - gridSize_ && pos.x <= center.x + gridSize_ &&          pos.y >= center.y - gridSize_ && pos.y <= center.y + gridSize_) {        cluster.addMarker({          'isAdded': isAdded,          'marker': marker        });        if (!opt_isNodraw) {          cluster.redraw_();        }        return;      }    }    // No cluster contain the marker, create a new cluster.    cluster = new Cluster(this, map);    cluster.addMarker({      'isAdded': isAdded,      'marker': marker    });    if (!opt_isNodraw) {      cluster.redraw_();    }    // Add this cluster both in clusters provided and clusters_    clusters.push(cluster);    if (clusters !== clusters_) {      clusters_.push(cluster);    }  };  /**   * Remove a marker.   *   * @param {GMarker} marker The marker you want to remove.   */  this.removeMarker = function (marker) {    for (var i = 0; i < clusters_.length; ++i) {      if (clusters_[i].remove(marker)) {        clusters_[i].redraw_();        return;      }    }  };  /**   * Redraw all clusters in viewport.   */  this.redraw_ = function () {    var clusters = this.getClustersInViewport_();    for (var i = 0; i < clusters.length; ++i) {      clusters[i].redraw_(true);    }  };  /**   * Get all clusters in viewport.   * @return {Array of Cluster}   */  this.getClustersInViewport_ = function () {    var clusters = [];    var curBounds = map_.getBounds();    for (var i = 0; i < clusters_.length; i ++) {      if (clusters_[i].isInBounds(curBounds)) {        clusters.push(clusters_[i]);      }    }    return clusters;  };  /**   * Get max zoom level.   * @private   * @return {Number}   */  this.getMaxZoom_ = function () {    return maxZoom_;  };  /**   * Get map object.   * @private   * @return {GMap2}   */  this.getMap_ = function () {    return map_;  };  /**   * Get grid size   * @private   * @return {Number}   */  this.getGridSize_ = function () {    return gridSize_;  };  /**   * Get total number of markers.   * @return {Number}   */  this.getTotalMarkers = function () {    var result = 0;    for (var i = 0; i < clusters_.length; ++i) {      result += clusters_[i].getTotalMarkers();    }    return result;  };  /**   * Get total number of clusters.   * @return {int}   */  this.getTotalClusters = function () {    return clusters_.length;  };  /**   * Collect all markers of clusters in viewport and regroup them.   */  this.resetViewport = function () {    var clusters = this.getClustersInViewport_();    var tmpMarkers = [];    var removed = 0;    for (var i = 0; i < clusters.length; ++i) {      var cluster = clusters[i];      var oldZoom = cluster.getCurrentZoom();      if (oldZoom === null) {        continue;      }      var curZoom = map_.getZoom();      if (curZoom !== oldZoom) {        // If the cluster zoom level changed then destroy the cluster        // and collect its markers.        var mks = cluster.getMarkers();        for (var j = 0; j < mks.length; ++j) {          var newMarker = {            'isAdded': false,            'marker': mks[j].marker          };          tmpMarkers.push(newMarker);        }        cluster.clearMarkers();        removed++;        for (j = 0; j < clusters_.length; ++j) {          if (cluster === clusters_[j]) {            clusters_.splice(j, 1);          }        }      }    }    // Add the markers collected into marker cluster to reset    reAddMarkers_(tmpMarkers);    this.redraw_();  };  /**   * Add a set of markers.   *   * @param {Array of GMarker} markers The markers you want to add.   */  this.addMarkers = function (markers) {    for (var i = 0; i < markers.length; ++i) {      this.addMarker(markers[i], true);    }    this.redraw_();  };  // initialize  if (typeof opt_markers === "object" && opt_markers !== null) {    this.addMarkers(opt_markers);  }  // when map move end, regroup.  mcfn_ = GEvent.addListener(map_, "moveend", function () {    me_.resetViewport();  });}/** * Create a cluster to collect markers. * A cluster includes some markers which are in a block of area. * If there are more than one markers in cluster, the cluster * will create a {@link ClusterMarker_} and show the total number * of markers in cluster. * * @constructor * @private * @param {MarkerClusterer} markerClusterer The marker cluster object */function Cluster(markerClusterer) {  var center_ = null;  var markers_ = [];  var markerClusterer_ = markerClusterer;  var map_ = markerClusterer.getMap_();  var clusterMarker_ = null;  var zoom_ = map_.getZoom();  /**   * Get markers of this cluster.   *   * @return {Array of GMarker}   */  this.getMarkers = function () {    return markers_;  };  /**   * If this cluster intersects certain bounds.   *   * @param {GLatLngBounds} bounds A bounds to test   * @return {Boolean} Is this cluster intersects the bounds   */  this.isInBounds = function (bounds) {    if (center_ === null) {      return false;    }    if (!bounds) {      bounds = map_.getBounds();    }    var sw = map_.fromLatLngToDivPixel(bounds.getSouthWest());    var ne = map_.fromLatLngToDivPixel(bounds.getNorthEast());    var centerxy = map_.fromLatLngToDivPixel(center_);    var inViewport = true;    var gridSize = markerClusterer.getGridSize_();    if (zoom_ !== map_.getZoom()) {      var dl = map_.getZoom() - zoom_;      gridSize = Math.pow(2, dl) * gridSize;    }    if (ne.x !== sw.x && (centerxy.x + gridSize < sw.x || centerxy.x - gridSize > ne.x)) {      inViewport = false;    }    if (inViewport && (centerxy.y + gridSize < ne.y || centerxy.y - gridSize > sw.y)) {      inViewport = false;    }    return inViewport;  };  /**   * Get cluster center.   *   * @return {GLatLng}   */  this.getCenter = function () {    return center_;  };  /**   * Add a marker.   *   * @param {Object} marker An object of marker you want to add:   *   {Boolean} isAdded If the marker is added on map.   *   {GMarker} marker The marker you want to add.   */  this.addMarker = function (marker) {    if (center_ === null) {      /*var pos = marker['marker'].getLatLng();       pos = map.fromLatLngToContainerPixel(pos);       pos.x = parseInt(pos.x - pos.x % (GRIDWIDTH * 2) + GRIDWIDTH);       pos.y = parseInt(pos.y - pos.y % (GRIDWIDTH * 2) + GRIDWIDTH);       center = map.fromContainerPixelToLatLng(pos);*/      center_ = marker.marker.getLatLng();    }    markers_.push(marker);  };  /**   * Remove a marker from cluster.   *   * @param {GMarker} marker The marker you want to remove.   * @return {Boolean} Whether find the marker to be removed.   */  this.removeMarker = function (marker) {    for (var i = 0; i < markers_.length; ++i) {      if (marker === markers_[i].marker) {        if (markers_[i].isAdded) {          map_.removeOverlay(markers_[i].marker);        }        markers_.splice(i, 1);        return true;      }    }    return false;  };  /**   * Get current zoom level of this cluster.   * Note: the cluster zoom level and map zoom level not always the same.   *   * @return {Number}   */  this.getCurrentZoom = function () {    return zoom_;  };  /**   * Redraw a cluster.   * @private   * @param {Boolean} isForce If redraw by force, no matter if the cluster is   *     in viewport.   */  this.redraw_ = function (isForce) {    if (!isForce && !this.isInBounds()) {      return;    }    // Set cluster zoom level.    zoom_ = map_.getZoom();    var i = 0;    var mz = markerClusterer.getMaxZoom_();    if (mz === null) {      mz = map_.getCurrentMapType().getMaximumResolution();    }    if (zoom_ >= mz || this.getTotalMarkers() === 1) {      // If current zoom level is beyond the max zoom level or the cluster      // have only one marker, the marker(s) in cluster will be showed on map.      for (i = 0; i < markers_.length; ++i) {        if (markers_[i].isAdded) {          if (markers_[i].marker.isHidden()) {            markers_[i].marker.show();          }        } else {          map_.addOverlay(markers_[i].marker);          markers_[i].isAdded = true;        }      }      if (clusterMarker_ !== null) {        clusterMarker_.hide();      }    } else {      // Else add a cluster marker on map to show the number of markers in      // this cluster.      for (i = 0; i < markers_.length; ++i) {        if (markers_[i].isAdded && (!markers_[i].marker.isHidden())) {          markers_[i].marker.hide();        }      }      if (clusterMarker_ === null) {        clusterMarker_ = new ClusterMarker_(center_, this.getTotalMarkers(), markerClusterer_.getStyles_(), markerClusterer_.getGridSize_());        map_.addOverlay(clusterMarker_);      } else {        if (clusterMarker_.isHidden()) {          clusterMarker_.show();        }        clusterMarker_.redraw(true);      }    }  };  /**   * Remove all the markers from this cluster.   */  this.clearMarkers = function () {    if (clusterMarker_ !== null) {      map_.removeOverlay(clusterMarker_);    }    for (var i = 0; i < markers_.length; ++i) {      if (markers_[i].isAdded) {        map_.removeOverlay(markers_[i].marker);      }    }    markers_ = [];  };  /**   * Get number of markers.   * @return {Number}   */  this.getTotalMarkers = function () {    return markers_.length;  };}/** * ClusterMarker_ creates a marker that shows the number of markers that * a cluster contains. * * @constructor * @private * @param {GLatLng} latlng Marker's lat and lng. * @param {Number} count Number to show. * @param {Array of Object} styles The image list to be showed: *   {String} url Image url. *   {Number} height Image height. *   {Number} width Image width. *   {Array of Number} anchor Text anchor of image left and top. *   {String} textColor text color. * @param {Number} padding Padding of marker center. */function ClusterMarker_(latlng, count, styles, padding) {  var index = 0;  var dv = count;  while (dv !== 0) {    dv = parseInt(dv / 10, 10);    index ++;  }  if (styles.length < index) {    index = styles.length;  }  this.url_ = styles[index - 1].url;  this.height_ = styles[index - 1].height;  this.width_ = styles[index - 1].width;  this.textColor_ = styles[index - 1].opt_textColor;  this.anchor_ = styles[index - 1].opt_anchor;  this.latlng_ = latlng;  this.index_ = index;  this.styles_ = styles;  this.text_ = count;  this.padding_ = padding;}ClusterMarker_.prototype = new GOverlay();/** * Initialize cluster marker. * @private */ClusterMarker_.prototype.initialize = function (map) {  this.map_ = map;  var div = document.createElement("div");  var latlng = this.latlng_;  var pos = map.fromLatLngToDivPixel(latlng);  pos.x -= parseInt(this.width_ / 2, 10);  pos.y -= parseInt(this.height_ / 2, 10);      var mstyle = "";  if (document.all) {    mstyle = 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src="' + this.url_ + '");';  } else {    mstyle = "background:url(" + this.url_ + ");";  }  if (typeof this.anchor_ === "object") {    if (typeof this.anchor_[0] === "number" && this.anchor_[0] > 0 && this.anchor_[0] < this.height_) {      mstyle += 'height:' + (this.height_ - this.anchor_[0]) + 'px;padding-top:' + this.anchor_[0] + 'px;';    } else {      mstyle += 'height:' + this.height_ + 'px;line-height:' + this.height_ + 'px;';    }    if (typeof this.anchor_[1] === "number" && this.anchor_[1] > 0 && this.anchor_[1] < this.width_) {      mstyle += 'width:' + (this.width_ - this.anchor_[1]) + 'px;padding-left:' + this.anchor_[1] + 'px;';    } else {      mstyle += 'width:' + this.width_ + 'px;text-align:center;';    }  } else {    mstyle += 'height:' + this.height_ + 'px;line-height:' + this.height_ + 'px;';    mstyle += 'width:' + this.width_ + 'px;text-align:center;';  }  var txtColor = this.textColor_ ? this.textColor_ : 'black';  div.style.cssText = mstyle + 'cursor:pointer;top:' + pos.y + "px;left:" +      pos.x + "px;color:" + txtColor +  ";position:absolute;font-size:11px;" +      'font-family:Arial,sans-serif;font-weight:bold';  div.innerHTML = this.text_;  map.getPane(G_MAP_MAP_PANE).appendChild(div);  var padding = this.padding_;  GEvent.addDomListener(div, "click", function () {    var pos = map.fromLatLngToDivPixel(latlng);    var sw = new GPoint(pos.x - padding, pos.y + padding);    sw = map.fromDivPixelToLatLng(sw);    var ne = new GPoint(pos.x + padding, pos.y - padding);    ne = map.fromDivPixelToLatLng(ne);    var zoom = map.getBoundsZoomLevel(new GLatLngBounds(sw, ne), map.getSize());    map.setCenter(latlng, zoom);  });  this.div_ = div;};/** * Remove this overlay. * @private */ClusterMarker_.prototype.remove = function () {  this.div_.parentNode.removeChild(this.div_);};/** * Copy this overlay. * @private */ClusterMarker_.prototype.copy = function () {  return new ClusterMarker_(this.latlng_, this.index_, this.text_, this.styles_, this.padding_);};/** * Redraw this overlay. * @private */ClusterMarker_.prototype.redraw = function (force) {  if (!force) {    return;  }  var pos = this.map_.fromLatLngToDivPixel(this.latlng_);  pos.x -= parseInt(this.width_ / 2, 10);  pos.y -= parseInt(this.height_ / 2, 10);  this.div_.style.top =  pos.y + "px";  this.div_.style.left = pos.x + "px";};/** * Hide this cluster marker. */ClusterMarker_.prototype.hide = function () {  this.div_.style.display = "none";};/** * Show this cluster marker. */ClusterMarker_.prototype.show = function () {  this.div_.style.display = "";};/** * Get whether the cluster marker is hidden. * @return {Boolean} */ClusterMarker_.prototype.isHidden = function () {  return this.div_.style.display === "none";};

;

var KlokhuisMap = ( function() {		var _mapNode = false;	var _map = false;		var _manager = false;	var _lat = 52.27488013068053;	var _lon = 5.306396484375;	var _zoom = 8;	var _dataUrl = '/xml_map';	var _data = [];	var _markers = [];	var _domain = '';		var init = function( config ) {				config = config || {};				_dataUrl = config.url || _dataUrl;				_mapNode = document.getElementById('map');				if ( GBrowserIsCompatible() ) {						window.onunload = GUnload;						_map = new GMap2( _mapNode, G_PHYSICAL_MAP );			_map.setCenter( new GLatLng( _lat, _lon ), _zoom );			_map.setUIToDefault();			_map.setMapType( G_PHYSICAL_MAP );			_map.enableDoubleClickZoom();									load();		}			};		var getIcon = function( path ) {				var icon = new GIcon( G_DEFAULT_ICON );					icon.image = '/static/img/smallmarker.png';			icon.iconSize = new GSize( 31, 30 );			icon.iconAnchor = new GPoint( 11, 26 );			icon.shadow = '/static/img/smallmarkershadow.png';			icon.shadowSize = new GSize( 31, 30 );       		return icon;	};		var getWindowHtml = function(data) {			function delimiter(t,num) {			if ( t < num ) { return ", "; }			return "";		}				var tags = data.tags;		var numTags = tags.length;		var max = numTags - 1;				var anchorStart = '<a href="'+ data.stream + '" onclick="openStream( this.href ); return false;">';				var html = '<div class="marker-info">';			html += '<h4>' + anchorStart + data.title + '</a><\/h4>';			html += '<p class="published">' + data.onair + '<\/p>';			html += anchorStart + '<img src="' + _domain + data.image + '" /></a>';			html += '<p>' + data.description + '<\/p>';			if ( numTags > 0 ) {				html += '<p class="tags">';				for( var t = 0; t <= max; t++) {					html += '<a href="/onderwerp/'+tags[t]+'">'+ tags[t] + "<\/a>" + delimiter( t, max );				}				html += '<\/p>';			}			html += '<\/div>';		return html;	};			var getMarker = function( data ) {		var latlng = new GLatLng( data.lat, data.lng );		var icon = getIcon( data.image );		var marker = new GMarker( latlng, { icon: icon } );				var html = getWindowHtml( data );				GEvent.addListener( marker, 'mouseover', function() {						marker.openInfoWindowHtml( html, { maxWidth: 300 } );					} );						return marker;	};		var setUpMap = function() {				var numMarkers = _data.length;				for( var i = 0; i < numMarkers; i++ ) {								_markers.push( getMarker( _data[i] ) );		}				var markerCluster = new MarkerClusterer( _map, _markers );	};		var throwError = function( xhr, status, error ) { };		var parseItemData = function( node ) {		var id 				= parseInt( node.attr("id"), 10 );		var lat 			= parseFloat( node.attr("lat") );		var lng 			= parseFloat( node.attr("lng") );		var onair 			= node.attr("date");		var title 			= node.find("title").text();		var description 	= node.find("description").text();		var stream 			= node.find("stream").text();		var tags 			= node.find("tags").text();		var image 			= node.find("image").text();			tags 				= tags.split('|');				return {			id : id,			image : image,			title : title,			onair : onair,			description : description,			stream : stream,			tags : tags,			lat : lat,			lng : lng		};			};		var parseMapData = function( xmlData ) {		var items = $( xmlData ).find( "item" );				var tmp = [];					items.each(	function() {					tmp.push( parseItemData( $(this) ) );						});		_data = tmp;				setUpMap();	};		var load = function() {				var that = this;		$.ajax( {			type:		"GET",			dataType:	"xml",			url:		_dataUrl,								success:	parseMapData,			error:		throwError		});			};		return {		init : init	};	} )();
