~mortenoh/+junk/dhis2-detailed-import-export

« back to all changes in this revision

Viewing changes to gis/dhis-gis-geostat/mfbase/openlayers/lib/OpenLayers/Util.js

  • Committer: larshelge at gmail
  • Date: 2009-03-03 16:46:36 UTC
  • Revision ID: larshelge@gmail.com-20090303164636-2sjlrquo7ib1gf7r
Initial check-in

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
 
2
 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 
3
 * full text of the license. */
 
4
 
 
5
 
 
6
/**
 
7
 * Namespace: Util
 
8
 */
 
9
OpenLayers.Util = {};
 
10
 
 
11
/** 
 
12
 * Function: getElement
 
13
 * This is the old $() from prototype
 
14
 */
 
15
OpenLayers.Util.getElement = function() {
 
16
    var elements = [];
 
17
 
 
18
    for (var i=0, len=arguments.length; i<len; i++) {
 
19
        var element = arguments[i];
 
20
        if (typeof element == 'string') {
 
21
            element = document.getElementById(element);
 
22
        }
 
23
        if (arguments.length == 1) {
 
24
            return element;
 
25
        }
 
26
        elements.push(element);
 
27
    }
 
28
    return elements;
 
29
};
 
30
 
 
31
/** 
 
32
 * Maintain $() from prototype
 
33
 */
 
34
if ($ == null) {
 
35
    var $ = OpenLayers.Util.getElement;
 
36
}
 
37
 
 
38
/**
 
39
 * APIFunction: extend
 
40
 * Copy all properties of a source object to a destination object.  Modifies
 
41
 *     the passed in destination object.  Any properties on the source object
 
42
 *     that are set to undefined will not be (re)set on the destination object.
 
43
 *
 
44
 * Parameters:
 
45
 * destination - {Object} The object that will be modified
 
46
 * source - {Object} The object with properties to be set on the destination
 
47
 *
 
48
 * Returns:
 
49
 * {Object} The destination object.
 
50
 */
 
51
OpenLayers.Util.extend = function(destination, source) {
 
52
    destination = destination || {};
 
53
    if(source) {
 
54
        for(var property in source) {
 
55
            var value = source[property];
 
56
            if(value !== undefined) {
 
57
                destination[property] = value;
 
58
            }
 
59
        }
 
60
 
 
61
        /**
 
62
         * IE doesn't include the toString property when iterating over an object's
 
63
         * properties with the for(property in object) syntax.  Explicitly check if
 
64
         * the source has its own toString property.
 
65
         */
 
66
 
 
67
        /*
 
68
         * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative
 
69
         * prototype object" when calling hawOwnProperty if the source object
 
70
         * is an instance of window.Event.
 
71
         */
 
72
 
 
73
        var sourceIsEvt = typeof window.Event == "function"
 
74
                          && source instanceof window.Event;
 
75
 
 
76
        if(!sourceIsEvt
 
77
           && source.hasOwnProperty && source.hasOwnProperty('toString')) {
 
78
            destination.toString = source.toString;
 
79
        }
 
80
    }
 
81
    return destination;
 
82
};
 
83
 
 
84
 
 
85
/** 
 
86
 * Function: removeItem
 
87
 * Remove an object from an array. Iterates through the array
 
88
 *     to find the item, then removes it.
 
89
 *
 
90
 * Parameters:
 
91
 * array - {Array}
 
92
 * item - {Object}
 
93
 * 
 
94
 * Return
 
95
 * {Array} A reference to the array
 
96
 */
 
97
OpenLayers.Util.removeItem = function(array, item) {
 
98
    for(var i = array.length - 1; i >= 0; i--) {
 
99
        if(array[i] == item) {
 
100
            array.splice(i,1);
 
101
            //break;more than once??
 
102
        }
 
103
    }
 
104
    return array;
 
105
};
 
106
 
 
107
/**
 
108
 * Function: clearArray
 
109
 * *Deprecated*. This function will disappear in 3.0.
 
110
 * Please use "array.length = 0" instead.
 
111
 * 
 
112
 * Parameters:
 
113
 * array - {Array}
 
114
 */
 
115
OpenLayers.Util.clearArray = function(array) {
 
116
    OpenLayers.Console.warn(
 
117
        OpenLayers.i18n(
 
118
            "methodDeprecated", {'newMethod': 'array = []'}
 
119
        )
 
120
    );
 
121
    array.length = 0;
 
122
};
 
123
 
 
124
/** 
 
125
 * Function: indexOf
 
126
 * Seems to exist already in FF, but not in MOZ.
 
127
 * 
 
128
 * Parameters:
 
129
 * array - {Array}
 
130
 * obj - {Object}
 
131
 * 
 
132
 * Returns:
 
133
 * {Integer} The index at, which the object was found in the array.
 
134
 *           If not found, returns -1.
 
135
 */
 
136
OpenLayers.Util.indexOf = function(array, obj) {
 
137
 
 
138
    for(var i=0, len=array.length; i<len; i++) {
 
139
        if (array[i] == obj) {
 
140
            return i;
 
141
        }
 
142
    }
 
143
    return -1;   
 
144
};
 
145
 
 
146
 
 
147
 
 
148
/**
 
149
 * Function: modifyDOMElement
 
150
 * 
 
151
 * Modifies many properties of a DOM element all at once.  Passing in 
 
152
 * null to an individual parameter will avoid setting the attribute.
 
153
 *
 
154
 * Parameters:
 
155
 * id - {String} The element id attribute to set.
 
156
 * px - {<OpenLayers.Pixel>} The left and top style position.
 
157
 * sz - {<OpenLayers.Size>}  The width and height style attributes.
 
158
 * position - {String}       The position attribute.  eg: absolute, 
 
159
 *                           relative, etc.
 
160
 * border - {String}         The style.border attribute.  eg:
 
161
 *                           solid black 2px
 
162
 * overflow - {String}       The style.overview attribute.  
 
163
 * opacity - {Float}         Fractional value (0.0 - 1.0)
 
164
 */
 
165
OpenLayers.Util.modifyDOMElement = function(element, id, px, sz, position, 
 
166
                                            border, overflow, opacity) {
 
167
 
 
168
    if (id) {
 
169
        element.id = id;
 
170
    }
 
171
    if (px) {
 
172
        element.style.left = px.x + "px";
 
173
        element.style.top = px.y + "px";
 
174
    }
 
175
    if (sz) {
 
176
        element.style.width = sz.w + "px";
 
177
        element.style.height = sz.h + "px";
 
178
    }
 
179
    if (position) {
 
180
        element.style.position = position;
 
181
    }
 
182
    if (border) {
 
183
        element.style.border = border;
 
184
    }
 
185
    if (overflow) {
 
186
        element.style.overflow = overflow;
 
187
    }
 
188
    if (parseFloat(opacity) >= 0.0 && parseFloat(opacity) < 1.0) {
 
189
        element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';
 
190
        element.style.opacity = opacity;
 
191
    } else if (parseFloat(opacity) == 1.0) {
 
192
        element.style.filter = '';
 
193
        element.style.opacity = '';
 
194
    }
 
195
};
 
196
 
 
197
/** 
 
198
 * Function: createDiv
 
199
 * Creates a new div and optionally set some standard attributes.
 
200
 * Null may be passed to each parameter if you do not wish to
 
201
 * set a particular attribute.
 
202
 * Note - zIndex is NOT set on the resulting div.
 
203
 * 
 
204
 * Parameters:
 
205
 * id - {String} An identifier for this element.  If no id is
 
206
 *               passed an identifier will be created 
 
207
 *               automatically.
 
208
 * px - {<OpenLayers.Pixel>} The element left and top position. 
 
209
 * sz - {<OpenLayers.Size>} The element width and height.
 
210
 * imgURL - {String} A url pointing to an image to use as a 
 
211
 *                   background image.
 
212
 * position - {String} The style.position value. eg: absolute,
 
213
 *                     relative etc.
 
214
 * border - {String} The the style.border value. 
 
215
 *                   eg: 2px solid black
 
216
 * overflow - {String} The style.overflow value. Eg. hidden
 
217
 * opacity - {Float} Fractional value (0.0 - 1.0)
 
218
 * 
 
219
 * Returns: 
 
220
 * {DOMElement} A DOM Div created with the specified attributes.
 
221
 */
 
222
OpenLayers.Util.createDiv = function(id, px, sz, imgURL, position, 
 
223
                                     border, overflow, opacity) {
 
224
 
 
225
    var dom = document.createElement('div');
 
226
 
 
227
    if (imgURL) {
 
228
        dom.style.backgroundImage = 'url(' + imgURL + ')';
 
229
    }
 
230
 
 
231
    //set generic properties
 
232
    if (!id) {
 
233
        id = OpenLayers.Util.createUniqueID("OpenLayersDiv");
 
234
    }
 
235
    if (!position) {
 
236
        position = "absolute";
 
237
    }
 
238
    OpenLayers.Util.modifyDOMElement(dom, id, px, sz, position, 
 
239
                                     border, overflow, opacity);
 
240
 
 
241
    return dom;
 
242
};
 
243
 
 
244
/**
 
245
 * Function: createImage
 
246
 * Creates an img element with specific attribute values.
 
247
 *  
 
248
 * Parameters:
 
249
 * id - {String} The id field for the img.  If none assigned one will be
 
250
 *               automatically generated.
 
251
 * px - {<OpenLayers.Pixel>} The left and top positions.
 
252
 * sz - {<OpenLayers.Size>} The style.width and style.height values.
 
253
 * imgURL - {String} The url to use as the image source.
 
254
 * position - {String} The style.position value.
 
255
 * border - {String} The border to place around the image.
 
256
 * delayDisplay - {Boolean} If true waits until the image has been
 
257
 *                          loaded.
 
258
 * opacity - {Float} Fractional value (0.0 - 1.0)
 
259
 * 
 
260
 * Returns:
 
261
 * {DOMElement} A DOM Image created with the specified attributes.
 
262
 */
 
263
OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border,
 
264
                                       opacity, delayDisplay) {
 
265
 
 
266
    var image = document.createElement("img");
 
267
 
 
268
    //set generic properties
 
269
    if (!id) {
 
270
        id = OpenLayers.Util.createUniqueID("OpenLayersDiv");
 
271
    }
 
272
    if (!position) {
 
273
        position = "relative";
 
274
    }
 
275
    OpenLayers.Util.modifyDOMElement(image, id, px, sz, position, 
 
276
                                     border, null, opacity);
 
277
 
 
278
    if(delayDisplay) {
 
279
        image.style.display = "none";
 
280
        OpenLayers.Event.observe(image, "load", 
 
281
            OpenLayers.Function.bind(OpenLayers.Util.onImageLoad, image));
 
282
        OpenLayers.Event.observe(image, "error", 
 
283
            OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError, image));
 
284
        
 
285
    }
 
286
    
 
287
    //set special properties
 
288
    image.style.alt = id;
 
289
    image.galleryImg = "no";
 
290
    if (imgURL) {
 
291
        image.src = imgURL;
 
292
    }
 
293
 
 
294
 
 
295
        
 
296
    return image;
 
297
};
 
298
 
 
299
/**
 
300
 * Function: setOpacity
 
301
 * *Deprecated*.  This function has been deprecated. Instead, please use 
 
302
 *     <OpenLayers.Util.modifyDOMElement> 
 
303
 *     or 
 
304
 *     <OpenLayers.Util.modifyAlphaImageDiv>
 
305
 * 
 
306
 * Set the opacity of a DOM Element
 
307
 *     Note that for this function to work in IE, elements must "have layout"
 
308
 *     according to:
 
309
 *     http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/haslayout.asp
 
310
 *
 
311
 * Parameters:
 
312
 * element - {DOMElement} Set the opacity on this DOM element
 
313
 * opacity - {Float} Opacity value (0.0 - 1.0)
 
314
 */
 
315
OpenLayers.Util.setOpacity = function(element, opacity) {
 
316
    OpenLayers.Util.modifyDOMElement(element, null, null, null,
 
317
                                     null, null, null, opacity);
 
318
};
 
319
 
 
320
/**
 
321
 * Function: onImageLoad
 
322
 * Bound to image load events.  For all images created with <createImage> or
 
323
 *     <createAlphaImageDiv>, this function will be bound to the load event.
 
324
 */
 
325
OpenLayers.Util.onImageLoad = function() {
 
326
    // The complex check here is to solve issues described in #480.
 
327
    // Every time a map view changes, it increments the 'viewRequestID' 
 
328
    // property. As the requests for the images for the new map view are sent
 
329
    // out, they are tagged with this unique viewRequestID. 
 
330
    // 
 
331
    // If an image has no viewRequestID property set, we display it regardless, 
 
332
    // but if it does have a viewRequestID property, we check that it matches 
 
333
    // the viewRequestID set on the map.
 
334
    // 
 
335
    // If the viewRequestID on the map has changed, that means that the user
 
336
    // has changed the map view since this specific request was sent out, and
 
337
    // therefore this tile does not need to be displayed (so we do not execute
 
338
    // this code that turns its display on).
 
339
    //
 
340
    if (!this.viewRequestID ||
 
341
        (this.map && this.viewRequestID == this.map.viewRequestID)) { 
 
342
        this.style.backgroundColor = null;
 
343
        this.style.display = "";  
 
344
    }
 
345
};
 
346
 
 
347
/**
 
348
 * Property: onImageLoadErrorColor
 
349
 * {String} The color tiles with load errors will turn.
 
350
 *          Default is "pink"
 
351
 */
 
352
OpenLayers.Util.onImageLoadErrorColor = "pink";
 
353
 
 
354
/**
 
355
 * Property: IMAGE_RELOAD_ATTEMPTS
 
356
 * {Integer} How many times should we try to reload an image before giving up?
 
357
 *           Default is 0
 
358
 */
 
359
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 0;
 
360
 
 
361
/**
 
362
 * Function: onImageLoadError 
 
363
 */
 
364
OpenLayers.Util.onImageLoadError = function() {
 
365
    this._attempts = (this._attempts) ? (this._attempts + 1) : 1;
 
366
    if (this._attempts <= OpenLayers.IMAGE_RELOAD_ATTEMPTS) {
 
367
        var urls = this.urls;
 
368
        if (urls && urls instanceof Array && urls.length > 1){
 
369
            var src = this.src.toString();
 
370
            var current_url, k;
 
371
            for (k = 0; current_url = urls[k]; k++){
 
372
                if(src.indexOf(current_url) != -1){
 
373
                    break;
 
374
                }
 
375
            }
 
376
            var guess = Math.floor(urls.length * Math.random());
 
377
            var new_url = urls[guess];
 
378
            k = 0;
 
379
            while(new_url == current_url && k++ < 4){
 
380
                guess = Math.floor(urls.length * Math.random());
 
381
                new_url = urls[guess];
 
382
            }
 
383
            this.src = src.replace(current_url, new_url);
 
384
        } else {
 
385
            this.src = this.src;
 
386
        }
 
387
    } else {
 
388
        this.style.backgroundColor = OpenLayers.Util.onImageLoadErrorColor;
 
389
    }
 
390
    this.style.display = "";
 
391
};
 
392
 
 
393
/**
 
394
 * Function: alphaHack
 
395
 * Checks whether it's necessary (and possible) to use the png alpha
 
396
 * hack which allows alpha transparency for png images under Internet
 
397
 * Explorer.
 
398
 * 
 
399
 * Returns:
 
400
 * {Boolean} true if alpha has is necessary and possible, false otherwise.
 
401
 */
 
402
OpenLayers.Util.alphaHack = function() {
 
403
    var arVersion = navigator.appVersion.split("MSIE");
 
404
    var version = parseFloat(arVersion[1]);
 
405
    var filter = false;
 
406
    
 
407
    // IEs4Lin dies when trying to access document.body.filters, because 
 
408
    // the property is there, but requires a DLL that can't be provided. This
 
409
    // means that we need to wrap this in a try/catch so that this can
 
410
    // continue.
 
411
    
 
412
    try { 
 
413
        filter = !!(document.body.filters);
 
414
    } catch (e) {
 
415
    }    
 
416
    
 
417
    return ( filter &&
 
418
                      (version >= 5.5) && (version < 7) );
 
419
};
 
420
 
 
421
/** 
 
422
 * Function: modifyAlphaImageDiv
 
423
 * 
 
424
 * div - {DOMElement} Div containing Alpha-adjusted Image
 
425
 * id - {String}
 
426
 * px - {<OpenLayers.Pixel>}
 
427
 * sz - {<OpenLayers.Size>}
 
428
 * imgURL - {String}
 
429
 * position - {String}
 
430
 * border - {String}
 
431
 * sizing {String} 'crop', 'scale', or 'image'. Default is "scale"
 
432
 * opacity - {Float} Fractional value (0.0 - 1.0)
 
433
 */ 
 
434
OpenLayers.Util.modifyAlphaImageDiv = function(div, id, px, sz, imgURL, 
 
435
                                               position, border, sizing, 
 
436
                                               opacity) {
 
437
 
 
438
    OpenLayers.Util.modifyDOMElement(div, id, px, sz, position,
 
439
                                     null, null, opacity);
 
440
 
 
441
    var img = div.childNodes[0];
 
442
 
 
443
    if (imgURL) {
 
444
        img.src = imgURL;
 
445
    }
 
446
    OpenLayers.Util.modifyDOMElement(img, div.id + "_innerImage", null, sz, 
 
447
                                     "relative", border);
 
448
    
 
449
    if (OpenLayers.Util.alphaHack()) {
 
450
        if(div.style.display != "none") {
 
451
            div.style.display = "inline-block";
 
452
        }
 
453
        if (sizing == null) {
 
454
            sizing = "scale";
 
455
        }
 
456
        
 
457
        div.style.filter = "progid:DXImageTransform.Microsoft" +
 
458
                           ".AlphaImageLoader(src='" + img.src + "', " +
 
459
                           "sizingMethod='" + sizing + "')";
 
460
        if (parseFloat(div.style.opacity) >= 0.0 && 
 
461
            parseFloat(div.style.opacity) < 1.0) {
 
462
            div.style.filter += " alpha(opacity=" + div.style.opacity * 100 + ")";
 
463
        }
 
464
 
 
465
        img.style.filter = "alpha(opacity=0)";
 
466
    }
 
467
};
 
468
 
 
469
/** 
 
470
 * Function: createAlphaImageDiv
 
471
 * 
 
472
 * id - {String}
 
473
 * px - {<OpenLayers.Pixel>}
 
474
 * sz - {<OpenLayers.Size>}
 
475
 * imgURL - {String}
 
476
 * position - {String}
 
477
 * border - {String}
 
478
 * sizing {String} 'crop', 'scale', or 'image'. Default is "scale"
 
479
 * delayDisplay{Boolean}
 
480
 * 
 
481
 * Returns:
 
482
 * {DOMElement} A DOM Div created with a DOM Image inside it. If the hack is 
 
483
 *              needed for transparency in IE, it is added.
 
484
 */ 
 
485
OpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL, 
 
486
                                               position, border, sizing, 
 
487
                                               opacity, delayDisplay) {
 
488
    
 
489
    var div = OpenLayers.Util.createDiv();
 
490
    var img = OpenLayers.Util.createImage(null, null, null, null, null, null, 
 
491
                                          null, false);
 
492
    div.appendChild(img);
 
493
 
 
494
    if (delayDisplay) {
 
495
        img.style.display = "none";
 
496
        OpenLayers.Event.observe(img, "load",
 
497
            OpenLayers.Function.bind(OpenLayers.Util.onImageLoad, div));
 
498
        OpenLayers.Event.observe(img, "error",
 
499
            OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError, div));
 
500
    }
 
501
 
 
502
    OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL, position, 
 
503
                                        border, sizing, opacity);
 
504
    
 
505
    return div;
 
506
};
 
507
 
 
508
 
 
509
/** 
 
510
 * Function: upperCaseObject
 
511
 * Creates a new hashtable and copies over all the keys from the 
 
512
 *     passed-in object, but storing them under an uppercased
 
513
 *     version of the key at which they were stored.
 
514
 * 
 
515
 * Parameters: 
 
516
 * object - {Object}
 
517
 * 
 
518
 * Returns: 
 
519
 * {Object} A new Object with all the same keys but uppercased
 
520
 */
 
521
OpenLayers.Util.upperCaseObject = function (object) {
 
522
    var uObject = {};
 
523
    for (var key in object) {
 
524
        uObject[key.toUpperCase()] = object[key];
 
525
    }
 
526
    return uObject;
 
527
};
 
528
 
 
529
/** 
 
530
 * Function: applyDefaults
 
531
 * Takes an object and copies any properties that don't exist from
 
532
 *     another properties, by analogy with OpenLayers.Util.extend() from
 
533
 *     Prototype.js.
 
534
 * 
 
535
 * Parameters:
 
536
 * to - {Object} The destination object.
 
537
 * from - {Object} The source object.  Any properties of this object that
 
538
 *     are undefined in the to object will be set on the to object.
 
539
 *
 
540
 * Returns:
 
541
 * {Object} A reference to the to object.  Note that the to argument is modified
 
542
 *     in place and returned by this function.
 
543
 */
 
544
OpenLayers.Util.applyDefaults = function (to, from) {
 
545
    to = to || {};
 
546
    /*
 
547
     * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative
 
548
     * prototype object" when calling hawOwnProperty if the source object is an
 
549
     * instance of window.Event.
 
550
     */
 
551
    var fromIsEvt = typeof window.Event == "function"
 
552
                    && from instanceof window.Event;
 
553
 
 
554
    for (var key in from) {
 
555
        if (to[key] === undefined ||
 
556
            (!fromIsEvt && from.hasOwnProperty
 
557
             && from.hasOwnProperty(key) && !to.hasOwnProperty(key))) {
 
558
            to[key] = from[key];
 
559
        }
 
560
    }
 
561
    /**
 
562
     * IE doesn't include the toString property when iterating over an object's
 
563
     * properties with the for(property in object) syntax.  Explicitly check if
 
564
     * the source has its own toString property.
 
565
     */
 
566
    if(!fromIsEvt && from && from.hasOwnProperty
 
567
       && from.hasOwnProperty('toString') && !to.hasOwnProperty('toString')) {
 
568
        to.toString = from.toString;
 
569
    }
 
570
    
 
571
    return to;
 
572
};
 
573
 
 
574
/**
 
575
 * Function: getParameterString
 
576
 * 
 
577
 * Parameters:
 
578
 * params - {Object}
 
579
 * 
 
580
 * Returns:
 
581
 * {String} A concatenation of the properties of an object in 
 
582
 *          http parameter notation. 
 
583
 *          (ex. <i>"key1=value1&key2=value2&key3=value3"</i>)
 
584
 *          If a parameter is actually a list, that parameter will then
 
585
 *          be set to a comma-seperated list of values (foo,bar) instead
 
586
 *          of being URL escaped (foo%3Abar). 
 
587
 */
 
588
OpenLayers.Util.getParameterString = function(params) {
 
589
    var paramsArray = [];
 
590
    
 
591
    for (var key in params) {
 
592
      var value = params[key];
 
593
      if ((value != null) && (typeof value != 'function')) {
 
594
        var encodedValue;
 
595
        if (typeof value == 'object' && value.constructor == Array) {
 
596
          /* value is an array; encode items and separate with "," */
 
597
          var encodedItemArray = [];
 
598
          for (var itemIndex=0, len=value.length; itemIndex<len; itemIndex++) {
 
599
            encodedItemArray.push(encodeURIComponent(value[itemIndex]));
 
600
          }
 
601
          encodedValue = encodedItemArray.join(",");
 
602
        }
 
603
        else {
 
604
          /* value is a string; simply encode */
 
605
          encodedValue = encodeURIComponent(value);
 
606
        }
 
607
        paramsArray.push(encodeURIComponent(key) + "=" + encodedValue);
 
608
      }
 
609
    }
 
610
    
 
611
    return paramsArray.join("&");
 
612
};
 
613
 
 
614
/**
 
615
 * Property: ImgPath
 
616
 * {String} Default is ''.
 
617
 */
 
618
OpenLayers.ImgPath = '';
 
619
 
 
620
/** 
 
621
 * Function: getImagesLocation
 
622
 * 
 
623
 * Returns:
 
624
 * {String} The fully formatted image location string
 
625
 */
 
626
OpenLayers.Util.getImagesLocation = function() {
 
627
    return OpenLayers.ImgPath || (OpenLayers._getScriptLocation() + "img/");
 
628
};
 
629
 
 
630
 
 
631
/** 
 
632
 * Function: Try
 
633
 * Execute functions until one of them doesn't throw an error. 
 
634
 *     Capitalized because "try" is a reserved word in JavaScript.
 
635
 *     Taken directly from OpenLayers.Util.Try()
 
636
 * 
 
637
 * Parameters:
 
638
 * [*] - {Function} Any number of parameters may be passed to Try()
 
639
 *    It will attempt to execute each of them until one of them 
 
640
 *    successfully executes. 
 
641
 *    If none executes successfully, returns null.
 
642
 * 
 
643
 * Returns:
 
644
 * {*} The value returned by the first successfully executed function.
 
645
 */
 
646
OpenLayers.Util.Try = function() {
 
647
    var returnValue = null;
 
648
 
 
649
    for (var i=0, len=arguments.length; i<len; i++) {
 
650
      var lambda = arguments[i];
 
651
      try {
 
652
        returnValue = lambda();
 
653
        break;
 
654
      } catch (e) {}
 
655
    }
 
656
 
 
657
    return returnValue;
 
658
};
 
659
 
 
660
 
 
661
/** 
 
662
 * Function: getNodes
 
663
 * 
 
664
 * These could/should be made namespace aware?
 
665
 * 
 
666
 * Parameters:
 
667
 * p - {}
 
668
 * tagName - {String}
 
669
 * 
 
670
 * Returns:
 
671
 * {Array}
 
672
 */
 
673
OpenLayers.Util.getNodes=function(p, tagName) {
 
674
    var nodes = OpenLayers.Util.Try(
 
675
        function () {
 
676
            return OpenLayers.Util._getNodes(p.documentElement.childNodes,
 
677
                                            tagName);
 
678
        },
 
679
        function () {
 
680
            return OpenLayers.Util._getNodes(p.childNodes, tagName);
 
681
        }
 
682
    );
 
683
    return nodes;
 
684
};
 
685
 
 
686
/**
 
687
 * Function: _getNodes
 
688
 * 
 
689
 * Parameters:
 
690
 * nodes - {Array}
 
691
 * tagName - {String}
 
692
 * 
 
693
 * Returns:
 
694
 * {Array}
 
695
 */
 
696
OpenLayers.Util._getNodes=function(nodes, tagName) {
 
697
    var retArray = [];
 
698
    for (var i=0, len=nodes.length; i<len; i++) {
 
699
        if (nodes[i].nodeName==tagName) {
 
700
            retArray.push(nodes[i]);
 
701
        }
 
702
    }
 
703
 
 
704
    return retArray;
 
705
};
 
706
 
 
707
 
 
708
 
 
709
/**
 
710
 * Function: getTagText
 
711
 * 
 
712
 * Parameters:
 
713
 * parent - {}
 
714
 * item - {String}
 
715
 * index - {Integer}
 
716
 * 
 
717
 * Returns:
 
718
 * {String}
 
719
 */
 
720
OpenLayers.Util.getTagText = function (parent, item, index) {
 
721
    var result = OpenLayers.Util.getNodes(parent, item);
 
722
    if (result && (result.length > 0))
 
723
    {
 
724
        if (!index) {
 
725
            index=0;
 
726
        }
 
727
        if (result[index].childNodes.length > 1) {
 
728
            return result.childNodes[1].nodeValue; 
 
729
        }
 
730
        else if (result[index].childNodes.length == 1) {
 
731
            return result[index].firstChild.nodeValue; 
 
732
        }
 
733
    } else { 
 
734
        return ""; 
 
735
    }
 
736
};
 
737
 
 
738
/**
 
739
 * Function: getXmlNodeValue
 
740
 * 
 
741
 * Parameters:
 
742
 * node - {XMLNode}
 
743
 * 
 
744
 * Returns:
 
745
 * {String} The text value of the given node, without breaking in firefox or IE
 
746
 */
 
747
OpenLayers.Util.getXmlNodeValue = function(node) {
 
748
    var val = null;
 
749
    OpenLayers.Util.Try( 
 
750
        function() {
 
751
            val = node.text;
 
752
            if (!val) {
 
753
                val = node.textContent;
 
754
            }
 
755
            if (!val) {
 
756
                val = node.firstChild.nodeValue;
 
757
            }
 
758
        }, 
 
759
        function() {
 
760
            val = node.textContent;
 
761
        }); 
 
762
    return val;
 
763
};
 
764
 
 
765
/** 
 
766
 * Function: mouseLeft
 
767
 * 
 
768
 * Parameters:
 
769
 * evt - {Event}
 
770
 * div - {HTMLDivElement}
 
771
 * 
 
772
 * Returns:
 
773
 * {Boolean}
 
774
 */
 
775
OpenLayers.Util.mouseLeft = function (evt, div) {
 
776
    // start with the element to which the mouse has moved
 
777
    var target = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;
 
778
    // walk up the DOM tree.
 
779
    while (target != div && target != null) {
 
780
        target = target.parentNode;
 
781
    }
 
782
    // if the target we stop at isn't the div, then we've left the div.
 
783
    return (target != div);
 
784
};
 
785
 
 
786
/**
 
787
 * Function: rad
 
788
 * 
 
789
 * Parameters:
 
790
 * x - {Float}
 
791
 * 
 
792
 * Returns:
 
793
 * {Float}
 
794
 */
 
795
OpenLayers.Util.rad = function(x) {return x*Math.PI/180;};
 
796
 
 
797
/**
 
798
 * Function: distVincenty
 
799
 * Given two objects representing points with geographic coordinates, this
 
800
 *     calculates the distance between those points on the surface of an
 
801
 *     ellipsoid.
 
802
 * 
 
803
 * Parameters:
 
804
 * p1 - {<OpenLayers.LonLat>} (or any object with both .lat, .lon properties)
 
805
 * p2 - {<OpenLayers.LonLat>} (or any object with both .lat, .lon properties)
 
806
 * 
 
807
 * Returns:
 
808
 * {Float} The distance (in km) between the two input points as measured on an
 
809
 *     ellipsoid.  Note that the input point objects must be in geographic
 
810
 *     coordinates (decimal degrees) and the return distance is in kilometers.
 
811
 */
 
812
OpenLayers.Util.distVincenty=function(p1, p2) {
 
813
    var a = 6378137, b = 6356752.3142,  f = 1/298.257223563;
 
814
    var L = OpenLayers.Util.rad(p2.lon - p1.lon);
 
815
    var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat)));
 
816
    var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat)));
 
817
    var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
 
818
    var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
 
819
    var lambda = L, lambdaP = 2*Math.PI;
 
820
    var iterLimit = 20;
 
821
    while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {
 
822
        var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
 
823
        var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
 
824
        (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
 
825
        if (sinSigma==0) {
 
826
            return 0;  // co-incident points
 
827
        }
 
828
        var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
 
829
        var sigma = Math.atan2(sinSigma, cosSigma);
 
830
        var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);
 
831
        var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);
 
832
        var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
 
833
        var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
 
834
        lambdaP = lambda;
 
835
        lambda = L + (1-C) * f * Math.sin(alpha) *
 
836
        (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
 
837
    }
 
838
    if (iterLimit==0) {
 
839
        return NaN;  // formula failed to converge
 
840
    }
 
841
    var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
 
842
    var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
 
843
    var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
 
844
    var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
 
845
        B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
 
846
    var s = b*A*(sigma-deltaSigma);
 
847
    var d = s.toFixed(3)/1000; // round to 1mm precision
 
848
    return d;
 
849
};
 
850
 
 
851
/**
 
852
 * Function: getParameters
 
853
 * Parse the parameters from a URL or from the current page itself into a 
 
854
 *     JavaScript Object. Note that parameter values with commas are separated
 
855
 *     out into an Array.
 
856
 * 
 
857
 * Parameters:
 
858
 * url - {String} Optional url used to extract the query string.
 
859
 *                If null, query string is taken from page location.
 
860
 * 
 
861
 * Returns:
 
862
 * {Object} An object of key/value pairs from the query string.
 
863
 */
 
864
OpenLayers.Util.getParameters = function(url) {
 
865
    // if no url specified, take it from the location bar
 
866
    url = url || window.location.href;
 
867
 
 
868
    //parse out parameters portion of url string
 
869
    var paramsString = "";
 
870
    if (OpenLayers.String.contains(url, '?')) {
 
871
        var start = url.indexOf('?') + 1;
 
872
        var end = OpenLayers.String.contains(url, "#") ?
 
873
                    url.indexOf('#') : url.length;
 
874
        paramsString = url.substring(start, end);
 
875
    }
 
876
        
 
877
    var parameters = {};
 
878
    var pairs = paramsString.split(/[&;]/);
 
879
    for(var i=0, len=pairs.length; i<len; ++i) {
 
880
        var keyValue = pairs[i].split('=');
 
881
        if (keyValue[0]) {
 
882
            var key = decodeURIComponent(keyValue[0]);
 
883
            var value = keyValue[1] || ''; //empty string if no value
 
884
 
 
885
            //decode individual values
 
886
            value = value.split(",");
 
887
            for(var j=0, jlen=value.length; j<jlen; j++) {
 
888
                value[j] = decodeURIComponent(value[j]);
 
889
            }
 
890
 
 
891
            //if there's only one value, do not return as array                    
 
892
            if (value.length == 1) {
 
893
                value = value[0];
 
894
            }                
 
895
            
 
896
            parameters[key] = value;
 
897
         }
 
898
     }
 
899
    return parameters;
 
900
};
 
901
 
 
902
/**
 
903
 * Function: getArgs
 
904
 * *Deprecated*.  Will be removed in 3.0.  Please use instead
 
905
 *     <OpenLayers.Util.getParameters>
 
906
 * 
 
907
 * Parameters:
 
908
 * url - {String} Optional url used to extract the query string.
 
909
 *                If null, query string is taken from page location.
 
910
 * 
 
911
 * Returns:
 
912
 * {Object} An object of key/value pairs from the query string.
 
913
 */
 
914
OpenLayers.Util.getArgs = function(url) {
 
915
    OpenLayers.Console.warn(
 
916
        OpenLayers.i18n(
 
917
            "methodDeprecated", {'newMethod': 'OpenLayers.Util.getParameters'}
 
918
        )
 
919
    );
 
920
    return OpenLayers.Util.getParameters(url);
 
921
};
 
922
 
 
923
/**
 
924
 * Property: lastSeqID
 
925
 * {Integer} The ever-incrementing count variable.
 
926
 *           Used for generating unique ids.
 
927
 */
 
928
OpenLayers.Util.lastSeqID = 0;
 
929
 
 
930
/**
 
931
 * Function: createUniqueID
 
932
 * Create a unique identifier for this session.  Each time this function
 
933
 *     is called, a counter is incremented.  The return will be the optional
 
934
 *     prefix (defaults to "id_") appended with the counter value.
 
935
 * 
 
936
 * Parameters:
 
937
 * prefix {String} Optionsal string to prefix unique id. Default is "id_".
 
938
 * 
 
939
 * Returns:
 
940
 * {String} A unique id string, built on the passed in prefix.
 
941
 */
 
942
OpenLayers.Util.createUniqueID = function(prefix) {
 
943
    if (prefix == null) {
 
944
        prefix = "id_";
 
945
    }
 
946
    OpenLayers.Util.lastSeqID += 1; 
 
947
    return prefix + OpenLayers.Util.lastSeqID;        
 
948
};
 
949
 
 
950
/**
 
951
 * Constant: INCHES_PER_UNIT
 
952
 * {Object} Constant inches per unit -- borrowed from MapServer mapscale.c
 
953
 * derivation of nautical miles from http://en.wikipedia.org/wiki/Nautical_mile
 
954
 */
 
955
OpenLayers.INCHES_PER_UNIT = { 
 
956
    'inches': 1.0,
 
957
    'ft': 12.0,
 
958
    'mi': 63360.0,
 
959
    'm': 39.3701,
 
960
    'km': 39370.1,
 
961
    'dd': 4374754,
 
962
    'yd': 36
 
963
};
 
964
OpenLayers.INCHES_PER_UNIT["in"]= OpenLayers.INCHES_PER_UNIT.inches;
 
965
OpenLayers.INCHES_PER_UNIT["degrees"] = OpenLayers.INCHES_PER_UNIT.dd;
 
966
OpenLayers.INCHES_PER_UNIT["nmi"] = 1852 * OpenLayers.INCHES_PER_UNIT.m;
 
967
 
 
968
/** 
 
969
 * Constant: DOTS_PER_INCH
 
970
 * {Integer} 72 (A sensible default)
 
971
 */
 
972
OpenLayers.DOTS_PER_INCH = 72;
 
973
 
 
974
/**
 
975
 * Function: normalzeScale
 
976
 * 
 
977
 * Parameters:
 
978
 * scale - {float}
 
979
 * 
 
980
 * Returns:
 
981
 * {Float} A normalized scale value, in 1 / X format. 
 
982
 *         This means that if a value less than one ( already 1/x) is passed
 
983
 *         in, it just returns scale directly. Otherwise, it returns 
 
984
 *         1 / scale
 
985
 */
 
986
OpenLayers.Util.normalizeScale = function (scale) {
 
987
    var normScale = (scale > 1.0) ? (1.0 / scale) 
 
988
                                  : scale;
 
989
    return normScale;
 
990
};
 
991
 
 
992
/**
 
993
 * Function: getResolutionFromScale
 
994
 * 
 
995
 * Parameters:
 
996
 * scale - {Float}
 
997
 * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable.
 
998
 *                  Default is degrees
 
999
 * 
 
1000
 * Returns:
 
1001
 * {Float} The corresponding resolution given passed-in scale and unit 
 
1002
 *         parameters.
 
1003
 */
 
1004
OpenLayers.Util.getResolutionFromScale = function (scale, units) {
 
1005
 
 
1006
    if (units == null) {
 
1007
        units = "degrees";
 
1008
    }
 
1009
 
 
1010
    var normScale = OpenLayers.Util.normalizeScale(scale);
 
1011
 
 
1012
    var resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units]
 
1013
                                    * OpenLayers.DOTS_PER_INCH);
 
1014
    return resolution;
 
1015
};
 
1016
 
 
1017
/**
 
1018
 * Function: getScaleFromResolution
 
1019
 * 
 
1020
 * Parameters:
 
1021
 * resolution - {Float}
 
1022
 * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable.
 
1023
 *                  Default is degrees
 
1024
 * 
 
1025
 * Returns:
 
1026
 * {Float} The corresponding scale given passed-in resolution and unit 
 
1027
 *         parameters.
 
1028
 */
 
1029
OpenLayers.Util.getScaleFromResolution = function (resolution, units) {
 
1030
 
 
1031
    if (units == null) {
 
1032
        units = "degrees";
 
1033
    }
 
1034
 
 
1035
    var scale = resolution * OpenLayers.INCHES_PER_UNIT[units] *
 
1036
                    OpenLayers.DOTS_PER_INCH;
 
1037
    return scale;
 
1038
};
 
1039
 
 
1040
/**
 
1041
 * Function: safeStopPropagation
 
1042
 * *Deprecated*. This function has been deprecated. Please use directly 
 
1043
 *     <OpenLayers.Event.stop> passing 'true' as the 2nd 
 
1044
 *     argument (preventDefault)
 
1045
 * 
 
1046
 * Safely stop the propagation of an event *without* preventing
 
1047
 *   the default browser action from occurring.
 
1048
 * 
 
1049
 * Parameter:
 
1050
 * evt - {Event}
 
1051
 */
 
1052
OpenLayers.Util.safeStopPropagation = function(evt) {
 
1053
    OpenLayers.Event.stop(evt, true);
 
1054
};
 
1055
 
 
1056
/**
 
1057
 * Function: pagePositon
 
1058
 * Calculates the position of an element on the page. 
 
1059
 *
 
1060
 * Parameters:
 
1061
 * forElement - {DOMElement}
 
1062
 * 
 
1063
 * Returns:
 
1064
 * {Array} two item array, L value then T value.
 
1065
 */
 
1066
OpenLayers.Util.pagePosition = function(forElement) {
 
1067
    var valueT = 0, valueL = 0;
 
1068
 
 
1069
    var element = forElement;
 
1070
    var child = forElement;
 
1071
    while(element) {
 
1072
 
 
1073
        if(element == document.body) {
 
1074
            if(OpenLayers.Element.getStyle(child, 'position') == 'absolute') {
 
1075
                break;
 
1076
            }
 
1077
        }
 
1078
        
 
1079
        valueT += element.offsetTop  || 0;
 
1080
        valueL += element.offsetLeft || 0;
 
1081
 
 
1082
        child = element;
 
1083
        try {
 
1084
            // wrapping this in a try/catch because IE chokes on the offsetParent
 
1085
            element = element.offsetParent;
 
1086
        } catch(e) {
 
1087
            OpenLayers.Console.error(OpenLayers.i18n(
 
1088
                                  "pagePositionFailed",{'elemId':element.id}));
 
1089
            break;
 
1090
        }
 
1091
    }
 
1092
 
 
1093
    element = forElement;
 
1094
    while(element) {
 
1095
        valueT -= element.scrollTop  || 0;
 
1096
        valueL -= element.scrollLeft || 0;
 
1097
        element = element.parentNode;
 
1098
    }
 
1099
    
 
1100
    return [valueL, valueT];
 
1101
};
 
1102
 
 
1103
 
 
1104
/** 
 
1105
 * Function: isEquivalentUrl
 
1106
 * Test two URLs for equivalence. 
 
1107
 * 
 
1108
 * Setting 'ignoreCase' allows for case-independent comparison.
 
1109
 * 
 
1110
 * Comparison is based on: 
 
1111
 *  - Protocol
 
1112
 *  - Host (evaluated without the port)
 
1113
 *  - Port (set 'ignorePort80' to ignore "80" values)
 
1114
 *  - Hash ( set 'ignoreHash' to disable)
 
1115
 *  - Pathname (for relative <-> absolute comparison) 
 
1116
 *  - Arguments (so they can be out of order)
 
1117
 *  
 
1118
 * Parameters:
 
1119
 * url1 - {String}
 
1120
 * url2 - {String}
 
1121
 * options - {Object} Allows for customization of comparison:
 
1122
 *                    'ignoreCase' - Default is True
 
1123
 *                    'ignorePort80' - Default is True
 
1124
 *                    'ignoreHash' - Default is True
 
1125
 *
 
1126
 * Returns:
 
1127
 * {Boolean} Whether or not the two URLs are equivalent
 
1128
 */
 
1129
OpenLayers.Util.isEquivalentUrl = function(url1, url2, options) {
 
1130
    options = options || {};
 
1131
 
 
1132
    OpenLayers.Util.applyDefaults(options, {
 
1133
        ignoreCase: true,
 
1134
        ignorePort80: true,
 
1135
        ignoreHash: true
 
1136
    });
 
1137
 
 
1138
    var urlObj1 = OpenLayers.Util.createUrlObject(url1, options);
 
1139
    var urlObj2 = OpenLayers.Util.createUrlObject(url2, options);
 
1140
 
 
1141
    //compare all keys (host, port, etc)
 
1142
    for(var key in urlObj1) {
 
1143
        if (options.test) {
 
1144
            OpenLayers.Console.userError(key + "\n1:" + urlObj1[key] + "\n2:" + urlObj2[key]);
 
1145
        }
 
1146
        var val1 = urlObj1[key];
 
1147
        var val2 = urlObj2[key];
 
1148
        
 
1149
        switch(key) {
 
1150
            case "args":
 
1151
                //do nothing, they'll be treated below
 
1152
                break;
 
1153
            case "host":
 
1154
            case "port":
 
1155
            case "protocol":
 
1156
                if ((val1 == "") || (val2 == "")) {
 
1157
                    //these will be blank for relative urls, so no need to 
 
1158
                    // compare them here -- call break. 
 
1159
                    // 
 
1160
                    break;
 
1161
                } 
 
1162
                // otherwise continue with default compare
 
1163
                //
 
1164
            default: 
 
1165
                if ( (key != "args") && (urlObj1[key] != urlObj2[key]) ) {
 
1166
                    return false;
 
1167
                }
 
1168
                break;
 
1169
        }
 
1170
        
 
1171
    }
 
1172
 
 
1173
    // compare search args - irrespective of order
 
1174
    for(var key in urlObj1.args) {
 
1175
        if(urlObj1.args[key] != urlObj2.args[key]) {
 
1176
            return false;
 
1177
        }
 
1178
        delete urlObj2.args[key];
 
1179
    }
 
1180
    // urlObj2 shouldn't have any args left
 
1181
    for(var key in urlObj2.args) {
 
1182
        return false;
 
1183
    }
 
1184
    
 
1185
    return true;
 
1186
};
 
1187
 
 
1188
/**
 
1189
 * Function: createUrlObject
 
1190
 * 
 
1191
 * Parameters:
 
1192
 * url - {String}
 
1193
 * options - {Object} A hash of options.  Can be one of:
 
1194
 *            ignoreCase: lowercase url,
 
1195
 *            ignorePort80: don't include explicit port if port is 80,
 
1196
 *            ignoreHash: Don't include part of url after the hash (#).
 
1197
 * 
 
1198
 * Returns:
 
1199
 * {Object} An object with separate url, a, port, host, and args parsed out 
 
1200
 *          and ready for comparison
 
1201
 */
 
1202
OpenLayers.Util.createUrlObject = function(url, options) {
 
1203
    options = options || {};
 
1204
 
 
1205
    var urlObject = {};
 
1206
  
 
1207
    if (options.ignoreCase) {
 
1208
        url = url.toLowerCase(); 
 
1209
    }
 
1210
 
 
1211
    var a = document.createElement('a');
 
1212
    a.href = url;
 
1213
    
 
1214
  //host (without port)
 
1215
    urlObject.host = a.host;
 
1216
    var port = a.port;
 
1217
    if (port.length <= 0) {
 
1218
        var newHostLength = urlObject.host.length - (port.length);
 
1219
        urlObject.host = urlObject.host.substring(0, newHostLength); 
 
1220
    }
 
1221
 
 
1222
  //protocol
 
1223
    urlObject.protocol = a.protocol;  
 
1224
 
 
1225
  //port
 
1226
    urlObject.port = ((port == "80") && (options.ignorePort80)) ? "" : port;
 
1227
                                                                     
 
1228
  //hash
 
1229
    urlObject.hash = (options.ignoreHash) ? "" : a.hash;  
 
1230
    
 
1231
  //args
 
1232
    var queryString = a.search;
 
1233
    if (!queryString) {
 
1234
        var qMark = url.indexOf("?");
 
1235
        queryString = (qMark != -1) ? url.substr(qMark) : "";
 
1236
    }
 
1237
    urlObject.args = OpenLayers.Util.getParameters(queryString);
 
1238
 
 
1239
 
 
1240
  //pathname (this part allows for relative <-> absolute comparison)
 
1241
    if ( ((urlObject.protocol == "file:") && (url.indexOf("file:") != -1)) || 
 
1242
         ((urlObject.protocol != "file:") && (urlObject.host != "")) ) {
 
1243
 
 
1244
        urlObject.pathname = a.pathname;  
 
1245
 
 
1246
        //Test to see if the pathname includes the arguments (Opera)
 
1247
        var qIndex = urlObject.pathname.indexOf("?");
 
1248
        if (qIndex != -1) {
 
1249
            urlObject.pathname = urlObject.pathname.substring(0, qIndex);
 
1250
        }
 
1251
 
 
1252
    } else {
 
1253
        var relStr = OpenLayers.Util.removeTail(url);
 
1254
 
 
1255
        var backs = 0;
 
1256
        do {
 
1257
            var index = relStr.indexOf("../");
 
1258
 
 
1259
            if (index == 0) {
 
1260
                backs++;
 
1261
                relStr = relStr.substr(3);
 
1262
            } else if (index >= 0) {
 
1263
                var prevChunk = relStr.substr(0,index - 1);
 
1264
                
 
1265
                var slash = prevChunk.indexOf("/");
 
1266
                prevChunk = (slash != -1) ? prevChunk.substr(0, slash +1)
 
1267
                                          : "";
 
1268
                
 
1269
                var postChunk = relStr.substr(index + 3);                
 
1270
                relStr = prevChunk + postChunk;
 
1271
            }
 
1272
        } while(index != -1);
 
1273
 
 
1274
        var windowAnchor = document.createElement("a");
 
1275
        var windowUrl = window.location.href;
 
1276
        if (options.ignoreCase) {
 
1277
            windowUrl = windowUrl.toLowerCase();
 
1278
        }
 
1279
        windowAnchor.href = windowUrl;
 
1280
 
 
1281
      //set protocol of window
 
1282
        urlObject.protocol = windowAnchor.protocol;
 
1283
 
 
1284
        var splitter = (windowAnchor.pathname.indexOf("/") != -1) ? "/" : "\\";
 
1285
        var dirs = windowAnchor.pathname.split(splitter);
 
1286
        dirs.pop(); //remove filename
 
1287
        while ((backs > 0) && (dirs.length > 0)) {
 
1288
            dirs.pop();
 
1289
            backs--;
 
1290
        }
 
1291
        relStr = dirs.join("/") + "/"+ relStr;
 
1292
        urlObject.pathname = relStr;
 
1293
    }
 
1294
    
 
1295
    if ((urlObject.protocol == "file:") || (urlObject.protocol == "")) {
 
1296
        urlObject.host = "localhost";
 
1297
    }
 
1298
 
 
1299
    return urlObject; 
 
1300
};
 
1301
 
 
1302
/**
 
1303
 * Function: removeTail
 
1304
 * Takes a url and removes everything after the ? and #
 
1305
 * 
 
1306
 * Parameters:
 
1307
 * url - {String} The url to process
 
1308
 * 
 
1309
 * Returns:
 
1310
 * {String} The string with all queryString and Hash removed
 
1311
 */
 
1312
OpenLayers.Util.removeTail = function(url) {
 
1313
    var head = null;
 
1314
    
 
1315
    var qMark = url.indexOf("?");
 
1316
    var hashMark = url.indexOf("#");
 
1317
 
 
1318
    if (qMark == -1) {
 
1319
        head = (hashMark != -1) ? url.substr(0,hashMark) : url;
 
1320
    } else {
 
1321
        head = (hashMark != -1) ? url.substr(0,Math.min(qMark, hashMark)) 
 
1322
                                  : url.substr(0, qMark);
 
1323
    }
 
1324
    return head;
 
1325
};
 
1326
 
 
1327
 
 
1328
/**
 
1329
 * Function: getBrowserName
 
1330
 * 
 
1331
 * Returns:
 
1332
 * {String} A string which specifies which is the current 
 
1333
 *          browser in which we are running. 
 
1334
 * 
 
1335
 *          Currently-supported browser detection and codes:
 
1336
 *           * 'opera' -- Opera
 
1337
 *           * 'msie'  -- Internet Explorer
 
1338
 *           * 'safari' -- Safari
 
1339
 *           * 'firefox' -- FireFox
 
1340
 *           * 'mozilla' -- Mozilla
 
1341
 * 
 
1342
 *          If we are unable to property identify the browser, we 
 
1343
 *           return an empty string.
 
1344
 */
 
1345
OpenLayers.Util.getBrowserName = function() {
 
1346
    var browserName = "";
 
1347
    
 
1348
    var ua = navigator.userAgent.toLowerCase();
 
1349
    if ( ua.indexOf( "opera" ) != -1 ) {
 
1350
        browserName = "opera";
 
1351
    } else if ( ua.indexOf( "msie" ) != -1 ) {
 
1352
        browserName = "msie";
 
1353
    } else if ( ua.indexOf( "safari" ) != -1 ) {
 
1354
        browserName = "safari";
 
1355
    } else if ( ua.indexOf( "mozilla" ) != -1 ) {
 
1356
        if ( ua.indexOf( "firefox" ) != -1 ) {
 
1357
            browserName = "firefox";
 
1358
        } else {
 
1359
            browserName = "mozilla";
 
1360
        }
 
1361
    }
 
1362
    
 
1363
    return browserName;
 
1364
};
 
1365
 
 
1366
 
 
1367
 
 
1368
    
 
1369
/**
 
1370
 * Method: getRenderedDimensions
 
1371
 * Renders the contentHTML offscreen to determine actual dimensions for
 
1372
 *     popup sizing. As we need layout to determine dimensions the content
 
1373
 *     is rendered -9999px to the left and absolute to ensure the 
 
1374
 *     scrollbars do not flicker
 
1375
 *     
 
1376
 * Parameters:
 
1377
 * contentHTML
 
1378
 * size - {<OpenLayers.Size>} If either the 'w' or 'h' properties is 
 
1379
 *     specified, we fix that dimension of the div to be measured. This is 
 
1380
 *     useful in the case where we have a limit in one dimension and must 
 
1381
 *     therefore meaure the flow in the other dimension.
 
1382
 * options - {Object}
 
1383
 *     displayClass - {String} Optional parameter.  A CSS class name(s) string
 
1384
 *         to provide the CSS context of the rendered content.
 
1385
 * 
 
1386
 * Returns:
 
1387
 * {OpenLayers.Size}
 
1388
 */
 
1389
OpenLayers.Util.getRenderedDimensions = function(contentHTML, size, options) {
 
1390
    
 
1391
    var w, h;
 
1392
    
 
1393
    // create temp container div with restricted size
 
1394
    var container = document.createElement("div");
 
1395
    container.style.overflow= "";
 
1396
    container.style.position = "absolute";
 
1397
    container.style.left = "-9999px";
 
1398
        
 
1399
    //fix a dimension, if specified.
 
1400
    if (size) {
 
1401
        if (size.w) {
 
1402
            w = size.w;
 
1403
            container.style.width = w + "px";
 
1404
        } else if (size.h) {
 
1405
            h = size.h;
 
1406
            container.style.height = h + "px";
 
1407
        }
 
1408
    }
 
1409
 
 
1410
    //add css classes, if specified
 
1411
    if (options && options.displayClass) {
 
1412
        container.className = options.displayClass;
 
1413
    }
 
1414
    
 
1415
    // create temp content div and assign content
 
1416
    var content = document.createElement("div");
 
1417
    content.innerHTML = contentHTML;
 
1418
    
 
1419
    // add content to restricted container 
 
1420
    container.appendChild(content);
 
1421
    
 
1422
    // append container to body for rendering
 
1423
    document.body.appendChild(container);
 
1424
    
 
1425
    // calculate scroll width of content and add corners and shadow width
 
1426
    if (!w) {
 
1427
        w = parseInt(content.scrollWidth);
 
1428
    
 
1429
        // update container width to allow height to adjust
 
1430
        container.style.width = w + "px";
 
1431
    }        
 
1432
    // capture height and add shadow and corner image widths
 
1433
    if (!h) {
 
1434
        h = parseInt(content.scrollHeight);
 
1435
    }
 
1436
 
 
1437
    // remove elements
 
1438
    container.removeChild(content);
 
1439
    document.body.removeChild(container);
 
1440
    
 
1441
    return new OpenLayers.Size(w, h);
 
1442
};
 
1443
 
 
1444
/**
 
1445
 * APIFunction: getScrollbarWidth
 
1446
 * This function has been modified by the OpenLayers from the original version,
 
1447
 *     written by Matthew Eernisse and released under the Apache 2 
 
1448
 *     license here:
 
1449
 * 
 
1450
 *     http://www.fleegix.org/articles/2006/05/30/getting-the-scrollbar-width-in-pixels
 
1451
 * 
 
1452
 *     It has been modified simply to cache its value, since it is physically 
 
1453
 *     impossible that this code could ever run in more than one browser at 
 
1454
 *     once. 
 
1455
 * 
 
1456
 * Returns:
 
1457
 * {Integer}
 
1458
 */
 
1459
OpenLayers.Util.getScrollbarWidth = function() {
 
1460
    
 
1461
    var scrollbarWidth = OpenLayers.Util._scrollbarWidth;
 
1462
    
 
1463
    if (scrollbarWidth == null) {
 
1464
        var scr = null;
 
1465
        var inn = null;
 
1466
        var wNoScroll = 0;
 
1467
        var wScroll = 0;
 
1468
    
 
1469
        // Outer scrolling div
 
1470
        scr = document.createElement('div');
 
1471
        scr.style.position = 'absolute';
 
1472
        scr.style.top = '-1000px';
 
1473
        scr.style.left = '-1000px';
 
1474
        scr.style.width = '100px';
 
1475
        scr.style.height = '50px';
 
1476
        // Start with no scrollbar
 
1477
        scr.style.overflow = 'hidden';
 
1478
    
 
1479
        // Inner content div
 
1480
        inn = document.createElement('div');
 
1481
        inn.style.width = '100%';
 
1482
        inn.style.height = '200px';
 
1483
    
 
1484
        // Put the inner div in the scrolling div
 
1485
        scr.appendChild(inn);
 
1486
        // Append the scrolling div to the doc
 
1487
        document.body.appendChild(scr);
 
1488
    
 
1489
        // Width of the inner div sans scrollbar
 
1490
        wNoScroll = inn.offsetWidth;
 
1491
    
 
1492
        // Add the scrollbar
 
1493
        scr.style.overflow = 'scroll';
 
1494
        // Width of the inner div width scrollbar
 
1495
        wScroll = inn.offsetWidth;
 
1496
    
 
1497
        // Remove the scrolling div from the doc
 
1498
        document.body.removeChild(document.body.lastChild);
 
1499
    
 
1500
        // Pixel width of the scroller
 
1501
        OpenLayers.Util._scrollbarWidth = (wNoScroll - wScroll);
 
1502
        scrollbarWidth = OpenLayers.Util._scrollbarWidth;
 
1503
    }
 
1504
 
 
1505
    return scrollbarWidth;
 
1506
};