src.dualinventive.com/mtinfo/dist/webroot/rc-4.05/html/javascript/mapview.js

1086 lines
45 KiB
JavaScript

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+"<br>");
}
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 = '<p class="popup_hdr">'+StatusTranslationTable['s_idcode']+"&nbsp;"+ZKL_Markers[serialnr]['s_idcode']+'</p>'+
'<table class="popup_bodytbl">';
// 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 += ('<tr class="popup_row"><td class="'+tdclass+'">'+key+'&nbsp;</td><td class="'+tdclass+'">'+val+'</td></tr>');
}
}
}
}
// Add the closing tags
PopupHTML += '</table>';
}
// 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 <icon_id>.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() {
}