Project

General

Profile

Download (33.1 KB) Statistics
| Branch: | Tag: | Revision:
1
//see also https://github.com/geetarista/jquery-plugin-template/blob/master/jquery.plugin-template.js
2

    
3
/**
4
 * Expected dom structure:
5
 *  '<div class="ahah-content" rel="'.$cdm_proxy_url.'"><span class="loading">Loading ....</span></div>';
6
 */
7
(function($, document, window, undefined) {
8

    
9
    $.fn.cdm_openlayers_map = function(mapserverBaseUrl, mapserverVersion, options) {
10

    
11
        var opts = $.extend({},$.fn.cdm_openlayers_map.defaults, options);
12

    
13
        return this.each(function(){
14
            this.cdmOpenlayersMap = new CdmOpenLayers.Map($(this), mapserverBaseUrl, mapserverVersion, opts);
15
            this.cdmOpenlayersMap.init();
16
        }); // END each
17

    
18
    }; // END cdm_openlayers_map
19

    
20
})(jQuery, document, window, undefined);
21

    
22
(function($){
23
  $.fn.cdm_openlayers_map.defaults = {  // set up default options
24
    legendPosition:  null,      // 1,2,3,4,5,6 = display a legend in the corner specified by the number
25
    distributionOpacity: 0.75,
26
    legendOpacity: 0.75,
27
    boundingBox: "-180,-90,180,90",
28
    aspectRatio: 2, // w/h
29
    showLayerSwitcher: false,
30
    baseLayerNames: ["osgeo_vmap0"],
31
    defaultBaseLayerName: 'osgeo_vmap0',
32
    maxZoom: 4,
33
    minZoom: 0,
34
    debug: true,
35
    /**
36
     * allows the map to display parts of the layers which are outside
37
     * the maxExtent if the aspect ratio of the map and of the baselayer
38
     * are not equal
39
     */
40
    displayOutsideMaxExtent: false,
41
    //  customWMSBaseLayerData: {
42
    //  name: "Euro+Med",
43
    //  url: "http://edit.africamuseum.be/geoserver/topp/wms",
44
    //  params: {layers: "topp:em_tiny_jan2003", format:"image/png", tiled: true},
45
    //  projection: "EPSG:7777777",
46
    //  maxExtent: "-1600072.75, -1800000, 5600000, 5850093",
47
    //  units: 'm'
48
    //  }
49
    customWMSBaseLayerData: {
50
        name: null,
51
        url: null,
52
        params: null,
53
        projection: null,
54
        max_extent: null,
55
        units: null
56
    },
57
    /**
58
     * when true the map is made resizable by adding the jQueryUI widget resizable
59
     * to the map container. This feature requires that the jQueryUI is loaded
60
     */
61
    resizable: false
62
  };
63
})(jQuery);
64

    
65
/**************************************************************************
66
 *                          CdmOpenLayers
67
 **************************************************************************/
68
(function() {
69

    
70
    /**
71
     * The CdmOpenLayers namespace definition
72
     */
73
    window.CdmOpenLayers  = (function () {
74

    
75
        // EPSG:3857 from http://spatialreference.org/ref/sr-org/6864/proj4/
76
        // OpenStreetMap etc
77
        Proj4js.defs["EPSG:3857"] = '+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs';
78

    
79
        var projections = {
80
                epsg_4326: new OpenLayers.Projection("EPSG:4326"),
81
                epsg_900913: new OpenLayers.Projection("EPSG:900913"),
82
                epsg_3857:  new OpenLayers.Projection("EPSG:3857")
83
        };
84
        var mapExtends = {
85
                epsg_4326: new OpenLayers.Bounds(-180, -90, 180, 90),
86
                epsg_900913: new OpenLayers.Bounds(-180, -90, 180, 90),
87
                epsg_3857: new OpenLayers.Bounds(-180, -90, 180, 90)
88
        };
89
        // transform epsg_900913 to units meter
90
        mapExtends.epsg_900913.transform(projections.epsg_4326, projections.epsg_900913);
91
        mapExtends.epsg_3857.transform(projections.epsg_4326, projections.epsg_3857);
92

    
93
        // make public by returning an object
94
        return {
95
            projections: projections,
96
            mapExtends: mapExtends,
97
            getMap: function (){},
98
            getLayerByName: function(layerName){} // initially empty function, will be populated by openlayers_layers.js
99
        };
100

    
101
    })(); // end of namespace definition for CdmOpenLayers
102

    
103
    /**
104
     * The CdmOpenLayers.Map constructor
105
     * @param mapElement
106
     * @param mapserverBaseUrl
107
     * @param mapserverVersion
108
     * @param opts
109
     * @returns
110
     */
111
    window.CdmOpenLayers.Map = function(mapElement, mapserverBaseUrl, mapserverVersion, opts){
112

    
113
        var mapServicePath = '/edit_wp5';
114

    
115
        // firebug console stub (avoids errors if firebug is not active)
116
        if(typeof console === "undefined") {
117
            console = { log: function() { } };
118
        }
119

    
120
        // sanitize given options
121
        try {
122
            opts.customWMSBaseLayerData.max_extent = OpenLayers.Bounds.fromString(opts.customWMSBaseLayerData.max_extent);
123
        } catch(e){
124
            opts.customWMSBaseLayerData.max_extent = null;
125
        }
126

    
127

    
128
        var legendImgSrc = null;
129

    
130
        var map = null;
131

    
132
        var infoElement = null;
133

    
134
        var dataBounds = null;
135

    
136
        var baseLayers = [];
137
        var defaultBaseLayer = null;
138

    
139
        var zoomToBounds = null;
140
        var zoomToClosestLevel = true;
141

    
142
        var LAYER_DATA_CNT = 0;
143

    
144
        /* this is usually the <div id="openlayers"> element */
145
        var mapContainerElement = mapElement.parent();
146

    
147
        var defaultControls = [
148
                               new OpenLayers.Control.PanZoom(),
149
                               new OpenLayers.Control.Navigation({zoomWheelEnabled: false, handleRightClicks:true, zoomBoxKeyMask: OpenLayers.Handler.MOD_CTRL})
150
                               ];
151

    
152

    
153
        var layerByNameMap = {
154
                tdwg1: 'topp:tdwg_level_1',
155
                tdwg2: 'topp:tdwg_level_2',
156
                tdwg3: 'topp:tdwg_level_3',
157
                tdwg4: 'topp:tdwg_level_4'
158
        };
159

    
160
        if(opts.resizable == true) {
161
          // resizable requires jQueryUI to  be loaded!!!
162
          mapContainerElement.resizable({
163
            resize: function( event, ui ) {
164
              map.updateSize();
165
              //   this.printInfo();
166
            }
167
          });
168
        }
169

    
170
        /**
171
         *
172
         */
173
        this.init = function(){ // public function
174

    
175
            // set the height of the container element
176
            adjustHeight();
177

    
178
            // register for resize events to be able to adjust the map aspect ratio and legend position
179
            jQuery( window ).resize(function() {
180
              adjustHeight();
181
              adjustLegendAsElementPosition();
182
            });
183

    
184
            createBaseLayers(opts.baseLayerNames, opts.defaultBaseLayerName, opts.customWMSBaseLayerData);
185

    
186
            initMap();
187

    
188
            // -- Distribution Layer --
189
            var mapServiceRequest;
190
            var distributionQuery = mapElement.attr('distributionQuery');
191

    
192
            if(distributionQuery !== undefined){
193
                distributionQuery = mergeQueryStrings(distributionQuery, '&recalculate=false');
194
                if(typeof legendPosition == 'number'){
195
                    distributionQuery = mergeQueryStrings(distributionQuery, 'legend=1&mlp=' + opts.legendPosition);
196
                }
197

    
198
                distributionQuery = mergeQueryStrings(distributionQuery, 'callback=?');
199
                var legendFormatQuery = mapElement.attr('legendFormatQuery');
200
                if(legendFormatQuery !== undefined){
201
                    legendImgSrc = mergeQueryStrings('/GetLegendGraphic?SERVICE=WMS&VERSION=1.1.1', legendFormatQuery);
202
                }
203

    
204
                mapServiceRequest = mapserverBaseUrl + mapServicePath + '/' + mapserverVersion + '/rest_gen.php?' + distributionQuery;
205

    
206
                LAYER_DATA_CNT++;
207
                jQuery.ajax({
208
                    url: mapServiceRequest,
209
                    dataType: "jsonp",
210
                    success: function(data){
211
                        var layers = createDataLayer(data, "AREA");
212
                        addLayers(layers);
213
                        layerDataLoaded();
214
                    }
215
                });
216
            }
217

    
218
            // -- Occurrence Layer --
219
            var occurrenceQuery = mapElement.attr('occurrenceQuery');
220
            if(occurrenceQuery !== undefined){
221
                occurrenceQuery = mergeQueryStrings(occurrenceQuery, '&recalculate=false');
222
//              if(typeof legendPosition == 'number'){
223
//              occurrenceQuery = mergeQueryStrings(distributionQuery, 'legend=1&mlp=' + opts.legendPosition);
224
//              }
225

    
226

    
227
                occurrenceQuery = mergeQueryStrings(occurrenceQuery, 'callback=?');
228
//              var legendFormatQuery = mapElement.attr('legendFormatQuery');
229
//              if(legendFormatQuery !== undefined){
230
//              legendImgSrc = mergeQueryStrings('/GetLegendGraphic?SERVICE=WMS&VERSION=1.1.1', legendFormatQuery);
231
//              }
232

    
233
                mapServiceRequest = mapserverBaseUrl + mapServicePath + '/' + mapserverVersion + '/rest_gen.php?' + occurrenceQuery;
234

    
235
                LAYER_DATA_CNT++;
236
                jQuery.ajax({
237
                    url: mapServiceRequest,
238
                    dataType: "jsonp",
239
                    success: function(data){
240
                        var layers = createDataLayer(data, "POINT");
241
                        addLayers(layers);
242
                        layerDataLoaded();
243
                    }
244
                });
245
            }
246

    
247
        };
248

    
249
        var layerDataLoaded = function() {
250
          LAYER_DATA_CNT--;
251
          if(LAYER_DATA_CNT == 0){
252
            initPostDataLoaded();
253
          }
254
        };
255

    
256
        var initPostDataLoaded = function () {
257
          // all layers prepared, make the visible
258
          map.layers.forEach(function(layer){
259

    
260
            // hack for cuba
261
            if(layer.name == "flora_cuba_2016_regions"){
262
              map.setLayerZIndex(layer, 5);
263
            }
264
            if(layer.name == "flora_cuba_2016_provinces"){
265
              map.setLayerZIndex(layer, 6);
266
            }
267
            if(layer.name == "flora_cuba_2016_world"){
268
              map.setLayerZIndex(layer, 4);
269
            }
270

    
271
            layer.setVisibility(true);
272
          });
273

    
274
          // zoom to the zoomToBounds
275
          log(" > starting zoomToExtend " + zoomToBounds, true);
276
          map.zoomToExtent(zoomToBounds, zoomToClosestLevel);
277

    
278
          if(map.getZoom() > opts.maxZoom){
279
            map.zoomTo(opts.maxZoom);
280
          } else if(map.getZoom() < opts.minZoom){
281
            map.zoomTo(opts.minZoom);
282
          }
283

    
284
          log(" > zoomToExtend done", true);
285
        };
286

    
287
        var getHeight = function(){
288
          return mapContainerElement.width() / opts.aspectRatio;
289
        };
290

    
291
        var getWidth = function(){
292
          return mapContainerElement.width();
293
        };
294

    
295
        var adjustHeight = function() {
296
          mapContainerElement.css("height", getHeight());
297
        };
298

    
299
        /**
300
         * public function
301
         */
302
        this.registerEvents = function(events){
303
            for (var key in events) {
304
                if (events.hasOwnProperty(key)) {
305
                    map.events.register(key, map , events[key]);
306
                }
307
            }
308
        };
309

    
310

    
311
        /**
312
         * public function
313
         */
314
        this.getMap = function(){
315
            return map;
316
        };
317

    
318
        /**
319
         * Prints info on the current map into the jQuery element
320
         * as set in the options (opts.infoElement)
321
         * public function
322
         *
323
         * @param jQuery $element
324
         */
325
        this.printInfo = function(){
326

    
327
            var mapExtendDegree = map.getExtent().clone();
328
            mapExtendDegree.transform(map.baseLayer.projection, CdmOpenLayers.projections.epsg_4326);
329

    
330
            var info = "<dl>";
331
            info += "<dt>zoom:<dt><dd>" + map.getZoom() + "</dd>";
332
            if(opts.debug){
333
                info += "<dt>map resolution:<dt><dd>" + map.getResolution() + "</dd>";
334
                info += "<dt>map max resolution:<dt><dd>" + map.getMaxResolution() + "</dd>";
335
                info += "<dt>map scale:<dt><dd>" + map.getScale() + "</dd>";
336
                info += "<dt>map width, height:<dt><dd>" + mapContainerElement.width() +  ", " + mapContainerElement.height() + "</dd>";
337
                info += "<dt>map aspect ratio:<dt><dd>" + mapContainerElement.width() / mapContainerElement.height() + "</dd>";
338
                info += "<dt>map extent bbox:<dt><dd class=\"map-extent-bbox\">" + map.getExtent().toBBOX() + ", <strong>degree:</strong> <span class=\"degree-value\">" + mapExtendDegree.toBBOX() + "</span></dd>";
339
                info += "<dt>map maxExtent bbox:<dt><dd>" + map.getMaxExtent().toBBOX() + "</dd>";
340
                info += "<dt>baselayer extent bbox:<dt><dd class=\"baselayer-extent-bbox\">" + map.baseLayer.getExtent().toBBOX() + ", <strong>degree:</strong> <span class=\"degree-value\">"
341
                  + map.baseLayer.getExtent().clone().transform(map.baseLayer.projection, CdmOpenLayers.projections.epsg_4326) + "</span></dd>"
342
                info += "<dt>baselayer projection:<dt><dd>" + map.baseLayer.projection.getCode() + "</dd>";
343
            } else {
344
                info += "<dt>bbox:<dt><dd>" + mapExtendDegree.toBBOX() + "</dd>";
345
            }
346
            info += "</dl>";
347

    
348
            if(infoElement == null){
349
                infoElement = jQuery('<div class="map_info"></div>');
350
                mapElement.parent().after(infoElement);
351
            }
352
            infoElement.html(info);
353
        };
354

    
355
        /**
356
         * Initialize the Openlayers Map with the base layer
357
         */
358
        var initMap = function(){
359

    
360
            if(opts.showLayerSwitcher === true){
361
                defaultControls.push(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
362
            }
363

    
364
            defaultControls.unshift(layerLoadingControl()); // as first control, needs to be below all others!
365

    
366
//          var maxExtentByAspectRatio = cropBoundsToAspectRatio(defaultBaseLayer.maxExtent, getWidth/getHeight);
367
            var maxResolution = null;
368
            // gmaps has no maxExtent at this point, need to check for null
369
            if(defaultBaseLayer.maxExtent != null){
370
                maxResolution = Math[(opts.displayOutsideMaxExtent ? 'max' : 'min')](
371
                        defaultBaseLayer.maxExtent.getWidth() / getWidth(),
372
                        defaultBaseLayer.maxExtent.getHeight() / getHeight()
373
                );
374
            }
375
            console.log("mapOptions.maxResolution: " + maxResolution);
376
            console.log("mapOptions.restrictedExtent: " + defaultBaseLayer.maxExtent);
377

    
378
            map = new OpenLayers.Map(
379
                    "openlayers_map",
380
                    {
381
                        // defines the map ui elements and interaction features
382
                        controls: defaultControls,
383

    
384
                        // maxResolution determines the lowest zoom level and thus places the map
385
                        // in its maximum extent into the available view port so that no additinal
386
                        // gutter is visible and no parts of the map are hidden
387
                        // see http://trac.osgeo.org/openlayers/wiki/SettingZoomLevels
388
                        // IMPORTANT!!!
389
                        // the maxResulution set here will be overwritten if the baselayers maxResolution
390
                        // it is set
391
                        maxResolution: maxResolution,
392

    
393
                        // setting restrictedExtent the the maxExtent prevents from panning the
394
                        // map out of its bounds
395
                        restrictedExtent: defaultBaseLayer.maxExtent,
396
//                      maxExtent: defaultBaseLayer.maxExtent,
397

    
398
                        // Setting the map.fractionalZoom property to true allows zooming to an arbitrary level
399
                        // (between the min and max resolutions).
400
                        // fractional tiles are not supported by XYZ layers like OSM so this option would
401
                        // break the tile retrieval for OSM (e.g.: tile for fractional zoom level
402
                        // 1.2933333333333332 = http://b.tile.openstreetmap.org/1.2933333333333332/1/0.png)
403
                        fractionalZoom: defaultBaseLayer.CLASS_NAME != "OpenLayers.Layer.OSM" && defaultBaseLayer.CLASS_NAME != "OpenLayers.Layer.XYZ",
404

    
405
                        eventListeners: opts.eventListeners,
406
                        // creating the map with a null theme, since we include the stylesheet directly in the page
407
                        theme: null
408

    
409
                    }
410
            );
411

    
412
            //add the base layers
413

    
414
            addLayers(baseLayers);
415
            map.setBaseLayer(defaultBaseLayer);
416

    
417
            // calculate the bounds to zoom to
418
            zoomToBounds = zoomToBoundsFor(opts.boundingBox, defaultBaseLayer);
419
            zoomToBounds = cropBoundsToAspectRatio(zoomToBounds, map.getSize().w / map.getSize().h);
420
            console.log("baselayer zoomToBounds: " + zoomToBounds);
421

    
422
        };
423

    
424
        var addLayers = function(layers){
425

    
426
          layers.forEach(function(layer){
427
            // layer.setVisibility(false);
428
          });
429

    
430
          map.addLayers(layers);
431
        };
432

    
433
        /**
434
         * add a distribution or occurrence layer
435
         *
436
         * @param mapResponseObj
437
         *   The reponse object returned by the edit map service
438
         * @param dataType
439
         *   either "AREA" or "POINT"
440
         */
441
        var createDataLayer = function(mapResponseObj, dataType){
442

    
443
            console.log("creating data layer of type " + dataType);
444

    
445
            var dataLayerOptions = {
446
                    isBaseLayer: false,
447
                    displayInLayerSwitcher: true,
448
                    maxExtent: map.maxExtent.clone().transform(new OpenLayers.Projection("EPSG:4326"), map.baseLayer.projection),
449
                    displayOutsideMaxExtent: true
450
            };
451

    
452
            var layers = [];
453
            // add additional layers, get them from the mapResponseObj
454
            if(mapResponseObj !== undefined){
455
                if(dataType == "POINT" && mapResponseObj.points_sld !== undefined){
456
                  var pointLayer;
457
                  // it is a response for an point map
458
                  var geoserverUri;
459
                  if(mapResponseObj.geoserver) {
460
                      geoserverUri = mapResponseObj.geoserver;
461
                  } else {
462
                      // it is an old service which is not providing the corresponding geoserver URI, so we guess it
463
                      geoserverUri = mapserverBaseUrl + "/geoserver/wms";
464
                  }
465

    
466
                  //TODO points_sld should be renamed to sld in response + fill path to sld should be given
467
                  pointLayer = new OpenLayers.Layer.WMS(
468
                          'points',
469
                          geoserverUri,
470
                          {
471
                              layers: 'topp:rest_points',
472
                              transparent:"true",
473
                              format:"image/png"
474
                          },
475
                          dataLayerOptions
476
                  );
477

    
478
                  var sld = mapResponseObj.points_sld;
479
                  if(sld.indexOf("http://") !== 0){
480
                      // it is an old servive which is not providing the full sdl URI, so we guess it
481
                      //  http://edit.africamuseum.be/synthesys/www/v1/sld/
482
                      //  http://edit.br.fgov.be/synthesys/www/v1/sld/
483
                      sld =  mapserverBaseUrl + "/synthesys/www/v1/sld/" + sld;
484
                  }
485
                  pointLayer.params.SLD = sld;
486

    
487
                  layers.push(pointLayer);
488
                } else {
489
                    // it is a response from for a distribution map
490
                    console.log("start with adding distribution layers :");
491
                    for ( var i in mapResponseObj.layers) {
492
                        var layerData = mapResponseObj.layers[i];
493

    
494
                        console.log(" " + i +" -> " + layerData.tdwg);
495
                        var layer = new OpenLayers.Layer.WMS(
496
                                layerData.tdwg,
497
                                mapResponseObj.geoserver + "/wms",
498
                                {
499
                                    layers: layerByNameMap[layerData.tdwg],
500
                                    transparent:"true",
501
                                    format:"image/png"
502
                                },
503
                                dataLayerOptions
504
                                );
505
                        layer.params.SLD = layerData.sld;
506
                        layer.setOpacity(opts.distributionOpacity);
507

    
508
                        layers.push(layer);
509
                    }
510
                }
511

    
512
                if(layers.length > 0) {
513
                  // calculate zoomBounds for the using the first layer
514
                  if(mapResponseObj.bbox !== undefined){
515
                    var newBounds =  OpenLayers.Bounds.fromString( mapResponseObj.bbox );
516
                    newBounds.transform(layers[0].projection, map.getProjectionObject());
517
                    if(dataBounds !== null){
518
                      dataBounds.extend(newBounds);
519
                    } else if(newBounds !== undefined){
520
                      dataBounds = newBounds;
521
                    }
522

    
523
                    zoomToBounds = dataBounds;
524
                    console.log("data layer zoomToBounds: " + zoomToBounds);
525
                    zoomToClosestLevel = false;
526
                  }
527
                }
528

    
529

    
530

    
531
                if(legendImgSrc != null && opts.legendPosition !== undefined && mapResponseObj.legend !== undefined){
532
                    var legendSrcUrl = mapResponseObj.geoserver + legendImgSrc + mapResponseObj.legend;
533
                    addLegendAsElement(legendSrcUrl);
534
                    //addLegendAsLayer(legendSrcUrl, map);
535
                }
536

    
537
                return layers;
538
            }
539

    
540
        };
541

    
542
        /**
543
         *
544
         */
545
        var addLegendAsElement= function(legendSrcUrl){
546

    
547
            var legendElement = jQuery('<div class="openlayers_legend"></div>');
548
            var legendImage = jQuery('<img src="' + legendSrcUrl + '"/>');
549
            legendElement
550
                .css('opacity', opts.legendOpacity)
551
                .css('position', 'relative')
552
                .css('z-index', '1002')
553
                .css('top', -mapElement.height());
554
            legendImage.load(function () {
555
                jQuery(this).parent()
556
                    .css('left', getWidth() - jQuery(this).width())
557
                    .width(jQuery(this).width());
558
                // reset height to original value
559
                adjustHeight();
560
            });
561
            legendElement.html(legendImage);
562
            mapElement.after(legendElement);
563
        };
564

    
565
         var adjustLegendAsElementPosition = function (){
566
           var legendContainer = mapContainerElement.children('.openlayers_legend');
567
           var legendImage = legendContainer.children('img');
568
           legendContainer.css('top', -mapElement.height())
569
             .css('left', getWidth() - legendImage.width());
570
         };
571

    
572

    
573
        var addLegendAsLayer= function(legendSrcUrl, map){
574
            var w, h;
575

    
576
            // 1. download image to find height and width
577
            mapElement.after('<div class="openlayers_legend"><img src="' + legendSrcUrl + '"></div>');
578
            mapElement.next('.openlayers_legend').css('display', 'none').css('opacity', opts.legendOpacity).find('img').load(function () {
579

    
580
                w = mapElement.next('.openlayers_legend').find('img').width();
581
                h = mapElement.next('.openlayers_legend').find('img').height();
582
                mapElement.next('.openlayers_legend').remove();
583

    
584
//              createLegendLayer();
585
//              // 2. create the Legend Layer
586
                //TODO createLegendLayer as inner function seems like an error
587
//              var createLegendLayer = function(){
588
                //
589
                //
590
//              var legendLayerOptions={
591
//              maxResolution: '.$maxRes.',
592
//              maxExtent: new OpenLayers.Bounds(0, 0, w, h)
593
//              };
594
                //
595
//              var legendLayer = new OpenLayers.Layer.Image(
596
//              'Legend',
597
//              legendSrcUrl,
598
//              new OpenLayers.Bounds(0, 0, w, h),
599
//              new OpenLayers.Size(w, h),
600
//              imageLayerOptions);
601
//              };
602
            });
603

    
604

    
605
        };
606

    
607
        /**
608
         * merge 2 Url query strings
609
         */
610
        var mergeQueryStrings = function(queryStr1, queryStr2){
611
            if(queryStr1.charAt(queryStr1.length - 1) != '&'){
612
                queryStr1 += '&';
613
            }
614
            if(queryStr2.charAt(0) == '&'){
615
                return queryStr1 + queryStr2.substr(1);
616
            } else {
617
                return queryStr1 + queryStr2;
618
            }
619

    
620
        };
621

    
622
        /**
623
         *
624
         */
625
        var createBaseLayers = function( baseLayerNames, defaultBaseLayerName, customWMSBaseLayerData){
626

    
627
            for(var i = 0; i <  baseLayerNames.length; i++) {
628
                // create the layer
629
                if (baseLayerNames[i] == "custom_wms_base_layer_1"){
630
                    baseLayers[i] = createWMSBaseLayer(
631
                            customWMSBaseLayerData.name,
632
                            customWMSBaseLayerData.url,
633
                            customWMSBaseLayerData.params,
634
                            customWMSBaseLayerData.projection,
635
                            customWMSBaseLayerData.proj4js_def,
636
                            customWMSBaseLayerData.units,
637
                            customWMSBaseLayerData.max_extent
638
                    );
639
                } else {
640
                    baseLayers[i] = window.CdmOpenLayers.getLayerByName(baseLayerNames[i]);
641
                }
642
                // set default baselayer
643
                if(baseLayerNames[i] == defaultBaseLayerName){
644
                    defaultBaseLayer = baseLayers[i];
645
                }
646

    
647
            }
648
        };
649

    
650
        /**
651
         * returns the intersection of the bounds b1 and b2.
652
         * The b1 and b2 do not intersect b1 will be returned.
653
         *
654
         * @param OpenLayers.Bounds b1
655
         * @param OpenLayers.Bounds b2
656
         *
657
         * @return the bounds of the intersection between both rectangles
658
         */
659
        var intersectionOfBounds = function (b1, b2){
660

    
661
            if(b1.intersectsBounds(b2)){
662

    
663
                var left = Math.max(b1.left, b2.left);
664
                var bottom = Math.max(b1.bottom, b2.bottom);
665
                var right = Math.min(b1.right, b2.right);
666
                var top = Math.min(b1.top, b2.top);
667

    
668
                return new OpenLayers.Bounds(left, bottom, right, top);
669

    
670
            } else {
671
                return b1;
672
            }
673
        };
674

    
675
        /**
676
         *
677
         * @param OpenLayers.Bounds b
678
         * @param float aspectRatio width/height
679
         *
680
         * @return the bounds cropped to the given aspectRatio
681
         */
682
        var cropBoundsToAspectRatio = function (b, aspectRatio){
683

    
684
            var cropedB = b.clone();
685

    
686
            if(aspectRatio == 1){
687
                return cropedB;
688
            }
689

    
690
            /*
691
             * LonLat:
692
             *   lon {Float} The x-axis coodinate in map units
693
             *   lat {Float} The y-axis coordinate in map units
694
             */
695
            var center = cropedB.getCenterLonLat();
696
            if(aspectRatio < 1){
697
                var dist = (b.getHeight() / 2) * aspectRatio;
698
                cropedB.top = center.lat + dist;
699
                cropedB.cropedBottom = center.lat - dist;
700
            } else if(aspectRatio > 1){
701
                var dist = (b.getWidth() / 2) / aspectRatio;
702
                cropedB.left = center.lon - dist;
703
                cropedB.right = center.lon + dist;
704
            }
705
            return cropedB;
706
        };
707

    
708
        /**
709
         * returns the zoom to bounds.
710
         *
711
         * @param bboxString
712
         *     a string representation of the bounds in degree
713
         * @param layer
714
         *     the Openlayers.Layer
715
         *
716
         * @return the bboxstring projected onto the layer and intersected with the maximum extent of the layer
717
         */
718
        var zoomToBoundsFor = function(bboxString, layer){
719
            var zoomToBounds;
720
            if(typeof bboxString == 'string' && bboxString.length > 6) {
721
                zoomToBounds = OpenLayers.Bounds.fromString(bboxString);
722
                // transform bounding box given in degree values to the projection of the base layer
723
                zoomToBounds.transform(CdmOpenLayers.projections.epsg_4326, layer.projection);
724
            } else if(layer.maxExtent) {
725
                zoomToBounds = layer.maxExtent;
726
                // no need to transform since the bounds are obtained from the layer
727
            } else {
728
                zoomToBounds = new OpenLayers.Bounds(-180, -90, 180, 90);
729
                // transform bounding box given in degree values to the projection of the base layer
730
                zoomToBounds.transform(CdmOpenLayers.projections.epsg_4326, layer.projection);
731
            }
732

    
733
            zoomToBounds = intersectionOfBounds(layer.maxExtent, zoomToBounds);
734

    
735
            return zoomToBounds;
736
        };
737

    
738

    
739

    
740
        /**
741
         * returns the version number contained in the version string:
742
         *   v1.1 --> 1.1
743
         *   v1.2_dev --> 1.2
744
         */
745
        var mapServerVersionNumber = function() {
746
            var pattern = /v([\d\.]+).*$/;
747
            var result;
748
            if (result = mapserverVersion.match(pattern) !== null) {
749
                return result[0];
750
            } else {
751
                return null;
752
            }
753
        };
754

    
755
        var log = function(message, addTimeStamp){
756
          var timestamp = '';
757
          if(addTimeStamp == true){
758
            var time = new Date();
759
            timestamp = time.getSeconds() + '.' + time.getMilliseconds() + 's';
760
          }
761
          console.log(timestamp + message);
762
        };
763

    
764
        /**
765
         * Creates a WMS Base layer
766
         * @param String name
767
         *     A name for the layer
768
         * @param String url
769
         *     Base url for the WMS (e.g.  http://wms.jpl.nasa.gov/wms.cgi)
770
         * @param Object params
771
         *     An object with key/value pairs representing the GetMap query string parameters and parameter values.
772
         * @param Object projection
773
         *    A OpenLayers.Projection object
774
         */
775
        var createWMSBaseLayer= function(name, url, params, projection, proj4js_def, units, maxExtent){
776

    
777
            console.log("creating WMSBaseLayer");
778

    
779
            if(projection && proj4js_def){
780
                // in case projection has been defined for the layer and if there is also
781
                // a Proj4js.defs, add it!
782
                Proj4js.defs[projection] = proj4js_def;
783
            }
784

    
785
            if(maxExtent == null){
786
                maxExtent = CdmOpenLayers.mapExtends.epsg_4326.clone();
787
                maxExtent.transform(CdmOpenLayers.projections.epsg_4326, projection);
788
            }
789

    
790
          wmsLayer = new OpenLayers.Layer.WMS(
791
            name,
792
            url,
793
            params,
794
            {
795
              maxExtent: maxExtent,
796
              projection: projection,
797
              units: units,
798
              isBaseLayer: true,
799
              displayInLayerSwitcher: true
800
            }
801
          );
802

    
803
          if(wmsLayer == null){
804
            console.log("Error creating WMSBaseLayer");
805
          }
806

    
807
          return  wmsLayer;
808
        };
809

    
810
        var layerLoadingControl = function() {
811

    
812
          var control = new OpenLayers.Control();
813

    
814
          OpenLayers.Util.extend(control, {
815

    
816
            LAYERS_LOADING: 0,
817

    
818
            updateState: function () {
819
              if(this.div != null){
820
                if (this.LAYERS_LOADING > 0) {
821
                  this.div.style.display = "block";
822
                } else {
823
                  this.div.style.display = "none";
824
                }
825
              }
826
            },
827

    
828
            updateSize: function () {
829
              this.div.style.width = this.map.size.w + "px";
830
              this.div.style.height = this.map.size.h  + "px";
831
              this.div.style.textAlign = "center";
832
              this.div.style.lineHeight = this.map.size.h  + "px";
833
            },
834

    
835
            counterIncrease: function (layer) {
836
              this.control.LAYERS_LOADING++;
837
              log(' > loading start : ' + this.layer.name + ' ' + this.control.LAYERS_LOADING, true);
838
              this.control.updateState();
839
            },
840

    
841
            counterDecrease: function (layer) {
842
              this.control.LAYERS_LOADING--;
843
              log(' > loading end : ' + this.layer.name + ' ' + this.control.LAYERS_LOADING, true);
844
              this.control.updateState();
845
            },
846

    
847
            draw: function () {
848

    
849
              // call the default draw function to initialize this.div
850
              OpenLayers.Control.prototype.draw.apply(this, arguments);
851

    
852
              this.map.events.register('updatesize', this, function(e){
853
                  this.updateSize();
854
                }
855
              );
856

    
857
              var loadingIcon = document.createElement("i");
858
              var fa_class = document.createAttribute("class");
859
              // fa-circle-o-notch fa-spin
860
              // fa-spinner fa-pulse
861
              // fa-refresh
862
              fa_class.value = "fa fa-refresh fa-spin fa-5x";
863
              loadingIcon.attributes.setNamedItem(fa_class);
864

    
865
              this.updateSize();
866

    
867
              this.div.appendChild(loadingIcon);
868

    
869
              this.registerEvents();
870

    
871
              return this.div;
872
            },
873

    
874
            registerEvents: function() {
875

    
876
              this.map.events.register('preaddlayer', this, function(e){
877
                console.log(" > preaddlayer " + e.layer.name);
878
                e.layer.events.register('loadstart', {control: this, layer: e.layer}, this.counterIncrease);
879
                e.layer.events.register('loadend', {control: this, layer: e.layer}, this.counterDecrease);
880
              });
881
            }
882

    
883
          });
884

    
885
          return control;
886
        }
887

    
888
    }; // end of CdmOpenLayers.Map
889
})();
890

    
891

    
892

    
893

    
894

    
895

    
896

    
897

    
898

    
(2-2/2)