var map = null; // Our map instance var marker_layer = null; // Our markers layer var ZKL_Markers = new Array(); // The associative array with ZKL markers. Key is the ZKL serial#/DBID, value is an OpenLayers.Marker object. var KML_layer = null; // Our KML layer var vehyb = null; var vestr = null; var osm = null; var bNeedRecenter = false; // Need a re-center of the map? var DeviceTypesVisible = new Array(); // Array containing device type visibility (true/false) var DevTypesToNames_transtbl = new Array(); // Array containing the mapping from device types (type_XX) to a name (string) var mapviewcontrol; // reference to mapview control var DebugEnabled = 0; var IconLib = new Array(); // Array holding size of different icons var TcpTimeout = 3000; // Stored at definitions.php /* * IE6 workaround */ if (typeof(is_IE6) != "undefined") { OpenLayers.Util.alphaHack = function() { return false; } } /* * A better typeof() function. */ function ol_TypeOf(value) { // First check to see if the value is undefined. if (value == undefined) { return "undefined"; } // Check for objects created with the "new" keyword. if (value instanceof Object) { // Check for a boolean object. if (value instanceof Boolean) { return "boolean"; // Check for a number object. } else if (value instanceof Number) { // Test whether it's a float or int. if (/\./.test(value)) { return "float"; } else { return "int"; } // Check whether it's a string object. } else if (value instanceof String) { return "string"; // Check whether it's an array object/array literal. } else if (value instanceof Array) { return "array"; // Check whether it's a date object. } else if (value instanceof Date) { return "date"; // Check whether it's a function object. } else if(value instanceof Function) { return "function"; // Check whether it's and object object/object literal. } else if (value instanceof Object ) { return "object"; } // If these tests failed, check to see if we're // dealing with a literal. } else if (typeof value) { // Here we're testing for null. Get this, // JavaScript returns it as an object! // So first we check for object, then for value. if (typeof value == "object") { if (typeof value == "object" && !value) { return "null"; } // If the value wasn't null, check if it is a literal. } else { // Check for a boolean literal. if (typeof value == "boolean") { return "boolean"; // Check for a number literal. } else if (typeof value == "number") { // Check if the number literal is a float or int. if (/\./.test(value)) { return "float"; } else { return "int"; } // Check if it's a string literal. } else if (typeof value == "string") { return "string"; } } // If it slipped through all these tests, // we're dealing with something undetectable. // Therefore return nothing. } else { return false; } } /** * Debug function: dump some text to our browser window in the 'debugwindow' div. */ function DbgPrint(dbgtext) { // Only show debuginfo debug mode active if (DebugEnabled > 0) { dbgtext = typeof(dbgtext) == 'string' ? dbgtext : toString(dbgtext); try { getElement("debugwindow").innerHTML += (dbgtext+"
"); } catch (ex) { /* Silent exception */ } } } /* * This callback is called when a popup needs closing. * We find the correct marker, and destroy the appropriate popup. */ function ol_ClosePopupCallback() { ZKL_Markers[this.PopupID].popup.hide(); } /* * Create a new popup for ZKL with serial number 'serialnr'. * If one already existed, remove it and create a new one */ function ol_CreatePopup(serialnr) { if (ZKL_Markers[serialnr]) { var PopupHTML; var IconType; // Called with a valid serial? if (typeof(ZKL_Markers[serialnr]) == 'undefined') { DbgPrint ("ol_CreatePopup called with invalid serial "+serialnr); return; } // Do we have user defined popup content for this popup? If so, use it. if (typeof(ZKL_Markers[serialnr].s_popupHTML) != 'undefined') { PopupHTML = ZKL_Markers[serialnr].s_popupHTML; } else { // No user defined content specified. Create the popup content. First: spit out a nice header PopupHTML = ''+ ''; // Get icon (ok/nok/error/etc.) IconType = ZKL_Markers[serialnr]['s_icon']; // Walk through all the status parameters, map them through a translation table, and put them in table rows for (x in ZKL_Markers[serialnr]) { // ZKL parameters start with an 's_' if (x.substring(0,2) == 's_') { // Do not render the serialnr; we already did that. // Also, don't render parameters such as s_icon. if (x != 's_serialnr' && x != 's_icon' && x != 's_idcode' && x != 's_devtype' && x != 's_icon_info' && x != 's_visible') { if (ZKL_Markers[serialnr][x] != null) { // No connection => text = popup color var tdclass = (IconType == "error") ? "popup_cell_nocon" : "popup_cell_normal"; // Fetch the translations from the translation table. // If we don't have a translation, use the value as-is. var key = String((typeof(StatusTranslationTable[x]) != 'undefined') ? StatusTranslationTable[x] : x); if( key.indexOf('%s') != -1 ) { key = key.replace(/\%s/g, ZKL_Markers[serialnr]['nm_' + x.substring(2)]); } var val = ZKL_Markers[serialnr][x]; if (val.substring(0,1) == '!') { // Normal display, or error-red display? If there is an exclamation mark, make it an error. val = val.substring(1,val.length); // No connection => text = popup color tdclass = (IconType == "error") ? "popup_cell_nocon" : "popup_cell_error"; } // Translate the text val = String((typeof(StatusTranslationTable[val]) != 'undefined') ? StatusTranslationTable[val] : (val.substr(0, 1).toUpperCase() + val.substr(1))); // And add it to the popup. PopupHTML += (''); } } } } // Add the closing tags PopupHTML += ''; } // Existing popup? if (ZKL_Markers[serialnr].popup != null) { // Popup already exists? ZKL_Markers[serialnr].popup.lonlat = ZKL_Markers[serialnr].lonlat; ZKL_Markers[serialnr].popup.setContentHTML(PopupHTML); } else { // Create popup ZKL_Markers[serialnr].popup = new OpenLayers.Popup.FramedCloud(serialnr, ZKL_Markers[serialnr].lonlat, null, PopupHTML, ZKL_Markers[serialnr].icon, true, ol_ClosePopupCallback ); // Add the popup to the map! marker_layer.map.addPopup(ZKL_Markers[serialnr].popup); } // Assign an ID so we can relate to this popup when an event occurs ZKL_Markers[serialnr].popup.PopupID = serialnr; // Disable autosizer and autopanner ZKL_Markers[serialnr].popup.contentDisplayClass = 'popup'; ZKL_Markers[serialnr].popup.autoSize = true; ZKL_Markers[serialnr].popup.panMapIfOutOfView = false; ZKL_Markers[serialnr].popup.keepInMap = false; // Show popup ZKL_Markers[serialnr].popup.show(); } } /* * The event handler for a click on a marker: display popup. */ function ol_MarkerClickEvent(evt) { // Create popup ol_CreatePopup(evt.object.s_serialnr); // End this event OpenLayers.Event.stop(evt); } /* * The event handler for a mouseover on a marker: change cursor type */ function ol_MarkerMouseOverEvent(evt) { // Adapt cursor document.body.style.cursor='pointer'; // End of event OpenLayers.Event.stop(evt); } /* * The event handler for a mouse out on a marker: change cursor type */ function ol_MarkerMouseOutEvent(evt) { // Adapt cursor document.body.style.cursor='auto'; // End of event OpenLayers.Event.stop(evt); } /* * The event handler for a double click on a marker: zoom in. */ function ol_MarkerDblClickEvent(evt) { // Set map center & zoom ol_CenterItem(evt.object.s_serialnr); // End this event OpenLayers.Event.stop(evt); } /* * Center the map around a marker with the given ID */ function ol_CenterItem(MarkerID) { var index = 0; var redraw = false; if (ZKL_Markers[MarkerID]) { if (ZKL_Markers[MarkerID].bIsUsed) { // Recenter only when visible if (!ZKL_Markers[MarkerID].bHidden) { var NewCenter = new OpenLayers.LonLat(ZKL_Markers[MarkerID].ip_Lon, ZKL_Markers[MarkerID].ip_Lat); map.setCenter(NewCenter.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()), map.numZoomLevels-1); } for (x in ZKL_Markers) { // Reset 'tracking' status for all markers if (ZKL_Markers[x].bIsUsed) { ZKL_Markers[x].ip_bTracking = false; } // Define new devIndex if (DeviceTypesVisible[ZKL_Markers[x].s_devtype] == true || ZKL_Markers[x].s_icon == "nok") { // Index already visible? if (x == MarkerID) { if ((index < mapviewcontrol.devIndex) || ((index >= mapviewcontrol.devIndex) && (index - mapviewcontrol.devIndex) >= mapviewcontrol.devVisible)) { if ((index + mapviewcontrol.devVisible) > mapviewcontrol.devMaxIndex) { mapviewcontrol.devIndex = mapviewcontrol.devMaxIndex - mapviewcontrol.devVisible; } else { mapviewcontrol.devIndex = index; } // Redraw mapview control redraw = true; } } index++; } } } } // Update the mapview control if (redraw) { mapviewcontrol.forceRedraw(); } else { mapviewcontrol.updateDevices(); } } /* * Create or clone an icon. * Pass the icon type (e.g. 'ok' for OK) and device type (e.g. type_0 for ZKL3000) to this function. * If the icon is already loaded, we clone it. If not, we load a bitmap named .png and create the icon * * Return: OpenLayers.Icon object with the requested icon if it exists, or the default diamond-like OpenLayers icon * when not. */ function ol_CreateIcon(icon_type, devtype) { // Define output format var output = 'png'; if (typeof(is_IE6) != "undefined") { output = 'gif'; } if (typeof(icon_type) == 'undefined') { return; } if (typeof(devtype) == 'undefined') { devtype = '0'; } // remove a leading 'type_' from devtype, when applicable. if (devtype.substring(0,5) == 'type_') { devtype = devtype.substring(5,devtype.length); } // Build the icon ID icon_id = '&dev_type=' + devtype + '&' + icon_type; // Skip rtremark & idcode & warning // This makes the icons less unique while the size is the same (so xmlhttp request less because of known image size) // Find &idcode=<*>& icon_id = icon_id.replace(/&idcode=.*&/gi, '&idcode&'); // Find &idcode=<*>EOL icon_id = icon_id.replace(/&idcode=.*/gi, '&idcode'); // Find &rtremark=<*>& icon_id = icon_id.replace(/&rtremark=.*&/gi, '&rtremark&'); // Find &rtremark=<*>EOL icon_id = icon_id.replace(/&rtremark=.*/gi, '&rtremark'); // Find &warning=<*>& icon_id = icon_id.replace(/&warning=.*&/gi, '&warning&'); // Find &warning=<*>EOL icon_id = icon_id.replace(/&warning=.*/gi, '&warning'); // See if the icon was already loaded if (typeof(IconLib[icon_id]) == 'undefined') { DbgPrint ("Icon with ID "+icon_id+" is not yet available. Loading and creating..."); // load image width/height var IconSizeCode = xmlhttp_data('include/db_icon.php', '', 0, '', '', '', '&device='+devtype+'&icon='+icon_type+'&action=jssize'); // Check if this is valid iconsize code for us if (IconSizeCode.substring(0,15) == '//iconsize_v1.0') { // eval() it. After this, we have a JS array named 'iconsize' eval (IconSizeCode); DbgPrint ("Icon size fetched from server ("+iconsize[0]+","+iconsize[1]+")\n"); } else { // Default iconsize = new Array(40,20); DbgPrint ("Icon size fetch failed. Assuming ("+iconsize[0]+","+iconsize[1]+")\n"); } // Store values IconLib[icon_id] = iconsize; } // Create new icon var size = new OpenLayers.Size(IconLib[icon_id][0], IconLib[icon_id][1]); var offset = new OpenLayers.Pixel(-Math.round(IconLib[icon_id][0]/2), -Math.round(IconLib[icon_id][1]/2)); // Debug info DbgPrint ('include/db_icon.php?device='+devtype+'&icon='+icon_type+'&output='+output); return new OpenLayers.Icon('include/db_icon.php?device='+devtype+'&icon='+icon_type+'&output='+output, size, offset); } /** * Update the marker layer on the map view with the items in the object passed. * This object should have the following format: * * ItemArray[0] --+ * +-- ItemInstance[0] --+ * | +-- position (required: postion on the map) * | +-- s_serialnr (required: item's serial number) * | +-- s_gps (optional: GPS position for display) * | +-- s_icon (required: icon identifier) * | +-- s_visible (required: icon visible) * | +-- s_icon_info (required: icon identifier&idcode&rtremark) * | +-- s_devtype (required: device type. e.g. zkl, trt, etc.) * | +-- s_popupHTML (optional: if you want to generate your own popup HTML, put it here. This overrides the default popup renderer) * | +-- s_optional1 (optional: parameter will be displayed in popup. * | +-- s_optional2 * | +-- s_optionalX * | +-- nm_serialnr (required: translated string "serial number") * | .. (etc) * | +-- nm_optionalX * | * +-- ItemInstance[1] --+ * | +-- s_serialnr * | .. * | +-- s_optionalX * | * +-- ItemInstance[n] --+ * +-- s_serialnr * .. * +-- s_optionalX * * * In a future expansion, more entries in ItemArray will be allowed so movement paths of items * can be displayed etc. But currently, only the data in ItemArray[0] is rendered to the map view * * Parameters can also indicate whether the value is OK or not OK. In the latter case the parameter will be shown in red. * To indicate a parameter which is not OK, start the parameter value with an '!'. * Example: ('s_batt1':'!Empty') would display a battery 1 status parameter in red. * * Note: Use common sense when using this feature. Obviously it doesn't make sense to make the serial numer 'invalid'. The * code won't check it. */ function mapview_UpdateItems(ItemArray) { // Get current date var current = new Date(); var hidemessage = 1; // We only use ItemArray[0] at this moment. Pull the information the quick and dirty way. // Also, see if we have a valid serial and IDcode. We might get empty results from the server due to // prematurely terminated server script etc. CurrItem = new Array(); for (x in ItemArray[0]) { var Serial = parseInt(ItemArray[0][x].s_serialnr); DbgPrint ("Serial="+ItemArray[0][x].s_serialnr+"\n"); if ((Serial > 0) && (ItemArray[0][x].s_idcode.length > 0)) { CurrItem.push(ItemArray[0][x]); } } // First step: mark all markers as 'not used'. This allows us to throw away unused markers later on. for (x in ZKL_Markers) { if (ZKL_Markers[x]) { ZKL_Markers[x].bIsUsed = false; } } // Walk through all objects in CurrItem, and parse them var bIsChanged, SerialNr; var bHaveNew = false; bMapControlUpdate = false; bMapControlRedraw = false; // Reset device type/name containers // Walk over the incoming data for (x in CurrItem) { // The serial number is used to index the arrays. SerialNr = CurrItem[x].s_serialnr; // Create/update entry in devtype -> devname translation table. DevTypesToNames_transtbl[CurrItem[x].s_devtype] = CurrItem[x].s_devname; // Add device type to visibility-array if it does not exist yet if (typeof(DeviceTypesVisible[CurrItem[x].s_devtype]) != "boolean") { // default visibility is 'true' (visible). DeviceTypesVisible[CurrItem[x].s_devtype] = true; DbgPrint ("Added devtype "+CurrItem[x].s_devtype+" to visibility array\n"); } // Store variables (visibility/icon info) CurrItem[x].s_icon_info = CurrItem[x].s_icon; var offset = CurrItem[x].s_icon.search("&idcode"); if (offset != -1) { CurrItem[x].s_icon = CurrItem[x].s_icon.substring(0, offset); } offset = CurrItem[x].s_icon.search("&warning"); if (offset != -1) { CurrItem[x].s_icon = CurrItem[x].s_icon.substring(0, offset); } CurrItem[x].s_visible = (DeviceTypesVisible[CurrItem[x].s_devtype] == true || CurrItem[x].s_icon == "nok") ? true : false; // Extract GPS lat and lon coords. Remove starting '!' if applicable. var stringLat; var stringLon; if(typeof(CurrItem[x].position) != "undefined") { comma = CurrItem[x].position.indexOf(","); stringLat = CurrItem[x].position.substr(0, comma); stringLon = CurrItem[x].position.substr(comma + 1); } Lon = parseFloat(stringLon); Lat = parseFloat(stringLat); // Default coordinates when GPS is invalid!! if (typeof(Lon)!="number" || typeof(Lat)!="number") { DbgPrint ("mapview_UpdateItems ERROR: Invalid lat or lon (lon="+stringLon+" lat="+CurrItem[x].s_lat+")"); DbgPrint ("typeof(Lon)="+ol_TypeOf(Lon)+" typeof(Lat)="+ol_TypeOf(Lat)); // An error occurred. Place the device at DI headquarters to avoid JS errors Lon = 5.163956; Lat = 51.6087; } // Store these numbers for future use as internal parameter. CurrItem[x].ip_Lon = Lon; CurrItem[x].ip_Lat = Lat; // Initial values bIsChanged = false; bNeedRecenter = false; // See if a marker for this ZKL instance exists. Use the serialnr as the key. // If not, create a marker and add it to the layer. if (ZKL_Markers[SerialNr] == null) { DbgPrint ('New ZKL with serial# '+SerialNr+' found. Adding to view'); // new marker position var point = new OpenLayers.LonLat(Lon,Lat); // Get point projection point = point.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()); // Create marker var icon = ol_CreateIcon(CurrItem[x].s_icon_info,CurrItem[x].s_devtype); ZKL_Markers[SerialNr] = new OpenLayers.Marker(point, icon.clone()); // Store original size ZKL_Markers[SerialNr].originalSize = icon.size; // Destroy icon icon.destroy(); // Store visibility ZKL_Markers[SerialNr].s_visible = false; ZKL_Markers[SerialNr].bHidden = false; // create popup holder ZKL_Markers[SerialNr].popup = null; // Add mouse events ZKL_Markers[SerialNr].events.register("click", ZKL_Markers[SerialNr], ol_MarkerClickEvent); ZKL_Markers[SerialNr].events.register("dblclick", ZKL_Markers[SerialNr], ol_MarkerDblClickEvent); ZKL_Markers[SerialNr].events.register("mouseover", ZKL_Markers[SerialNr], ol_MarkerMouseOverEvent); ZKL_Markers[SerialNr].events.register("mouseout", ZKL_Markers[SerialNr], ol_MarkerMouseOutEvent); // Store lonlat/icon info (prevent update) ZKL_Markers[SerialNr].lonlat = point; ZKL_Markers[SerialNr].s_icon_info = CurrItem[x].s_icon_info; // Add marker to marker map marker_layer.addMarker(ZKL_Markers[SerialNr]); // Indicate that we have added a new ZKL instance. This is used later for centering/zooming the map view bHaveNew = true; // New ZKL instance => update mapview control bMapControlRedraw = true; // Heartbeat unhandled ZKL_Markers[SerialNr].hbhandled = 0; ZKL_Markers[SerialNr].hbtimeout = new Date(); // Rest of init is done by the changed event bIsChanged = true; } // Now walk over all the status items in the ZKL object, update them, see if they are changed var CopyScript = ' '; for (i in CurrItem[x]) { // Extra check to see if this is indeed a valid status parameter if (i.substring(0,2) == 's_' || i.substring(0,3) == 'ip_' || i.substring(0,3) == 'nm_') { // Add this status parameter to the copy script CopyScript += 'ZKL_Markers[SerialNr].'+i+'=CurrItem[x].'+i+';'; if (CurrItem[x][i] != ZKL_Markers[SerialNr][i]) { DbgPrint('ZKL with serial number '+SerialNr+': parameter '+i+' has changed to '+CurrItem[x][i]); // indicate that something has changed bIsChanged = true; // See if a change in this parameter needs to trigger a popup or re-center. // We need a re-center when the icon changes from 'nonexistent' to something else' // Mapcontrol redraw automatically updated by recenter if (i=='s_icon' && CurrItem[x][i]!='nok' && ZKL_Markers[SerialNr][i]=='nok') { DbgPrint ("Contact with "+SerialNr+" restored. Re-centering..."); bNeedRecenter = true; } // See if we need to update the mapcontrol // Find changes in s_idcode and s_icon, visibility is handled by mapview_control itself if ((i == 's_idcode') || (i == 's_icon')) { bMapControlUpdate = true; } } } } // Extra CopyScript additions to carry over information in the existing marker CopyScript = CopyScript+'ZKL_Markers[SerialNr].ip_bTracking = '+ZKL_Markers[SerialNr].ip_bTracking; // And, was there a change? or unhandled heartbeat check if ((bIsChanged) || (ZKL_Markers[SerialNr].hbhandled == 0)) { // (re)create the marker/position var point = new OpenLayers.LonLat(CurrItem[x].ip_Lon,CurrItem[x].ip_Lat); // Get point projection point = point.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()); // New icon? if (CurrItem[x].s_icon_info != ZKL_Markers[SerialNr].s_icon_info) { // Get new icon from library var icon = ol_CreateIcon(CurrItem[x].s_icon_info, CurrItem[x].s_devtype); ZKL_Markers[SerialNr].icon.setSize(icon.size); ZKL_Markers[SerialNr].setUrl(icon.url); ZKL_Markers[SerialNr].icon.offset = icon.offset; // Store original size ZKL_Markers[SerialNr].originalSize = icon.size; // Destroy icon icon.destroy(); } // New coordinate? if (point != ZKL_Markers[SerialNr].lonlat) { ZKL_Markers[SerialNr].lonlat = point; ZKL_Markers[SerialNr].icon.lonlat = point; } // Remove old data parameters var RemoveKeys = new Array(); for (y in ZKL_Markers[SerialNr]) { // ZKL parameters start with an 's_' if (y.substring(0,2) == 's_') { RemoveKeys.push(y); } } for (y in RemoveKeys) { delete(ZKL_Markers[SerialNr][RemoveKeys[y]]); } // Store marker info (Copy from CurrItem => ZKL_Markers) eval(CopyScript); // Waiting for heartbeat? if ((ZKL_Markers[SerialNr].hbhandled == 1) || (ZKL_Markers[SerialNr].s_icon != 'error') || ((current.getTime() - ZKL_Markers[SerialNr].hbtimeout.getTime()) >= TcpTimeout)) { // Set flag ZKL_Markers[SerialNr].hbhandled = 1; } else { // Still displaying message hidemessage = 0; } // Set marker visibility ZKL_Markers[SerialNr].display(CurrItem[x].s_visible && !ZKL_Markers[SerialNr].bHidden && ZKL_Markers[SerialNr].hbhandled); // Hide popup if (!CurrItem[x].s_visible || ZKL_Markers[SerialNr].bHidden) { if (ZKL_Markers[SerialNr].popup != null) { ZKL_Markers[SerialNr].popup.hide(); } } else { // If there was a popup, recreate it if (ZKL_Markers[SerialNr].popup != null) { if (ZKL_Markers[SerialNr].popup.visible()) { // Copy the parameter data into the marker and show? ol_CreatePopup(SerialNr); } } } } // Set the state of this marker to 'used' ZKL_Markers[SerialNr].bIsUsed = true; } // Cleanup stage. All markers which are still 'not used' may be thrown away. // Also, if we're tracking, set a flag. for (x in ZKL_Markers) { if (ZKL_Markers[x]) { if (!ZKL_Markers[x].bIsUsed) { // ZKL instance deleted => update mapview control bMapControlRedraw = true; // Try to remove popup try { marker_layer.map.removePopup(ZKL_Markers[x].popup); ZKL_Markers[x].popup.destroy(); ZKL_Markers[x].popup = null; } catch (err) {} DbgPrint ('Marker '+x+' is not in use anymore. Killing the marker..'); // Marker is not in use anymore. // step 1: remove marker from the map marker_layer.removeMarker(ZKL_Markers[x]); // step 2: destroy the marker itself ZKL_Markers[x].events.destroy(); ZKL_Markers[x].destroy(); // step 3: remove it from our array (BvH note: splice() went wrong; setting to null is a workaround) delete(ZKL_Markers[x]); } } } // Re-sort array if (bHaveNew) { // Sort devices var backup = ZKL_Markers; var temp = new Array(); // Collect all idcodes for (x in backup) { temp.push(backup[x].s_idcode); } // Sort all devices temp.sort(); // Clear array ZKL_Markers = new Array(); // Refill array for (y in temp) { for (x in backup) { if (temp[y] == backup[x].s_idcode) { ZKL_Markers[x] = backup[x]; } } } // Sort device types DevTypesToNames_transtbl = sortAssoc(DevTypesToNames_transtbl); // Create backup backup = DeviceTypesVisible; temp = new Array(); // Clear array DeviceTypesVisible = new Array(); // Refill marker array for (y in DevTypesToNames_transtbl) { for (x in backup) { if (y == x) { DeviceTypesVisible[y] = backup[x]; } } } } // When a ZKL intance was added to the list, calculate the extents of the ZKL instances and try // to fit them neatly on the map. Also when changed from 'ok' to 'nok' if (bHaveNew || bNeedRecenter) { ol_RecenterMap(); } else { // No need to recenter, but some of the devices we're tracking may be off the map. // Check this too. ol_RecenterTracked(); } // Update/redraw the mapview control if (bMapControlRedraw) { mapviewcontrol.forceRedraw(); } else if (bMapControlUpdate) { mapviewcontrol.updateDevices(); } // Display message if (hidemessage) { HideWaitingMessage(); } else { ShowWaitingMessage(); } } /* * Center & zoom map so that all devices are visible */ function ol_RecenterMap(Redraw) { // Devices available? var DevAvailable = false; // The bounds of the tracked devices var TrackedDevicesBounds = new OpenLayers.Bounds(); for (x in ZKL_Markers) { if (ZKL_Markers[x]) { // Markers visibible? if (ZKL_Markers[x].s_visible && !ZKL_Markers[x].bHidden) { // Device found DevAvailable = true; // Add this device to the bounding box around all tracking markers var MarkerLonLat = new OpenLayers.LonLat(ZKL_Markers[x].ip_Lon,ZKL_Markers[x].ip_Lat); TrackedDevicesBounds.extend(MarkerLonLat.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())); } } } if (DevAvailable) { // Recenter and zoom map in sich a way that all tracked markers are visible. TrackedDevicesBounds.toBBOX(); map.zoomToExtent(TrackedDevicesBounds, false); } } /* * Center & zoom map so that all tracked devices are visible */ function ol_RecenterTracked() { // Are there devices invisible? var bDevicesInvisible = false; // The bounds of the tracked devices var TrackedDevicesBounds = new OpenLayers.Bounds(); for (x in ZKL_Markers) { if (ZKL_Markers[x]) { if (ZKL_Markers[x].bIsUsed && ZKL_Markers[x].ip_bTracking && ZKL_Markers[x].s_visible && !ZKL_Markers[x].bHidden) { var MarkerLonLat = new OpenLayers.LonLat(ZKL_Markers[x].ip_Lon,ZKL_Markers[x].ip_Lat); // Add this device to the bounding box around all tracking markers TrackedDevicesBounds.extend(MarkerLonLat.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())); // Find out if this device is actually invisible. // (if none of the devices are invisible, we don't need to recenter/zoom map) if (!ZKL_Markers[x].onScreen()) { DbgPrint ("Device "+x+" is not visible. Adjusting zoom and center.."); bDevicesInvisible = true; } } } } // Are there actually devices invisible? if (bDevicesInvisible) { // Get old zoom level var oldZoom = map.getZoom(); // Recenter and zoom map in sich a way that all tracked markers are visible. TrackedDevicesBounds.toBBOX(); map.zoomToExtent(TrackedDevicesBounds, false); // Get new zoom level var newZoom = map.getZoom(); // Restore old zoom level? if (oldZoom < newZoom) { map.zoomTo(oldZoom); } } } /** * Redraw all the markers */ function ol_RedrawMarkers() { try { if (marker_layer != null) { // Redraw marker layer marker_layer.redraw(); // Redraw popup for (x in ZKL_Markers) { if ((x != null) && (typeof(ZKL_Markers[x]) == 'object') && (ZKL_Markers[x].popup != null)) { try { ZKL_Markers[x].popup.updatePosition(); } catch (err) { /* Silent exception */ } } } } if (KML_layer != null) { KML_layer.redraw(); } } catch(err) { /* Silent exception */ } finally { // Recursive setTimeout('ol_RedrawMarkers();', 500); } } /** * Initialise OpenLayers mapping API */ function ol_init(Center, Zoom){ /// Create map objects if (map == null) { map = new OpenLayers.Map('map', { projection : new OpenLayers.Projection("EPSG:900913"), displayProjection : new OpenLayers.Projection("EPSG:4326"), maxExtent : new OpenLayers.Bounds(-20037508, -20037508,20037508, 20037508.34), numZoomLevels : 18, controls: [ new OpenLayers.Control.PanZoomBar(), //new OpenLayers.Control.LayerSwitcher({'ascending':false}), mapviewcontrol=new OpenLayers.Control.Mapview_Control(), new OpenLayers.Control.ScaleLine(), //new OpenLayers.Control.MousePosition(), new OpenLayers.Control.MouseDefaults(), new OpenLayers.Control.Navigation() ] } ); // Register "end-of-zoom" event (inflating icons) //map.events.register("zoomend", null, ol_PanZoomEvent); } // Bing Hybrid base layer if (vestr == null) { vestr = new OpenLayers.Layer.VirtualEarth(StatusTranslationTable["streetmap"] + ' (BING)', { "sphericalMercator": true }); map.addLayer(vestr); } // Open street layer /* Removed due to SSL security error if (osm == null) { osm = new OpenLayers.Layer.OSM(StatusTranslationTable["streetmap"] + ' (OSM)'); map.addLayer(osm); } */ // Bing Street map if (vehyb == null) { vehyb = new OpenLayers.Layer.VirtualEarth(StatusTranslationTable["satellitemap"], { 'type': VEMapStyle.Hybrid, "sphericalMercator": true }); map.addLayer(vehyb); } // Set the map center and zoom to a value where entire NL is visible. var point = new OpenLayers.LonLat(5.11877, 52.09832); map.setCenter(point.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()), 7); // KML layer //if (KML_layer == null) { // // KML file exists? // var kml = "rt.kml"; // // if (xmlhttp_data('include/fetch_info.php','', 0, '', getURLParam('id'),'&file_exits=1&file=../' + kml, '', null) == '1') { // KML_layer = new OpenLayers.Layer.Vector("KML", { // projection: new OpenLayers.Projection("EPSG:4326"), // strategies: [new OpenLayers.Strategy.Fixed()], // protocol: new OpenLayers.Protocol.HTTP({ // url : kml, // format : new OpenLayers.Format.KML({ // extractStyles : true, // extractAttributes : true, // extractTracks : true // }) // }) // } // ); // map.addLayer(KML_layer); // } //} // Create the marker layer. Marker layer will be filled in later as a result of a successfull XMLHttpRequest. if (marker_layer == null) { marker_layer = new OpenLayers.Layer.Markers("DEV"); map.addLayer(marker_layer); } // Startup marker timer setTimeout('ol_RedrawMarkers();',500); } /* * Clean up markers/layers/map */ function ol_Cleanup() { // Clean up markers for (x in ZKL_Markers) { // Try to remove popup try { marker_layer.map.removePopup(ZKL_Markers[x].popup); ZKL_Markers[x].popup.destroy(); ZKL_Markers[x].popup = null; } catch (err) {} // step 1: remove marker from the map marker_layer.removeMarker(ZKL_Markers[x]); // step 2: destroy the marker itself ZKL_Markers[x].events.destroy(); ZKL_Markers[x].destroy(); // step 3: remove it from our array delete(ZKL_Markers[x]); } // Clean up layers if (map != null) { if (vestr != null) { // step 1: remove layer from the map map.removeLayer(vestr, false); // step 2: destroy the layer itself vestr.destroy(); } if (osm != null) { // step 1: remove layer from the map map.removeLayer(osm, false); // step 2: destroy the layer itself osm.destroy(); } if (vehyb != null) { // step 1: remove layer from the map map.removeLayer(vehyb, false); // step 2: destroy the layer itself vehyb.destroy(); } if (KML_layer != null) { // step 1: remove layer from the map map.removeLayer(KML_layer, false); // step 2: destroy the layer itself KML_layer.destroy(); } } // Cleanup map if (map != null) { map.destroy(); } } /* * End of zoom event, inflate markers */ function ol_PanZoomEvent() { // Determine inflate value var InflateStep = (0.5/map.numZoomLevels); var Inflate = 0.5 + (InflateStep * (map.getZoom() + 1)); for (x in ZKL_Markers) { if (ZKL_Markers[x]) { // Inflate marker ZKL_Markers[x].icon.setSize(new OpenLayers.Size(ZKL_Markers[x].originalSize.w * Inflate, ZKL_Markers[x].originalSize.h * Inflate)); ZKL_Markers[x].icon.offset = new OpenLayers.Pixel(-Math.round(ZKL_Markers[x].icon.size.w/2), -Math.round(ZKL_Markers[x].icon.size.h/2)); } } } /* * This functions swaps invisible/visible image and hides/shows marker */ function ol_HideItem(serialnr) { // Swap image if (getElement(serialnr + '_visible_image').src.search("invisible.gif") == -1) { getElement(serialnr + '_visible_image').src = 'html/images/invisible.gif'; if (ZKL_Markers[serialnr]) { // Set flag ZKL_Markers[serialnr].bHidden = true; // Hide marker & popup ZKL_Markers[serialnr].display(false); if (ZKL_Markers[serialnr].popup != null) { ZKL_Markers[serialnr].popup.hide(); } } } else { getElement(serialnr + '_visible_image').src = 'html/images/visible.gif'; if (ZKL_Markers[serialnr]) { // Clear flag ZKL_Markers[serialnr].bHidden = false; // Show marker ZKL_Markers[serialnr].display(true); } } } /* * Map view mouse handlers. We use it to redraw the markers to force correct behaviour with Google */ function mouseup() { } function mousedown() { }