Project

General

Profile

1
/*
2
Author:       Cameron Shorter cameronAtshorter.net
3
License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html
4

    
5
$Id$
6
*/
7

    
8
// Ensure this object's dependancies are loaded.
9
mapbuilder.loadScript(baseDir+"/widget/WidgetBase.js");
10
mapbuilder.loadScript(baseDir+"/widget/MapContainerBase.js");
11

    
12
/**
13
 * Widget to render a map from an OGC context document.  The layers are rendered
14
 * as an array of DHTML layers that contain an <IMG> tag with src attribute set 
15
 * to the GetMap request.
16
 * @constructor
17
 * @base WidgetBaseXSL
18
 * @base MapContainerBase
19
 * @param widgetNode  The widget's XML object node from the configuration document.
20
 * @param model       The model object that this widget belongs to.
21
 */
22
function MapPane(widgetNode, model) {
23
  WidgetBase.apply(this,new Array(widgetNode, model));
24
  MapContainerBase.apply(this,new Array(widgetNode, model));
25

    
26
  // Set this.stylesheet
27
  // Defaults to "widget/<widgetName>.xsl" if not defined in config file.
28
  if ( !this.stylesheet ) {
29
    var styleNode = widgetNode.selectSingleNode("mb:stylesheet");
30
    if (styleNode ) {
31
      this.stylesheet = new XslProcessor(styleNode.firstChild.nodeValue,model.namespace);
32
    } else {
33
      this.stylesheet = new XslProcessor(baseDir+"/widget/"+widgetNode.nodeName+".xsl",model.namespace);
34
    }
35
  }
36

    
37
  //loading img to be displayed while models load
38
  var loadingSrc = widgetNode.selectSingleNode("mb:loadingSrc");
39
  if (loadingSrc) {
40
    this.loadingSrc = config.skinDir + loadingSrc.firstChild.nodeValue;
41
  } else {
42
    this.loadingSrc = config.skinDir + "/images/Loading.gif";
43
  }
44

    
45
  // Set stylesheet parameters for all the child nodes from the config file
46
  for (var j=0;j<widgetNode.childNodes.length;j++) {
47
    if (widgetNode.childNodes[j].firstChild
48
      && widgetNode.childNodes[j].firstChild.nodeValue)
49
    {
50
      this.stylesheet.setParameter(
51
        widgetNode.childNodes[j].nodeName,
52
        widgetNode.childNodes[j].firstChild.nodeValue);
53
    }
54
  }
55

    
56
  //all stylesheets will have these properties available
57
  this.stylesheet.setParameter("modelId", this.model.id );
58
  this.stylesheet.setParameter("modelTitle", this.model.title );
59
  this.stylesheet.setParameter("widgetId", this.id );
60
  this.stylesheet.setParameter("skinDir", config.skinDir );
61
  this.stylesheet.setParameter("lang", config.lang );
62

    
63

    
64
  /**
65
   * Called when the context's hidden attribute changes.
66
   * @param objRef This object.
67
   * @param layerName  The name of the layer that was toggled.
68
   */
69
  this.hiddenListener=function(objRef, layerName){
70
    var vis="visible";
71
    if(objRef.model.getHidden(layerName)=="1") {
72
      vis="hidden";
73
    }
74
    var layerId = objRef.model.id + "_" + objRef.id + "_" + layerName;
75
    var layer = document.getElementById(layerId);
76
    if (layer) {
77
      layer.style.visibility=vis;
78
      imgId = "real"+layer.imgId;
79
      img = document.getElementById(imgId); // Hack to make sure that the child element is toggled in IE
80
      if(img) img.style.visibility=vis;
81
    }
82
  }
83
  this.model.addListener("hidden",this.hiddenListener,this);
84

    
85
  /**
86
   * Called after a feature has been added to a WFS.  This function triggers
87
   * the WMS basemaps to be redrawn.  A timestamp param is added to the URL
88
   * to ensure the basemap image is not cached.
89
   */
90
  this.refreshWmsLayers=function(objRef){
91
    objRef.d=new Date();
92
    objRef.stylesheet.setParameter("uniqueId",objRef.d.getTime());
93
    objRef.paint(objRef);
94
  }
95
  this.model.addListener("refreshWmsLayers",this.refreshWmsLayers,this);
96

    
97
  this.model.addListener("refresh",this.paint, this);
98
  this.model.addListener("addLayer",this.addLayer, this);
99
  this.model.addListener("deleteLayer",this.deleteLayer, this);
100
  this.model.addListener("moveLayerUp",this.moveLayerUp, this);
101
  this.model.addListener("moveLayerDown",this.moveLayerDown, this);
102
}
103

    
104
/**
105
 * Render the widget.
106
 * @param objRef Pointer to widget object.
107
 */
108
MapPane.prototype.paint = function(objRef, refresh) {
109

    
110
  if (objRef.model.doc && objRef.node && (objRef.autoRefresh||refresh) ) {
111
    //if (objRef.debug) alert("source:"+Sarissa.serialize(objRef.model.doc));
112

    
113
    objRef.stylesheet.setParameter("width", objRef.model.getWindowWidth());
114
    objRef.stylesheet.setParameter("height", objRef.model.getWindowHeight());
115
    objRef.stylesheet.setParameter("bbox", objRef.model.getBoundingBox().join(","));
116
    objRef.stylesheet.setParameter("srs", objRef.model.getSRS());
117

    
118
    //confirm inputs
119
    if (objRef.debug) alert("painting:"+Sarissa.serialize(objRef.model.doc));
120
    if (objRef.debug) alert("stylesheet:"+Sarissa.serialize(objRef.stylesheet.xslDom));
121

    
122
    //process the doc with the stylesheet
123
    var tempDom = objRef.stylesheet.transformNodeToObject(objRef.model.doc);
124
    var tempNodeList = tempDom.selectNodes("//img");
125

    
126
    //debug output
127
    if (objRef.debug) {
128
      alert("painting:"+objRef.id+":"+s);
129
      if (config.serializeUrl) postLoad(config.serializeUrl, s);
130
    }
131

    
132
    //create a DIV to hold all the individual image DIVs
133
    var outputNode = document.getElementById( objRef.outputNodeId );
134
    if (!outputNode) {
135
      outputNode = document.createElement("div");
136
      outputNode.setAttribute("id", objRef.outputNodeId);
137
      outputNode.style.position = "absolute"; 
138
      objRef.node.appendChild(outputNode);
139
      outputNode.style.left='0px';
140
      outputNode.style.top='0px';
141
    } 
142

    
143
    //loop through all layers and create an array of IMG objects for preloading 
144
    // the WMS getMap calls
145
    var layers = objRef.model.getAllLayers();
146
    if (!objRef.imageStack) objRef.imageStack = new Array(layers.length);
147
    objRef.firstImageLoaded = false;
148

    
149
    objRef.layerCount = layers.length;
150

    
151
    for (var i=0;i<layers.length;i++){
152
      if (!objRef.imageStack[i]) {
153
        objRef.imageStack[i] = new Image();
154
        objRef.imageStack[i].objRef = objRef;
155
      }
156
      //var newSrc = tempNode.firstChild.childNodes[i].firstChild.getAttribute("src"); 
157
      var newSrc = tempNodeList[i].getAttribute("src");
158
      objRef.loadImgDiv(layers[i],newSrc,objRef.imageStack[i]);
159
    }
160
    var message = "loading " + objRef.layerCount + " map layer" + ((objRef.layerCount>1)?"s":"");
161
    objRef.model.setParam("modelStatus", message);
162
  }
163
}
164

    
165
/**
166
 * Returns an ID for the image DIV given a layer name
167
 * @param layerName the name of the WMS layer
168
 */
169
MapPane.prototype.getLayerDivId = function(layerName) {
170
  return this.model.id +"_"+ this.id +"_"+ layerName; //TBD: add in timestamps
171
}
172

    
173
/**
174
 * Adds a layer into the output
175
 * @param layerName the WMS anme for the layer to be removed
176
 */
177
MapPane.prototype.addLayer = function(objRef, layerNode) {
178

    
179
  ++objRef.layerCount;
180
  var message = "loading " + objRef.layerCount + " map layer" + ((objRef.layerCount>1)?"s":"");
181
  objRef.model.setParam("modelStatus", message);
182

    
183
  //process the doc with the stylesheet
184
  objRef.stylesheet.setParameter("width", objRef.model.getWindowWidth());
185
  objRef.stylesheet.setParameter("height", objRef.model.getWindowHeight());
186
  objRef.stylesheet.setParameter("bbox", objRef.model.getBoundingBox().join(","));
187
  objRef.stylesheet.setParameter("srs", objRef.model.getSRS());
188
  var s = objRef.stylesheet.transformNodeToString(layerNode);
189
  var tempNode = document.createElement("div");
190
  tempNode.innerHTML = s;
191
  var newSrc = tempNode.firstChild.firstChild.getAttribute("src"); 
192

    
193
  objRef.imageStack.push(new Image());
194
  objRef.imageStack[objRef.imageStack.length-1].objRef = objRef;
195
  objRef.firstImageLoaded = true;
196
  objRef.loadImgDiv(layerNode,newSrc,objRef.imageStack[objRef.imageStack.length-1]);
197
}
198

    
199
/**
200
 * Removes a layer from the output
201
 * @param layerName the WMS anme for the layer to be removed
202
 */
203
MapPane.prototype.deleteLayer = function(objRef, layerName) {
204
  var imgDivId = objRef.getLayerDivId(layerName); 
205
  var imgDiv = document.getElementById(imgDivId);
206
  var outputNode = document.getElementById( objRef.outputNodeId );
207
  outputNode.removeChild(imgDiv);
208
}
209

    
210
/**
211
 * Moves a layer up in the stack of map layers
212
 * @param layerName the WMS anme for the layer to be removed
213
 */
214
MapPane.prototype.moveLayerUp = function(objRef, layerName) {
215
  var outputNode = document.getElementById( objRef.outputNodeId );
216
  var imgDivId = objRef.getLayerDivId(layerName); 
217
  var movedNode = document.getElementById(imgDivId);
218
  var sibNode = movedNode.nextSibling;
219
  if (!sibNode) {
220
    alert("can't move node past beginning of list:"+layerName);
221
    return;
222
  }
223
  outputNode.insertBefore(sibNode,movedNode);
224
}
225

    
226
/**
227
 * Moves a layer up in the stack of map layers
228
 * @param layerName the WMS anme for the layer to be removed
229
 */
230
MapPane.prototype.moveLayerDown = function(objRef, layerName) {
231
  var outputNode = document.getElementById( objRef.outputNodeId );
232
  var imgDivId = objRef.getLayerDivId(layerName); 
233
  var movedNode = document.getElementById(imgDivId);
234
  var sibNode = movedNode.previousSibling;
235
  if (!sibNode) {
236
    alert("can't move node past end of list:"+layerName);
237
    return;
238
  }
239
  outputNode.insertBefore(movedNode,sibNode);
240
}
241

    
242
/**
243
 * sets up the image div to be loaded.  Images are preloaded in the imageStack
244
 * array and replaced in the document DOM in the onload handler
245
 * @param layerNode the context layer to be loaded
246
 * @param newSrc the new URL to be used for the image
247
 * @param newImg an HTML IMG object to pre-load the image in
248
 */
249
MapPane.prototype.loadImgDiv = function(layerNode,newSrc,newImg) {
250
  var outputNode = document.getElementById( this.outputNodeId );
251
  var layerName = layerNode.selectSingleNode("wmc:Name").firstChild.nodeValue;  
252
  var layerHidden = (layerNode.getAttribute("hidden")==1)?true:false;  
253
  var imageFormat = "image/gif";
254
  var imageFormatNode = layerNode.selectSingleNode("wmc:FormatList/wmc:Format[@current='1']");  
255
  if (imageFormatNode) imageFormat = imageFormatNode.firstChild.nodeValue;  
256

    
257
  //make sure there is an image DIV in the output node for this layer
258
  var imgDivId = this.getLayerDivId(layerName); 
259
  var imgDiv = document.getElementById(imgDivId);
260
  if (!imgDiv) {
261
    imgDiv = document.createElement("div");
262
    imgDiv.setAttribute("id", imgDivId);
263
    imgDiv.style.position = "absolute"; 
264
    imgDiv.style.visibility = (layerHidden)?"hidden":"visible";
265
    imgDiv.style.top = '0px'; 
266
    imgDiv.style.left = '0px';
267
    imgDiv.imgId = Math.random().toString(); 
268
    var domImg = document.createElement("img");
269
    domImg.id = "real"+imgDiv.imgId;
270
    //domImg.src = this.loadingSrc;
271
    domImg.src = config.skinDir+"/images/Spacer.gif";
272
    domImg.layerHidden = layerHidden;
273
    imgDiv.appendChild(domImg);
274
    outputNode.appendChild(imgDiv);
275
  }
276

    
277
  // preload image
278
  newImg.id = imgDiv.imgId;
279
  newImg.hidden = layerHidden;
280
  newImg.title = layerNode.selectSingleNode("wmc:Title").firstChild.nodeValue;  
281
  newImg.fixPng = false;
282
  if (_SARISSA_IS_IE && imageFormat=="image/png") newImg.fixPng = true;
283
  newImg.onload = MapImgLoadHandler;
284
  newImg.onerror = MapImgErrorHandler;
285
  newImg.onfail = MapImgFailHandler;
286
  newImg.src = newSrc;
287
}
288

    
289
/**
290
* image onload handler function.
291
* Replaces the source with the new one and fixes the displacement to 
292
* compensate the container main div displacement to result in in a zero displacement.
293
* The first image to be returned will hide all other layers and re-position them
294
* and they are made visible when their onload event fires.
295
*/
296
function MapImgLoadHandler() {
297
  var oldImg = document.getElementById("real"+this.id );
298

    
299
  if (!this.objRef.firstImageLoaded) {
300
    this.objRef.firstImageLoaded = true;
301
    var outputNode = document.getElementById( this.objRef.outputNodeId );
302
    var siblingImageDivs = outputNode.childNodes;
303
    for (var i=0; i<siblingImageDivs.length ;++i) {
304
      var sibImg = siblingImageDivs[i].firstChild;
305
      sibImg.parentNode.style.visibility = "hidden";
306
      sibImg.style.visibility = "hidden";//Make sure for IE that the child node is hidden as well
307
      if (_SARISSA_IS_IE) sibImg.src = config.skinDir+"/images/Spacer.gif";
308
    }
309
    if (_SARISSA_IS_IE) siblingImageDivs[0].firstChild.parentNode.parentNode.style.visibility = "hidden";
310
    outputNode.style.left='0px';
311
    outputNode.style.top='0px';
312
  }
313

    
314
  --this.objRef.layerCount;
315
  if (this.objRef.layerCount > 0) {
316
    var message = "loading " + this.objRef.layerCount + " map layers"
317
    this.objRef.model.setParam("modelStatus", message);
318
  } else {
319
    this.objRef.model.setParam("modelStatus");
320
  }
321
  var legendText = document.getElementById( this.title + "_legendText" );
322
  legendText.style.textDecoration = "none";
323

    
324
  if (_SARISSA_IS_IE) oldImg.parentNode.parentNode.style.visibility = "visible";
325
  if (this.fixPng) {
326
    var vis = oldImg.layerHidden?"hidden":"visible";
327
    oldImg.outerHTML = fixPNG(this,"real"+this.id);
328
    if (!this.hidden) {
329
      fixImg = document.getElementById("real"+this.id); // The result of fixPng is a span, so we need to set that particular element visible
330
      fixImg.style.visibility = "visible"
331
    }
332
  } else {
333
    oldImg.src = this.src;
334
    oldImg.width = this.objRef.model.getWindowWidth();
335
    oldImg.height = this.objRef.model.getWindowHeight();
336
    if (!this.hidden) {
337
      oldImg.parentNode.style.visibility = "visible";
338
      oldImg.style.visibility = "visible"; //Make sure for IE that the child node is visible as well
339
    }
340
  }
341
}
342

    
343
function MapImgFailHandler() {
344
  --this.objRef.layerCount;
345
  if (this.objRef.layerCount > 0) {
346
    var message = "loading " + this.objRef.layerCount + " map layer" + ((this.objRef.layerCount>1)?"s":"");
347
    this.objRef.model.setParam("modelStatus", message);
348
  } else {
349
    this.objRef.model.setParam("modelStatus");
350
  }
351
  var legendText = document.getElementById( this.title + "_legendText" );
352
  legendText.style.textDecoration = "line-through";
353
}
354

    
355
function MapImgErrorHandler() {
356
  --this.objRef.layerCount;
357
  if (this.objRef.layerCount > 0) {
358
    var message = "loading " + this.objRef.layerCount + " map layer" + ((this.objRef.layerCount>1)?"s":"");
359
    this.objRef.model.setParam("modelStatus", message);
360
  } else {
361
    this.objRef.model.setParam("modelStatus");
362
  }
363
  var legendText = document.getElementById( this.title + "_legendText" );
364
  legendText.style.textDecoration = "line-through";
365
}
366

    
(76-76/145)