Project

General

Profile

1
/*
2
License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html
3
Dependancies: Sarissa
4

    
5
$Id: Util.js 3961 2008-04-01 12:45:02Z ahocevar $
6
*/
7

    
8
// some basic browser detection
9
var MB_IS_MOZ = (document.implementation && document.implementation.createDocument)?true:false;
10

    
11
/**
12
Transform an XML document using the provided XSL and use the results to build
13
a web page.
14
@constructor
15
@param xslUrl The URL of an XSL stylesheet.
16
@author Cameron Shorter - Cameron AT Shorter.net
17
*/
18
function XslProcessor(xslUrl,docNSUri) {
19
  // override Sarissa configurations to prefer MSXML3, because
20
  // MSXML6 does not work well with IE6SP2
21
  if (!MB_IS_MOZ) {
22
    _SARISSA_DOM_PROGID = Sarissa.pickRecentProgID(["Msxml2.DOMDocument.3.0", "Msxml2.DOMDocument.6.0"], [["SELECT_NODES", 2],["TRANSFORM_NODE", 2]]);
23
    _SARISSA_XMLHTTP_PROGID = Sarissa.pickRecentProgID(["Msxml2.XMLHTTP.3.0", "MSXML2.XMLHTTP.6.0"], [["XMLHTTP", 4]]);
24
    _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["Msxml2.FreeThreadedDOMDocument.3.0", "MSXML2.FreeThreadedDOMDocument.6.0"]);
25
    _SARISSA_XSLTEMPLATE_PROGID = Sarissa.pickRecentProgID(["Msxml2.XSLTemplate.3.0", "MSXML2.XSLTemplate.6.0"], [["XSLTPROC", 2]]);
26
  }
27
  // get the stylesheet document
28
  this.xslUrl=xslUrl;
29
  this.xslDom = Sarissa.getDomDocument();
30
  this.xslDom.async = false;
31
  // fix some issues in IE
32
  if (!MB_IS_MOZ) {
33
    try {
34
      // IE6 SP2 parsing bug
35
      this.xslDom.validateOnParse=false;
36
      // Prevent "Access denied" with external documents
37
      this.xslDom.setProperty("AllowDocumentFunction", true);
38
      this.xslDom.resolveExternals = true;
39
    }
40
    catch (e) {
41
      // do nothing here, we won't get far anyway.
42
    }
43
  }
44
  if(typeof(inlineXSL)!="undefined") {
45
    xmlString = inlineXSL[_1];
46
    xmlString = xmlString.replace(/DOUBLE_QUOTE/g,"\"");
47
    this.xslDom = (new DOMParser()).parseFromString(xmlString, "text/xml");
48
  }
49
  else {
50
    if(_SARISSA_IS_SAFARI){
51
        var xmlhttp = new XMLHttpRequest();
52
        xmlhttp.open("GET", xslUrl, false);
53
        xmlhttp.send(null);
54
        this.xslDom = xmlhttp.responseXML;
55
    }else
56
    {
57
      this.xslDom.load(xslUrl);
58
    }
59
  }
60
  if ( Sarissa.getParseErrorText(this.xslDom) != Sarissa.PARSED_OK )
61
    alert(mbGetMessage("errorLoadingStylesheet", xslUrl));
62

    
63
  this.processor = new XSLTProcessor();
64
  this.processor.importStylesheet(this.xslDom);
65
  
66
  this.docNSUri = docNSUri;
67

    
68
  /**
69
   * Transforms XML in the provided xml node according to this XSL.
70
   * @param xmlNode The XML node to be transformed.
71
   * @return The transformed String.
72
   */
73
  this.transformNodeToString = function(xmlNode) {
74
    try {
75
      // transform and build a web page with result
76
      //MAP-427 Quick hack to transform an XMLElement to XMLDocument in IE
77
     
78
      if (_SARISSA_IS_IE){
79
	      var str = (new XMLSerializer()).serializeToString(xmlNode);
80
	      var xmlNode = (new DOMParser()).parseFromString(str, "text/xml");
81
	  }
82
      var newDoc = this.transformNodeToObject(xmlNode);
83
      var s = (new XMLSerializer()).serializeToString(newDoc);
84
      if(_SARISSA_IS_OPERA)
85
      	s =  s.replace(/.*\?\>/,"");//hack for opera to delete <?xml ... ?>
86
      return s;
87
    } catch(e){
88
      alert(mbGetMessage("exceptionTransformingDoc", this.xslUrl));
89
      alert("XSL="+(new XMLSerializer()).serializeToString(this.xslDom));
90
      alert("XML="+(new XMLSerializer()).serializeToString(xmlNode));
91
    }
92
  }
93

    
94
  /**
95
   * Transforms XML in the provided xml node according to this XSL.
96
   * @param xmlNode The XML node to be transformed.
97
   * @return a DOM document object
98
   */
99
  this.transformNodeToObject=function(xmlNode) {
100
    if(_SARISSA_IS_SAFARI){
101
      var oResult = new DOMParser().parseFromString("<xsltresult></xsltresult>", "text/xml");
102
      var newFragment = this.processor.transformToFragment(xmlNode, oResult);
103
      var str = (new XMLSerializer()).serializeToString(newFragment);
104
      str.replace(/\s/g,"");
105
    }else{
106
       var newFragment = this.processor.transformToDocument(xmlNode);
107
    }
108
    return newFragment;
109
  }
110

    
111
  /**
112
   * Set XSL parameter.
113
   */
114
  this.setParameter=function(paramName, paramValue, nsUri) {
115
    //if ( typeof paramValue == "string" || typeof paramValue == "number") paramValue="'"+paramValue+"'";
116
    if (!paramValue) {
117
      //alert("null value for stylesheet param:"+paramName+":"+paramValue);
118
      return;
119
    }
120
    this.processor.setParameter( null, paramName, paramValue);
121
  }
122
}
123

    
124
/**
125
 * A more flexible interface for loading docs that allows POST and async loading
126
 */
127
function postLoad(sUri, docToSend, contentType ) {
128
   var xmlHttp = new XMLHttpRequest();
129
   if ( sUri.indexOf("http://")==0 || sUri.indexOf("https://")==0 ) {
130
     xmlHttp.open("POST", config.proxyUrl, false);
131
     xmlHttp.setRequestHeader("serverUrl",sUri);//escape(sUri).replace(/\+/g, '%2C').replace(/\"/g,'%22').replace(/\'/g, '%27'));
132
   } else {
133
     xmlHttp.open("POST", sUri, false);
134
   }
135
   xmlHttp.setRequestHeader("content-type","text/xml");
136
   if (contentType) xmlHttp.setRequestHeader("content-type",contentType);
137
   //alert("sending:"+docToSend.xml);
138
   xmlHttp.send( docToSend );
139
/*
140
   if (_SARISSA_IS_IE) {
141
alert("before");
142
    xmlHttp.status = xmlHttp.Status;
143
alert("after");
144
    xmlHttp.statusText = xmlHttp.StatusText;
145
    xmlHttp.responseText = xmlHttp.ResponseText;
146
   }
147
*/
148
   if (xmlHttp.status >= 400) {   //http errors status start at 400
149
      alert(mbGetMessage("errorLoadingDocument", sUri, xmlHttp.statusText, xmlHttp.responseText));
150
      var outDoc = Sarissa.getDomDocument();
151
      outDoc.parseError = -1;
152
      return outDoc;
153
   } else {
154
     //alert(xmlHttp.getResponseHeader("Content-Type"));
155
     if ( null==xmlHttp.responseXML ) alert(mbGetMessage("nullXmlResponse", xmlHttp.responseText));
156
     return xmlHttp.responseXML;
157
   }
158
}
159

    
160

    
161
/**
162
 * A more flexible interface for loading docs that allows POST et GET param for save model
163
 */
164

    
165
function postGetLoad(sUri, docToSend, contentType , dir, fileName) {
166

    
167
   var xmlHttp = new XMLHttpRequest();
168
   var appendChar = sUri.indexOf("?") == -1 ? "?" : "&";
169
   if(dir && fileName)
170
       	sUri=sUri+appendChar+"dir="+dir+"&fileName="+fileName;
171
   else if(dir)
172
   		sUri=sUri+appendChar+"dir="+dir;
173
   else if(fileName)
174
   		sUri=sUri+appendChar+"fileName="+fileName;
175
   		
176
   if ( sUri.indexOf("http://")==0 || sUri.indexOf("https://")==0 )
177
   {
178
       xmlHttp.open("POST", config.proxyUrl, false);       
179
       xmlHttp.setRequestHeader("serverUrl",sUri);
180
   }
181
   else
182
   {
183
       xmlHttp.open("POST", sUri, false);
184
   }
185
   xmlHttp.setRequestHeader("content-type","text/xml");
186
   if (contentType) xmlHttp.setRequestHeader("content-type",contentType);
187
   xmlHttp.send( docToSend );
188

    
189
   if (xmlHttp.status >= 400)
190
   {   //http errors status start at 400
191
        alert(mbGetMessage("errorLoadingDocument", sUri, xmlHttp.statusText, xmlHttp.responseText));
192
        var outDoc = Sarissa.getDomDocument();
193
        outDoc.parseError = -1;
194
        return outDoc;
195
   }
196
   else
197
   {
198
       if ( null==xmlHttp.responseXML ) alert(mbGetMessage("nullXmlResponse", xmlHttp.responseText));
199
       return xmlHttp.responseXML;
200
   }
201
}
202

    
203

    
204

    
205
  /**
206
   * If URL is local, then return URL unchanged,
207
   * else return URL of http://proxy?url=URL , or null if proxy not defined.
208
   * @param url Url of the file to access.
209
   * @return Url of the proxy and service in the form http://host/proxy?url=service
210
   */
211
function getProxyPlusUrl(url) {
212
  if ( url.indexOf("http://")==0 || url.indexOf("https://")==0 ) {
213
    if ( config.proxyUrl ) {
214
      url=config.proxyUrl+"?url="+escape(url).replace(/\+/g, '%2C').replace(/\"/g,'%22').replace(/\'/g, '%27');
215
    } else {
216
      alert(mbGetMessage("unableToLoadDoc", url));
217
      url=null;
218
    }
219
  }
220
  return url;
221
}
222

    
223
  /**
224
   * Browser independant version of createElementNS()
225
   * @param doc the owner document for the new element
226
   * @param name for the new element
227
   * @param ns the URL for the namespace (without a prefix)
228
   * @return element in the document with the specified namespace
229
   */
230
function createElementWithNS(doc,name,nsUri) {
231
  if (_SARISSA_IS_IE) {
232
    return doc.createNode(1, name, nsUri);
233
  } else {
234
    return doc.createElementNS(nsUri,name);
235
  }
236
}
237

    
238
/**
239
 * Create a unique Id which can be used for classes to link themselves to HTML
240
 * Ids.
241
 * @constructor
242
 */
243
function UniqueId(){
244
  this.lastId=0;
245

    
246
  /** Return a numeric unique Id. */
247
  this.getId=function() {
248
    this.lastId++;
249
    return this.lastId;
250
  }
251
}
252
//use this global object to generate a unique ID via the getId function
253
var mbIds = new UniqueId();
254

    
255
function setISODate(isoDateStr) {
256
  var parts = isoDateStr.match(/(\d{4})-?(\d{2})?-?(\d{2})?T?(\d{2})?:?(\d{2})?:?(\d{2})?\.?(\d{0,3})?(Z)?/);
257
  var res = null;
258
  for (var i=1;i<parts.length;++i){
259
    if (!parts[i]) {
260
      parts[i] = (i==3)?1:0; //months start with day number 1, not 0
261
      if (!res) res = i;
262
    }
263
  }
264
  var isoDate = new Date();
265
  isoDate.setFullYear(parseInt(parts[1],10));
266
  isoDate.setMonth(parseInt(parts[2],10)-1,parseInt(parts[3],10));
267
  isoDate.setDate(parseInt(parts[3],10));
268
  isoDate.setHours(parseInt(parts[4],10));
269
  isoDate.setMinutes(parseInt(parts[5],10));
270
  isoDate.setSeconds(parseFloat(parts[6],10));
271
  if (!res) res = 6;
272
  isoDate.res = res;
273
  return isoDate;
274
}
275

    
276
function getISODate(isoDate) {
277
  var res = isoDate.res?isoDate.res:6;
278
  var dateStr = "";
279
  dateStr += res>=1?isoDate.getFullYear():"";
280
  dateStr += res>=2?"-"+leadingZeros(isoDate.getMonth()+1,2):"";
281
  dateStr += res>=3?"-"+leadingZeros(isoDate.getDate(),2):"";
282
  dateStr += res>=4?"T"+leadingZeros(isoDate.getHours(),2):"";
283
  dateStr += res>=5?":"+leadingZeros(isoDate.getMinutes(),2):"";
284
  dateStr += res>=6?":"+leadingZeros(isoDate.getSeconds(),2):"";
285
  return dateStr;
286
}
287

    
288
function leadingZeros(num,digits) {
289
  var intNum = parseInt(num,10);
290
  var base = Math.pow(10,digits);
291
  if (intNum<base) intNum += base;
292
  return intNum.toString().substr(1);
293
}
294

    
295

    
296
// Correctly handle PNG transparency in Win IE 5.5 or higher.
297
// this method should be set as an IMG onload handler for PNG map layers
298
// thanks to Caroklyn Cole for this fix.  For an explanation see:
299
// http://homepage.ntlworld.com/bobosola. Updated 02-March-2004
300
// modified to the images as visible after this has been called.
301
// PL-BRGM
302
// Add oldImage in parameter
303
function fixPNG(myImage,myId,oldImage) {
304
  if (_SARISSA_IS_IE) {
305
    // PL - BRGM
306
    //opacity of the image
307
    if(oldImage) {
308
      var valIEOpacity= oldImage.style.filter.substring(oldImage.style.filter.indexOf('opacity=',0)+8,oldImage.style.filter.lastIndexOf(')',0));
309
      if(oldImage.style.filter.indexOf('opacity=',0) ==-1){
310
        valIEOpacity = null;
311
      }
312
       var _opacity= (valIEOpacity)?valIEOpacity/100:-1;
313
     }
314
  // END
315
    var imgID = "id='" + myId + "' ";
316
    var imgClass = (myImage.className) ? "class='" + myImage.className + "' " : ""
317
    var imgTitle = (myImage.title) ? "title='" + myImage.title + "' " : "title='" + myImage.alt + "' "
318
    var imgStyle = "display:inline-block;" + myImage.style.cssText
319
    var strNewHTML = "<span " + imgID + imgClass + imgTitle
320

    
321
    strNewHTML += " style=\"" + "width:" + myImage.width + "px; height:" + myImage.height + "px;" + imgStyle + ";"
322
    // store the opacity in the style even not used by IE
323
    if (_opacity!=-1) strNewHTML += "opacity=" + _opacity + ";" ;
324
    // Escape some chars (don't use encode() that would escape %xx previously used in XSL)
325
    var src = myImage.src;
326
    src = src.replace(/\(/g,'%28');
327
    src = src.replace(/\)/g,'%29');
328
    src = src.replace(/'/g,'%27');
329
    // AlphaImageLoader converts '%23' in src to '#' and cuts URL on '#'
330
    src = src.replace(/%23/g,'%2523');
331
    strNewHTML += "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader";
332
    strNewHTML += "(src=\'" + src + "\', sizingMethod='scale')";
333

    
334
    // PL - BRGM
335
    // add the opacity
336
    if (oldImage && _opacity!=-1) strNewHTML +=  " alpha(opacity=" + (_opacity * 100) + ")";
337
    strNewHTML +="; \"></span>" ;
338
  // END PL - BRGM
339
    //myImage.outerHTML = strNewHTML;
340
    //alert(strNewHTML);
341
    return strNewHTML;
342
  }
343
}
344

    
345

    
346

    
347
/**
348
 * get the absolute position of HTML element NS4, IE4/5 & NS6, even if it's in a table.
349
 * @param element The HTML element.
350
 * @return Top left X position.
351
 */
352
function getAbsX(elt) {
353
        return (elt.x) ? elt.x : getAbsPos(elt,"Left") + 2;
354
}
355

    
356
/**
357
 * get the absolute position of HTML element NS4, IE4/5 & NS6, even if it's in a table.
358
 * @param element The HTML element.
359
 * @return Top left Y position.
360
 */
361
function getAbsY(elt) {
362
        return (elt.y) ? elt.y : getAbsPos(elt,"Top") + 2;
363
}
364

    
365
/**
366
 * TBD: Comment me.
367
 * @param elt TBD
368
 * @param which TBD
369
 */
370
function getAbsPos(elt,which) {
371
 iPos = 0;
372
 while (elt != null) {
373
        iPos += elt["offset" + which];
374
        elt = elt.offsetParent;
375
 }
376
 return iPos;
377
}
378

    
379
/**
380
 * get the absolute position of a user event (e.g., a mousedown).
381
 * @param e The user event.
382
 * @return Left or top position.
383
 */
384
function getPageX(e){
385
  var posx = 0;
386
  if (!e) var e = window.event;
387
  if (e.pageX) {
388
    posx = e.pageX;
389
  }
390
  else if (e.clientX) {
391
   posx = e.clientX;
392
  }
393
  if (document.body && document.body.scrollLeft){
394
    posx += document.body.scrollLeft;
395
  }
396
  else if (document.documentElement && document.documentElement.scrollLeft){
397
    posx += document.documentElement.scrollLeft;
398
  }
399
  return posx;
400
}
401

    
402
/**
403
 * get the absolute position of a user event (e.g., a mousedown).
404
 * @param e The user event.
405
 * @return Left or top position.
406
 */
407
function getPageY(e){
408
  var posy = 0;
409
  if (!e) var e = window.event;
410
  if (e.pageY) {
411
    posy = e.pageY;
412
  }
413
  else if (e.clientY) {
414
    posy = e.clientY;
415
  }
416
  if (document.body && document.body.scrollTop){
417
    posy += document.body.scrollTop;
418
  }
419
  else if (document.documentElement && document.documentElement.scrollTop){
420
    posy += document.documentElement.scrollTop;
421
  }
422
  return posy;
423
}
424

    
425
/**
426
 * parse comma-separated name=value argument pairs from the query string of the URL; the function stores name=value pairs in properties of an object and returns that object.
427
 * @return args Array of arguments passed to page, in form args[argname] = value.
428
 */
429
function getArgs(){
430
  var args = new Object();
431
  var query = location.search.substring(1);
432
  var pairs = query.split("&");
433
  for(var i = 0; i < pairs.length; i++) {
434
    var pos = pairs[i].indexOf('=');
435
    if (pos == -1) continue;
436
    var argname = pairs[i].substring(0,pos);
437
    var value = pairs[i].substring(pos+1);
438
    args[argname] = unescape(value.replace(/\+/g, " "));
439
  }
440
  return args;
441
}
442
//initialize the array once
443
window.cgiArgs = getArgs();
444

    
445
/**
446
 * convert geographic x coordinate to screen coordinate.
447
 * @param context The context object.
448
 * @param xCoord The geographic x coordinate to be converted.
449
 * @return x the converted x coordinate.
450
 */
451
function getScreenX(context, xCoord){
452
  bbox=context.getBoundingBox();
453
  width=context.getWindowWidth();
454
  bbox[0]=parseFloat(bbox[0]);
455
  bbox[2]=parseFloat(bbox[2]);
456
  var xfac = (width/(bbox[2]-bbox[0]));
457
  x=xfac*(xCoord-bbox[0]);
458
  return x;
459
}
460

    
461
/**
462
 * convert geographic y coordinate to screen coordinate.
463
 * @param context The context object.
464
 * @param yCoord The geographic x coordinate to be converted.
465
 * @return y the converted x coordinate.
466
 */
467
function getScreenY(context, yCoord){
468
  var bbox=context.getBoundingBox();
469
  var height=context.getWindowHeight();
470
  bbox[1]=parseFloat(bbox[1]);
471
  bbox[3]=parseFloat(bbox[3]);
472
  var yfac = (heighteight/(bbox[3]-bbox[1]));
473
  var y=height-(yfac*(pt.y-bbox[1]));
474
  return y;
475
}
476

    
477
/**
478
 * convert screen x coordinate to geographic coordinate.
479
 * @param context The context object.
480
 * @param xCoord The screen x coordinate to be converted.
481
 * @return x the converted x coordinate.
482
 */
483
function getGeoCoordX(context, xCooord) {
484
  var bbox=context.getBoundingBox();
485
  var width=context.getWindowWidth();
486
  bbox[0]=parseFloat(bbox[0]);
487
  bbox[2]=parseFloat(bbox[2]);
488
  var xfac = ((bbox[2]-bbox[0]) / width);
489
  var x=bbox[0] + xfac*(xCoord);
490
  return x;
491
}
492

    
493
/**
494
 * convert screen coordinate to screen coordinate.
495
 * @param context The context object.
496
 * @param yCoord The geographic y coordinate to be converted.
497
 * @return y the converted y coordinate.
498
 */
499
function getGeoCoordY(yCoord){
500
  var bbox=context.getBoundingBox();
501
  var height=context.getWindowHeight();
502
  bbox[1]=parseFloat(bbox[1]);
503
  bbox[3]=parseFloat(bbox[3]);
504
  var yfac = ((bbox[3]-bbox[1]) / height);
505
  var y=bbox[1] + yfac*(height-yCoord);
506
  return y;
507
}
508

    
509
/**
510
 * create an element and append it to the document body element.
511
 * @param type The type of element to be created.
512
 * @return node The node created and appended.
513
 */
514
function makeElt(type) {
515
  var node=document.createElement(type);
516
  document.getElementsByTagName("body").item(0).appendChild(node);
517
  return node;
518
}
519

    
520
// variable needed to determine if a popup window is currently open
521
var newWindow = '';
522
/**
523
 * open a popup window, adapted from http://www.quirksmode.org/js/croswin.html
524
 * @param url The url of the page to be opened.
525
 * @param width Width of the popup window, in pixels.
526
 * @param height Height of the popup window, in pixels.
527
 */
528
function openPopup(url, width, height) {
529
  if(width == null) {
530
    width = 300;
531
  }
532
  if(height == null) {
533
    height = 200;
534
  }
535
  if (!newWindow.closed && newWindow.location) {
536
    newWindow.location.href = url;
537
  }
538
  else {
539
    newWindow=window.open(url,'name','height=' + height + ',width=' + width);
540
    if (!newWindow.opener) newwindow.opener = self;
541
  }
542
  if (window.focus) {newWindow.focus()}
543
  return false;
544
}
545

    
546
/**
547
 * write debugging info to a textbox onscreen.
548
 * @param output String to be output.
549
 */
550
function debug(output){
551
  tarea=makeElt("textarea");
552
  tarea.setAttribute("rows","3");
553
  tarea.setAttribute("cols","40");
554
  tnode=document.createTextNode(output);
555
  tarea.appendChild(tnode);
556
}
557

    
558
/**
559
 * determine and return the target element of an event.
560
 * @param evt The event.
561
 * @return elt The element.
562
 */
563
function returnTarget(evt){
564
  evt = (evt) ? evt : ((window.event) ? window.event : "");
565
  var elt=null;
566
  if(evt.target){
567
    elt=evt.target;
568
  }
569
  else if(evt.srcElement){
570
    elt=evt.srcElement;
571
  }
572
  return elt;
573
}
574

    
575
/**
576
 * attach an event to an element.
577
 * @param elementObject The object.
578
 * @param eventName The name of the event.
579
 * @param functionObject The function to be called.
580
 */
581
function addEvent(elementObject, eventName, functionObject) {
582
  if(document.addEventListener) {
583
    elementObject.addEventListener(eventName, functionObject, false);
584
  }
585
  else if(document.attachEvent) {
586
    elementObject.attachEvent("on" + eventName, functionObject);
587
  }
588
}
589

    
590
/**
591
 * handle event attached to an object.
592
 * @param evt The event.
593
 */
594
function handleEventWithObject(evt){
595
  var elt = returnTarget(evt);
596
  var obj = elt.ownerObj;
597
  if (obj!=null) obj.handleEvent(evt);
598
}
599

    
600
/**
601
 * Show a message if the debug property of the object has been set.
602
 * @param object  the object that possibly has the debug property set
603
 * @param message the message to show
604
 */
605
function mbDebugMessage(object, message)
606
{
607
  if (object && object.debug) {
608
    alert(message);
609
  }
610
}
611

    
612
/**
613
 * Get a message from the <code>widgetText</code> file and format it if extra
614
 * arguments are passed.
615
 * @param messageKey       the message key within the message node
616
 * @param varArgs          optional extra parameters for formatting the message
617
 * @return                 <code>"NoMsgsFound"</code> if the <code>widgetText</code> file is not found,<br/>
618
 *                         the <code>messageKey</code> if the message key was not found within the message node,<br/>
619
 *                         the (formatted) message if it was found
620
 */
621
function mbGetMessage(messageKey)
622
{
623
  var message = "NoMsgsFound";
624
  if (config.widgetText) {
625
    var msgKeyXpath = "/mb:WidgetText/mb:messages/mb:" + messageKey;
626
    var msgKeyNodes = config.widgetText.selectNodes(msgKeyXpath);
627
    if (!msgKeyNodes || msgKeyNodes.length == 0) {
628
      // Message not found, fall back to message key
629
      message = messageKey;
630
    }
631
    else {
632
      // Message found; pick last one so user can override messages
633
      message = getNodeValue(msgKeyNodes.item(msgKeyNodes.length-1));
634
      if (arguments[mbGetMessage.length]) {
635
        // Extra arguments, format message
636
        var varArgs = [].slice.call(arguments, mbGetMessage.length);
637
        varArgs.unshift(message);
638
        message = mbFormatMessage.apply(this, varArgs);
639
      }
640
    }
641
  }
642
  return message;
643
}
644

    
645
/**
646
 * Format a message with the extra arguments. <br/>
647
 * E.g. if called as: <code>mbFormatMessage("{1} is {0} {2}, {1}", "a good", "this", "test")</code><br/>
648
 * the formatted message returned is: <code>"this is a good test, this"</code>
649
 * @param messageFormat the message format string
650
 * @param varArgs       optional extra parameters for formatting the message
651
 * @return              the formatted message
652
 */
653
function mbFormatMessage(messageFormat)
654
{
655
  var message = messageFormat;
656
  var varArgs = [].slice.call(arguments, mbFormatMessage.length);
657
  for (var i=0; i<varArgs.length; i++) {
658
    var parm = new RegExp("\\{" + i + "\\}", "g");
659
    message = message.replace(parm, varArgs[i]);
660
  }
661
  return message;
662
}
663

    
664
/**
665
 * extract a style from a SLD node of an XML doc and return
666
 * it as url parameter for a WMS request
667
 * @param node XML node containing the styled layer descriptor
668
 * @return WMS-compliant SLD URL parameters as array
669
 */
670
function sld2UrlParam(node) {
671
  var params=new Array();
672
  if (node) {
673
    var sld = node.selectSingleNode("wmc:SLD");
674
    var name = node.selectSingleNode("wmc:Name");
675
    if(sld) {
676
      if(sld.selectSingleNode("wmc:OnlineResource")) {	
677
        params.sld=sld.selectSingleNode("wmc:OnlineResource").getAttribute("xlink:href");
678
      } else if(sld.selectSingleNode("wmc:FeatureTypeStyle")) {
679
        params.sld=(new XMLSerializer()).serializeToString(sld.selectSingleNode("wmc:FeatureTypeStyle"));
680
      } else if(sld.selectSingleNode("wmc:StyledLayerDescriptor")) { 
681
        params.sld_body=(new XMLSerializer()).serializeToString(sld.selectSingleNode("wmc:StyledLayerDescriptor"));    		
682
      }
683
    } else if(name) {
684
      params.styles = getNodeValue(name) || "";	
685
    }
686
  }  
687
  return params;
688
}
689

    
690
/**
691
 * extract a style from a SLD node of an XML doc and return
692
 * it as OpenLayers style
693
 * @param objRef reference to the map widget that will use the style
694
 * @param node XML node containing the styled layer descriptor
695
 * @return OpenLayers style object
696
 */
697
function sld2OlStyle(node) {
698
  // OpenLayers SLD parsing
699
  if (node) {
700
    var ruleNode = node.selectSingleNode("wmc:SLD/sld:FeatureTypeStyle");
701
    if (ruleNode) {
702
      var sld = new XMLSerializer().serializeToString(ruleNode);
703
      var search = /<([^:]*:?)StyledLayerDescriptor/;
704
      if (!search.test(sld)) {
705
      	sld = sld.replace(/<([^:]*:?)FeatureTypeStyle([^>]*)>(.*)$/,
706
            "<$1StyledLayerDescriptor$2><$1NamedLayer><$1Name>sld</$1Name><$1UserStyle><$1FeatureTypeStyle>$3</$1UserStyle></$1NamedLayer></$1StyledLayerDescriptor>");
707
      }
708
    }
709
    var styles = new OpenLayers.Format.SLD().read(sld);
710
    if (styles) {
711
      return styles.namedLayers["sld"].userStyles[0];
712
    }
713
  }
714
  
715
  // fallback to native SLD parsing for older OwsContext docs
716
  
717
  // sld-conform default style
718
  var defaultStyle = {
719
            fillColor: "#808080",
720
            fillOpacity: 1,
721
            strokeColor: "#000000",
722
            strokeOpacity: 1,
723
            strokeWidth: 1,
724
            pointRadius: 6};
725
            
726
  var style1=OpenLayers.Util.extend(defaultStyle,OpenLayers.Feature.Vector.style["default"]);
727
  var value;
728
  var styleSet=false;
729

    
730
  if (node) {
731
    value=node.selectSingleNode(".//sld:ExternalGraphic/sld:OnlineResource/@xlink:href");
732
    if(value){
733
      style1.externalGraphic=getNodeValue(value);
734
      styleSet=true;
735
    }
736
    value=node.selectSingleNode(".//sld:Fill/sld:CssParameter[@name='fill']");
737
    if(value){
738
      style1.fillColor=getNodeValue(value);
739
      styleSet=true;
740
    }
741
    value=node.selectSingleNode(".//sld:Fill/sld:CssParameter[@name='fill-opacity']");
742
    if(value){
743
      style1.fillOpacity=getNodeValue(value);
744
      styleSet=true;
745
    } else {
746
      // opacity eg. for externalGraphic
747
      value=node.selectSingleNode(".//sld:Opacity/sld:Literal");
748
      if (value){
749
        style1.fillOpacity=getNodeValue(value);
750
        styleSet=true;
751
      }
752
    }
753
  
754
    value=node.selectSingleNode(".//sld:Stroke/sld:CssParameter[@name='stroke']");
755
    if(value){
756
      style1.strokeColor=getNodeValue(value);
757
      styleSet=true;
758
    }
759
    
760
    value=node.selectSingleNode(".//sld:Stroke/sld:CssParameter[@name='stroke-opacity']");
761
    if(value){
762
      style1.strokeOpacity=getNodeValue(value);
763
      styleSet=true;
764
    }
765
    
766
    value=node.selectSingleNode(".//sld:Stroke/sld:CssParameter[@name='stroke-width']");
767
    if(value){
768
      style1.strokeWidth=getNodeValue(value);
769
      styleSet=true;
770
    }
771
    
772
    value=node.selectSingleNode(".//sld:Size");
773
    if(value){
774
      style1.pointRadius=getNodeValue(value);
775
      styleSet=true;
776
    }
777
  }
778
  
779
  if(!styleSet)style1=null;
780
  return style1;
781
}
782

    
783
/**
784
 * Dynamically loads a stylesheet into the html page.
785
 * @param cssFileName name of the file to load, relative to config.skinDir
786
 */
787
function loadCss(cssFileName) {
788
  // queue the request if we do not know the skinDir yet
789
  if (typeof config == "undefined" || typeof config.skinDir != "string") {
790
    if (!mapbuilder.cssToLoad) {
791
      mapbuilder.cssToLoad = [];
792
    }
793
    mapbuilder.cssToLoad.push(cssFileName);
794
    return;
795
  }
796
  
797
  var id = cssFileName.match(/[^\/]*$/).toString().replace(/./, '_');
798
  if (!document.getElementById(id)) {
799
    var cssNode = document.createElement('link');
800
    cssNode.setAttribute('id', id);
801
    cssNode.setAttribute('rel', 'stylesheet');
802
    cssNode.setAttribute('type', 'text/css');
803
    cssNode.setAttribute('href', config.skinDir+'/'+cssFileName);
804
    document.getElementsByTagName('head')[0].appendChild(cssNode);
805
  }
806
}
807

    
808
/**
809
 * getNodevalue return value of node
810
 * it as OpenLayers style
811
 * @param node 
812
 * @return return node's value
813
 */
814
function getNodeValue(sResult){
815
  if(sResult.nodeType == 1) return sResult.firstChild ? sResult.firstChild.nodeValue : "";
816
  if(sResult.nodeType < 5) return sResult.nodeValue;
817
  return sResult;
818
}
819

    
820
/**
821
 * Convenience method that is used to parse dom nodes.
822
 * @param domNode node to find the property in
823
 * @param propertyName string of the property name (including namespace prefix)
824
 * @param defaultValue value to return if property is not found (null by default)
825
 * @return the property value
826
 */
827
Mapbuilder.getProperty = function(domNode, propertyName, defaultValue) {
828
  if (typeof defaultValue == "undefined") {
829
    defaultValue = null;
830
  }
831
  var property = domNode.selectSingleNode(propertyName);
832
  return property ? getNodeValue(property) : defaultValue;
833
}
834

    
835
/**
836
 * Convenience method to parse a string or number as a boolean value
837
 * @param value string (true/false) or number (1/0)
838
 * @return boolean value, default false
839
 */
840
Mapbuilder.parseBoolean = function(value) {
841
  var result = false;
842
  if (!value) {
843
    result = false;
844
  } else if (value == 0) {
845
    result = false;
846
  } else if (value == 1) {
847
      result = true;
848
  } else if (value.match(/true/i)) {
849
    result = true;
850
  } else if (value.match(/false/i)){
851
    return false;
852
  }
853
  return result;
854
}
(3-3/5)