Project

General

Profile

Download (35.6 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
      // sanitize invalid opts.boundingBox
14
      if(opts.boundingBox &&  !( typeof opts.boundingBox  == 'string' && opts.boundingBox .length > 6)) {
15
        opts.boundingBox = null;
16
      }
17

    
18
      return this.each(function(){
19
          this.cdmOpenlayersMap = new CdmOpenLayers.Map($(this), mapserverBaseUrl, mapserverVersion, opts);
20
          this.cdmOpenlayersMap.create();
21
      }); // END each
22

    
23
    }; // END cdm_openlayers_map
24

    
25
})(jQuery, document, window, undefined);
26

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

    
77
/**************************************************************************
78
 *                          CdmOpenLayers
79
 **************************************************************************/
80
(function() {
81

    
82
    /**
83
     * The CdmOpenLayers namespace definition
84
     */
85
    window.CdmOpenLayers  = (function () {
86

    
87
        // EPSG:3857 from http://spatialreference.org/ref/sr-org/6864/proj4/
88
        // OpenStreetMap etc
89
        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';
90

    
91
        var projections = {
92
                epsg_4326: new OpenLayers.Projection("EPSG:4326"),
93
                epsg_900913: new OpenLayers.Projection("EPSG:900913"),
94
                epsg_3857:  new OpenLayers.Projection("EPSG:3857")
95
        };
96
        var mapExtends = {
97
                epsg_4326: new OpenLayers.Bounds(-180, -90, 180, 90),
98
                epsg_900913: new OpenLayers.Bounds(-180, -90, 180, 90),
99
                epsg_3857: new OpenLayers.Bounds(-180, -90, 180, 90)
100
        };
101
        // transform epsg_900913 to units meter
102
        mapExtends.epsg_900913.transform(projections.epsg_4326, projections.epsg_900913);
103
        mapExtends.epsg_3857.transform(projections.epsg_4326, projections.epsg_3857);
104

    
105
        // make public by returning an object
106
        return {
107
            projections: projections,
108
            mapExtends: mapExtends,
109
            getMap: function (){},
110
            getLayerByName: function(layerName){} // initially empty function, will be populated by openlayers_layers.js
111
        };
112

    
113
    })(); // end of namespace definition for CdmOpenLayers
114

    
115
    /**
116
     * The CdmOpenLayers.Map constructor
117
     * @param mapElement
118
     * @param mapserverBaseUrl
119
     * @param mapserverVersion
120
     * @param opts
121
     * @returns
122
     */
123
    window.CdmOpenLayers.Map = function(mapElement, mapserverBaseUrl, mapserverVersion, opts){
124

    
125
      var mapServicePath = '/edit_wp5';
126

    
127
      // firebug console stub (avoids errors if firebug is not active)
128
      if(typeof console === "undefined") {
129
          console = { log: function() { } };
130
      }
131

    
132
      // sanitize given options
133
      try {
134
          opts.customWMSBaseLayerData.max_extent = OpenLayers.Bounds.fromString(opts.customWMSBaseLayerData.max_extent);
135
      } catch(e){
136
          opts.customWMSBaseLayerData.max_extent = null;
137
      }
138

    
139

    
140
      var legendImgSrc = null;
141

    
142
      var map = null;
143

    
144
      var infoElement = null;
145

    
146
      var baseLayers = [];
147

    
148
      var defaultBaseLayer = null;
149

    
150
      /**
151
       * The top most layer which will be places above all data layers
152
       *
153
       * @type {null}
154
       */
155
      var wmsOverlay = null;
156

    
157
      /**
158
       * Default bounding box for map viewport in the projection of the base layer.
159
       * as defined by the user, can be null.
160
       *
161
       * These are bounds in the epsg_4326 projection, and will be transformed to the baselayer projection.
162
       *
163
       * @type string
164
       */
165
      var defaultBaseLayerBoundingBox = "-180,-90,180,90";
166

    
167
      /**
168
       * bounding box for map viewport as defined by the user, can be null.
169
       *
170
       * These are bounds in the projection of the base layer.
171
       *
172
       * @type string
173
       */
174
      var boundingBox = null;
175

    
176
      /**
177
       * Bounds for the view port calculated from the data layer responses.
178
       * These are either calculated by the minimum bounding box which
179
       * encloses the data in the data layers, or it is equal to the
180
       * boundingBox as defined by the user.
181
       *
182
       * These are bounds in the projection of the base layer.
183
       *
184
       * @see boundingBox
185
       *
186
       * @type OpenLayers.Bounds
187
       */
188
      var dataBounds = null;
189

    
190
      /**
191
       * Final value for the view port, calculated from the other bounds.
192
       *
193
       * These are bounds in the projection of the base layer.
194
       *
195
       * @type OpenLayers.Bounds
196
       */
197
      var zoomToBounds = null;
198

    
199
      var zoomToClosestLevel = true;
200

    
201
      var LAYER_DATA_CNT = 0;
202

    
203
      /* this is usually the <div id="openlayers"> element */
204
      var mapContainerElement = mapElement.parent();
205

    
206
      var defaultControls = [
207
         new OpenLayers.Control.PanZoom(),
208
         new OpenLayers.Control.Navigation(
209
           {
210
             zoomWheelEnabled: false,
211
             handleRightClicks:true,
212
             zoomBoxKeyMask: OpenLayers.Handler.MOD_CTRL
213
           }
214
         )
215
      ];
216

    
217

    
218
      var layerByNameMap = {
219
              tdwg1: 'topp:tdwg_level_1',
220
              tdwg2: 'topp:tdwg_level_2',
221
              tdwg3: 'topp:tdwg_level_3',
222
              tdwg4: 'topp:tdwg_level_4'
223
      };
224

    
225
      if(opts.resizable == true) {
226
        // resizable requires jQueryUI to  be loaded!!!
227
        mapContainerElement.resizable({
228
          resize: function( event, ui ) {
229
            map.updateSize();
230
            //   this.printInfo();
231
          }
232
        });
233
      }
234

    
235
        /**
236
         *
237
         */
238
        this.create = function(){ // public function
239

    
240
          // set the height of the container element
241
          adjustHeight();
242

    
243
          // register for resize events to be able to adjust the map aspect ratio and legend position
244
          jQuery( window ).resize(function() {
245
            adjustHeight();
246
            adjustLegendAsElementPosition();
247
          });
248

    
249
          createBaseLayers(opts.baseLayerNames, opts.defaultBaseLayerName, opts.customWMSBaseLayerData);
250

    
251
          initMap();
252

    
253
          // now it is
254
          if(opts.boundingBox){
255
            boundingBox = OpenLayers.Bounds.fromString(opts.boundingBox);
256
            boundingBox.transform(CdmOpenLayers.projections.epsg_4326, map.getProjectionObject());
257
          }
258

    
259
          // -- Distribution Layer --
260
          var mapServiceRequest;
261
          var distributionQuery = mapElement.attr('distributionQuery');
262

    
263
          if(distributionQuery !== undefined){
264
            distributionQuery = mergeQueryStrings(distributionQuery, '&recalculate=false');
265
            if(typeof legendPosition === 'number'){
266
              distributionQuery = mergeQueryStrings(distributionQuery, 'legend=1&mlp=' + opts.legendPosition);
267
            }
268
            if(opts.boundingBox){
269
              distributionQuery = mergeQueryStrings(distributionQuery, 'bbox=' + boundingBox);
270
            }
271

    
272
            distributionQuery = mergeQueryStrings(distributionQuery, 'callback=?');
273
            var legendFormatQuery = mapElement.attr('legendFormatQuery');
274
            if(legendFormatQuery !== undefined){
275
              legendImgSrc = mergeQueryStrings('/GetLegendGraphic?SERVICE=WMS&VERSION=1.1.1', legendFormatQuery);
276
            }
277

    
278
            mapServiceRequest = mapserverBaseUrl + mapServicePath + '/' + mapserverVersion + '/rest_gen.php?' + distributionQuery;
279

    
280
            LAYER_DATA_CNT++;
281
            jQuery.ajax({
282
              url: mapServiceRequest,
283
              dataType: "jsonp",
284
              success: function(data){
285
                  var layers = createDataLayer(data, "AREA");
286
                  addLayers(layers);
287
                  layerDataLoaded();
288
              }
289
            });
290
          }
291

    
292
          // -- Occurrence Layer --
293
          var occurrenceQuery = mapElement.attr('occurrenceQuery');
294
          if(occurrenceQuery !== undefined){
295
            occurrenceQuery = mergeQueryStrings(occurrenceQuery, '&recalculate=false');
296
//              if(typeof legendPosition == 'number'){
297
//              occurrenceQuery = mergeQueryStrings(distributionQuery, 'legend=1&mlp=' + opts.legendPosition);
298
//              }
299

    
300

    
301
            occurrenceQuery = mergeQueryStrings(occurrenceQuery, 'callback=?');
302
//              var legendFormatQuery = mapElement.attr('legendFormatQuery');
303
//              if(legendFormatQuery !== undefined){
304
//              legendImgSrc = mergeQueryStrings('/GetLegendGraphic?SERVICE=WMS&VERSION=1.1.1', legendFormatQuery);
305
//              }
306
            if(opts.boundingBox){
307
              occurrenceQuery = mergeQueryStrings(occurrenceQuery, 'bbox=' + boundingBox);
308
            }
309

    
310
            mapServiceRequest = mapserverBaseUrl + mapServicePath + '/' + mapserverVersion + '/rest_gen.php?' + occurrenceQuery;
311

    
312
            LAYER_DATA_CNT++;
313
            jQuery.ajax({
314
              url: mapServiceRequest,
315
              dataType: "jsonp",
316
              success: function(data){
317
                  var layers = createDataLayer(data, "POINT");
318
                  addLayers(layers);
319
                  layerDataLoaded();
320
              }
321
            });
322
          }
323

    
324
          if(LAYER_DATA_CNT === 0) {
325
            // a map only with base layer
326
            initPostDataLoaded();
327
          }
328

    
329
          // -- Overlay Layer --
330
          if(opts.wmsOverlayLayerData.params){
331
            overlay_layer_params = opts.wmsOverlayLayerData.params;
332
            overlay_layer_params.transparent=true;
333
            wmsOverlay = createWMSLayer(
334
              opts.wmsOverlayLayerData.name,
335
              opts.wmsOverlayLayerData.url,
336
              overlay_layer_params,
337
              null,
338
              null,
339
              null,
340
              null
341
            );
342

    
343
            if(map.addLayer(wmsOverlay)){
344
              wmsOverlay.setVisibility(true);
345
              map.setLayerIndex(wmsOverlay, 100);
346
              log("Overlay wms added");
347
            } else {
348
              log("ERROR adding overlay wms layer")
349
            }
350
          }
351

    
352
          log("Map viewer creation complete.");
353

    
354
        };
355

    
356
        var layerDataLoaded = function() {
357
          LAYER_DATA_CNT--;
358
          if(LAYER_DATA_CNT === 0){
359
            initPostDataLoaded();
360
          }
361
        };
362

    
363
        var initPostDataLoaded = function () {
364
          // all layers prepared, make the visible
365
          map.layers.forEach(function(layer){
366
            layer.setVisibility(true);
367
          });
368

    
369
          // zoom to the zoomToBounds
370
          log(" > starting zoomToExtend " + zoomToBounds, true);
371
          map.zoomToExtent(zoomToBounds, zoomToClosestLevel);
372

    
373
          if(map.getZoom() > opts.maxZoom){
374
            map.zoomTo(opts.maxZoom);
375
          } else if(map.getZoom() < opts.minZoom){
376
            map.zoomTo(opts.minZoom);
377
          }
378

    
379
          // make sure the wmsOverlay is still on top
380
          if(wmsOverlay){
381
            map.setLayerIndex(wmsOverlay, 100);
382
          }
383

    
384
          log(" > zoomToExtend done", true);
385
        };
386

    
387
        var getHeight = function(){
388
          return mapContainerElement.width() / opts.aspectRatio;
389
        };
390

    
391
        var getWidth = function(){
392
          return mapContainerElement.width();
393
        };
394

    
395
        var adjustHeight = function() {
396
          mapContainerElement.css("height", getHeight());
397
        };
398

    
399
        /**
400
         * public function
401
         */
402
        this.registerEvents = function(events){
403
            for (var key in events) {
404
                if (events.hasOwnProperty(key)) {
405
                    map.events.register(key, map , events[key]);
406
                }
407
            }
408
        };
409

    
410

    
411
        /**
412
         * public function
413
         */
414
        this.getMap = function(){
415
            return map;
416
        };
417

    
418
        /**
419
         * Prints info on the current map into the jQuery element
420
         * as set in the options (opts.infoElement)
421
         * public function
422
         *
423
         */
424
        this.printInfo = function(){
425

    
426

    
427
            var mapExtendDegree = null;
428
            if(map.getExtent() != null){
429
              // If the baselayer is not yet set, getExtent() returns null.
430
              mapExtendDegree = map.getExtent().clone();
431
              mapExtendDegree.transform(map.baseLayer.projection, CdmOpenLayers.projections.epsg_4326);
432
            }
433

    
434
            var info = "<dl>";
435
            info += "<dt>zoom:<dt><dd>" + map.getZoom() + "</dd>";
436
            if(opts.debug){
437
                info += "<dt>map resolution:<dt><dd>" + map.getResolution() + "</dd>";
438
                info += "<dt>map max resolution:<dt><dd>" + map.getMaxResolution() + "</dd>";
439
                info += "<dt>map scale:<dt><dd>" + map.getScale() + "</dd>";
440
                info += "<dt>map width, height:<dt><dd>" + mapContainerElement.width() +  ", " + mapContainerElement.height() + "</dd>";
441
                info += "<dt>map aspect ratio:<dt><dd>" + mapContainerElement.width() / mapContainerElement.height() + "</dd>";
442
                if(map.getExtent() != null){
443
                  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>";
444
                  info += "<dt>map maxExtent bbox:<dt><dd>" + map.getMaxExtent().toBBOX() + "</dd>";
445
                  info += "<dt>baselayer extent bbox:<dt><dd class=\"baselayer-extent-bbox\">" +  map.baseLayer.getExtent().toBBOX() + ", <strong>degree:</strong> <span class=\"degree-value\">"
446
                    + map.baseLayer.getExtent().clone().transform(map.baseLayer.projection, CdmOpenLayers.projections.epsg_4326) + "</span></dd>"
447
                  info += "<dt>baselayer projection:<dt><dd>" + map.baseLayer.projection.getCode() + "</dd>";
448
                }
449
            } else {
450
                info += "<dt>bbox:<dt><dd>" + (mapExtendDegree != null ? mapExtendDegree.toBBOX() : 'NULL') + "</dd>";
451
            }
452
            info += "</dl>";
453

    
454
            if(infoElement == null){
455
                infoElement = jQuery('<div class="map_info"></div>');
456
                mapElement.parent().after(infoElement);
457
            }
458
            infoElement.html(info);
459
        };
460

    
461
        /**
462
         * Initialize the Openlayers Map with the base layer
463
         */
464
        var initMap = function(){
465

    
466
          if(opts.showLayerSwitcher === true){
467
              defaultControls.push(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
468
          }
469

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

    
472
//          var maxExtentByAspectRatio = cropBoundsToAspectRatio(defaultBaseLayer.maxExtent, getWidth/getHeight);
473
          var maxResolution = null;
474
          // gmaps has no maxExtent at this point, need to check for null
475
          if(defaultBaseLayer.maxExtent != null){
476
              maxResolution = Math[(opts.displayOutsideMaxExtent ? 'max' : 'min')](
477
                      defaultBaseLayer.maxExtent.getWidth() / getWidth(),
478
                      defaultBaseLayer.maxExtent.getHeight() / getHeight()
479
              );
480
          }
481
          console.log("mapOptions.maxResolution: " + maxResolution);
482
          console.log("mapOptions.restrictedExtent: " + defaultBaseLayer.maxExtent);
483

    
484
          map = new OpenLayers.Map(
485
            mapElement.attr('id'),
486
            {
487
              // defines the map ui elements and interaction features
488
              controls: defaultControls,
489

    
490
              // maxResolution determines the lowest zoom level and thus places the map
491
              // in its maximum extent into the available view port so that no additinal
492
              // gutter is visible and no parts of the map are hidden
493
              // see http://trac.osgeo.org/openlayers/wiki/SettingZoomLevels
494
              // IMPORTANT!!!
495
              // the maxResulution set here will be overwritten if the baselayers maxResolution
496
              // it is set
497
              maxResolution: maxResolution,
498

    
499
              // setting restrictedExtent the the maxExtent prevents from panning the
500
              // map out of its bounds
501
              restrictedExtent: defaultBaseLayer.maxExtent,
502
//                      maxExtent: defaultBaseLayer.maxExtent,
503

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

    
511
              eventListeners: opts.eventListeners,
512
              // creating the map with a null theme, since we include the stylesheet directly in the page
513
              theme: null
514

    
515
            }
516
          );
517

    
518
          //add the base layers
519

    
520
          addLayers(baseLayers);
521
          map.setBaseLayer(defaultBaseLayer);
522

    
523
          // calculate the bounds to zoom to
524
          zoomToBounds = zoomToBoundsFor(opts.boundingBox ? opts.boundingBox : defaultBaseLayerBoundingBox, defaultBaseLayer);
525
          zoomToBounds = cropBoundsToAspectRatio(zoomToBounds, map.getSize().w / map.getSize().h);
526
          console.log("baselayer zoomToBounds: " + zoomToBounds);
527

    
528
        };
529

    
530
        var addLayers = function(layers){
531

    
532
          layers.forEach(function(layer){
533
            // layer.setVisibility(false);
534
          });
535

    
536
          map.addLayers(layers);
537
        };
538

    
539
        /**
540
         * add a distribution or occurrence layer
541
         *
542
         * @param mapResponseObj
543
         *   The reponse object returned by the edit map service
544
         * @param dataType
545
         *   either "AREA" or "POINT"
546
         */
547
        var createDataLayer = function(mapResponseObj, dataType){
548

    
549
          console.log("creating data layer of type " + dataType);
550

    
551
          dataLayerOptions = makeWMSLayerOptions();
552
          dataLayerOptions.displayOutsideMaxExtent = true; // move into makeWMSLayerOptions?
553

    
554
          var layers = [];
555
          // add additional layers, get them from the mapResponseObj
556
          if(mapResponseObj !== undefined){
557
            if(dataType === "POINT" && mapResponseObj.points_sld !== undefined){
558
              var pointLayer;
559
              // it is a response for an point map
560
              var geoserverUri;
561
              if(mapResponseObj.geoserver) {
562
                  geoserverUri = mapResponseObj.geoserver;
563
              } else {
564
                  // it is an old service which is not providing the corresponding geoserver URI, so we guess it
565
                  geoserverUri = mapserverBaseUrl + "/geoserver/wms";
566
              }
567

    
568
              //TODO points_sld should be renamed to sld in response + fill path to sld should be given
569
              pointLayer = new OpenLayers.Layer.WMS(
570
                'points',
571
                geoserverUri,
572
                {
573
                    layers: 'topp:rest_points',
574
                    transparent:"true",
575
                    format:"image/png"
576
                },
577
                dataLayerOptions
578
              );
579

    
580
              var sld = mapResponseObj.points_sld;
581
              if(sld.indexOf("http://") !== 0){
582
                  // it is an old servive which is not providing the full sdl URI, so we guess it
583
                  //  http://edit.africamuseum.be/synthesys/www/v1/sld/
584
                  //  http://edit.br.fgov.be/synthesys/www/v1/sld/
585
                  sld =  mapserverBaseUrl + "/synthesys/www/v1/sld/" + sld;
586
              }
587
              pointLayer.params.SLD = sld;
588

    
589
              layers.push(pointLayer);
590
            } else {
591
              // it is a response from for a distribution map
592
              console.log("start with adding distribution layers :");
593
              for ( var i in mapResponseObj.layers) {
594
                var layerData = mapResponseObj.layers[i];
595

    
596
                console.log(" " + i +" -> " + layerData.tdwg);
597
                var layer = new OpenLayers.Layer.WMS(
598
                  layerData.tdwg,
599
                  mapResponseObj.geoserver + "/wms",
600
                  {
601
                      layers: layerByNameMap[layerData.tdwg],
602
                      transparent:"true",
603
                      format:"image/png"
604
                  },
605
                  dataLayerOptions
606
                  );
607
                layer.params.SLD = layerData.sld;
608
                layer.setOpacity(opts.distributionOpacity);
609

    
610
                layers.push(layer);
611
              }
612
            }
613

    
614
            if(layers.length > 0) {
615
              // calculate zoomBounds using the first layer
616
              if(mapResponseObj.bbox !== undefined){
617
                // mapResponseObj.bbox are bounds for the projection of the specific layer
618
                var newBounds =  OpenLayers.Bounds.fromString( mapResponseObj.bbox );
619
                newBounds.transform(layers[0].projection, map.getProjectionObject());
620
                if(dataBounds !== null){
621
                  dataBounds.extend(newBounds);
622
                } else if(newBounds !== undefined){
623
                  dataBounds = newBounds;
624
                }
625

    
626
                zoomToBounds = dataBounds;
627
                console.log("data layer zoomToBounds: " + zoomToBounds);
628
                zoomToClosestLevel = false;
629
              }
630
            }
631

    
632

    
633

    
634
            if(legendImgSrc != null && opts.legendPosition !== undefined && mapResponseObj.legend !== undefined){
635
                var legendSrcUrl = mapResponseObj.geoserver + legendImgSrc + mapResponseObj.legend;
636
                addLegendAsElement(legendSrcUrl);
637
                //addLegendAsLayer(legendSrcUrl, map);
638
            }
639

    
640
            return layers;
641
          }
642

    
643
        };
644

    
645
        /**
646
         *
647
         */
648
        var addLegendAsElement= function(legendSrcUrl){
649

    
650
            var legendElement = jQuery('<div class="openlayers_legend"></div>');
651
            var legendImage = jQuery('<img src="' + legendSrcUrl + '"/>');
652
            legendElement
653
                .css('opacity', opts.legendOpacity)
654
                .css('position', 'relative')
655
                .css('z-index', '1002')
656
                .css('top', -mapElement.height());
657
            legendImage.load(function () {
658
                jQuery(this).parent()
659
                    .css('left', getWidth() - jQuery(this).width())
660
                    .width(jQuery(this).width());
661
                // reset height to original value
662
                adjustHeight();
663
            });
664
            legendElement.html(legendImage);
665
            mapElement.after(legendElement);
666
        };
667

    
668
         var adjustLegendAsElementPosition = function (){
669
           var legendContainer = mapContainerElement.children('.openlayers_legend');
670
           var legendImage = legendContainer.children('img');
671
           legendContainer.css('top', -mapElement.height())
672
             .css('left', getWidth() - legendImage.width());
673
         };
674

    
675

    
676
        var addLegendAsLayer= function(legendSrcUrl, map){
677
            var w, h;
678

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

    
683
                w = mapElement.next('.openlayers_legend').find('img').width();
684
                h = mapElement.next('.openlayers_legend').find('img').height();
685
                mapElement.next('.openlayers_legend').remove();
686

    
687
//              createLegendLayer();
688
//              // 2. create the Legend Layer
689
                //TODO createLegendLayer as inner function seems like an error
690
//              var createLegendLayer = function(){
691
                //
692
                //
693
//              var legendLayerOptions={
694
//              maxResolution: '.$maxRes.',
695
//              maxExtent: new OpenLayers.Bounds(0, 0, w, h)
696
//              };
697
                //
698
//              var legendLayer = new OpenLayers.Layer.Image(
699
//              'Legend',
700
//              legendSrcUrl,
701
//              new OpenLayers.Bounds(0, 0, w, h),
702
//              new OpenLayers.Size(w, h),
703
//              imageLayerOptions);
704
//              };
705
            });
706

    
707

    
708
        };
709

    
710
        /**
711
         * merge 2 Url query strings
712
         */
713
        var mergeQueryStrings = function(queryStr1, queryStr2){
714
            if(queryStr1.charAt(queryStr1.length - 1) != '&'){
715
                queryStr1 += '&';
716
            }
717
            if(queryStr2.charAt(0) == '&'){
718
                return queryStr1 + queryStr2.substr(1);
719
            } else {
720
                return queryStr1 + queryStr2;
721
            }
722

    
723
        };
724

    
725
        /**
726
         *
727
         */
728
        var createBaseLayers = function( baseLayerNames, defaultBaseLayerName, customWMSBaseLayerData){
729

    
730
            for(var i = 0; i <  baseLayerNames.length; i++) {
731
                // create the layer
732
                if (baseLayerNames[i] === "custom_wms_base_layer_1"){
733
                    wmsBaseLayer =createWMSLayer(
734
                            customWMSBaseLayerData.name,
735
                            customWMSBaseLayerData.url,
736
                            customWMSBaseLayerData.params,
737
                            customWMSBaseLayerData.projection,
738
                            customWMSBaseLayerData.proj4js_def,
739
                            customWMSBaseLayerData.units,
740
                            customWMSBaseLayerData.max_extent
741
                    );
742
                  wmsBaseLayer.setIsBaseLayer(true);
743
                  baseLayers[i] = wmsBaseLayer;
744
                } else {
745
                    baseLayers[i] = window.CdmOpenLayers.getLayerByName(baseLayerNames[i]);
746
                }
747
                // set default baselayer
748
                if(baseLayerNames[i] === defaultBaseLayerName){
749
                    defaultBaseLayer = baseLayers[i];
750
                }
751

    
752
            }
753
        };
754

    
755
        /**
756
         * returns the intersection of the bounds b1 and b2.
757
         * The b1 and b2 do not intersect b1 will be returned.
758
         *
759
         * @param OpenLayers.Bounds b1
760
         * @param OpenLayers.Bounds b2
761
         *
762
         * @return the bounds of the intersection between both rectangles
763
         */
764
        var intersectionOfBounds = function (b1, b2){
765

    
766
            if(b1.intersectsBounds(b2)){
767

    
768
                var left = Math.max(b1.left, b2.left);
769
                var bottom = Math.max(b1.bottom, b2.bottom);
770
                var right = Math.min(b1.right, b2.right);
771
                var top = Math.min(b1.top, b2.top);
772

    
773
                return new OpenLayers.Bounds(left, bottom, right, top);
774

    
775
            } else {
776
                return b1;
777
            }
778
        };
779

    
780
        /**
781
         *
782
         * @param OpenLayers.Bounds b
783
         * @param float aspectRatio width/height
784
         *
785
         * @return the bounds cropped to the given aspectRatio
786
         */
787
        var cropBoundsToAspectRatio = function (b, aspectRatio){
788

    
789
            var cropedB = b.clone();
790

    
791
            if(aspectRatio == 1){
792
                return cropedB;
793
            }
794

    
795
            /*
796
             * LonLat:
797
             *   lon {Float} The x-axis coodinate in map units
798
             *   lat {Float} The y-axis coordinate in map units
799
             */
800
            var center = cropedB.getCenterLonLat();
801
            if(aspectRatio < 1){
802
                var dist = (b.getHeight() / 2) * aspectRatio;
803
                cropedB.top = center.lat + dist;
804
                cropedB.cropedBottom = center.lat - dist;
805
            } else if(aspectRatio > 1){
806
                var dist = (b.getWidth() / 2) / aspectRatio;
807
                cropedB.left = center.lon - dist;
808
                cropedB.right = center.lon + dist;
809
            }
810
            return cropedB;
811
        };
812

    
813
        /**
814
         * returns the version number contained in the version string:
815
         *   v1.1 --> 1.1
816
         *   v1.2_dev --> 1.2
817
         */
818
        var mapServerVersionNumber = function() {
819
            var pattern = /v([\d\.]+).*$/;
820
            var result;
821
            if (result = mapserverVersion.match(pattern) !== null) {
822
                return result[0];
823
            } else {
824
                return null;
825
            }
826
        };
827

    
828

    
829

    
830
      /**
831
       * returns the zoom to bounds.
832
       *
833
       * NOTE: only used for the base layer
834
       *
835
       * @param bboxString
836
       *     a string representation of the bounds in degree for epsg_4326
837
       * @param layer
838
       *     the Openlayers.Layer
839
       *
840
       * @return the bboxstring projected onto the layer and intersected with the maximum extent of the layer
841
       */
842
      var zoomToBoundsFor = function(bboxString, layer){
843
        var zoomToBounds;
844
        if(bboxString) {
845
          zoomToBounds = OpenLayers.Bounds.fromString(bboxString);
846
          // transform bounding box given in degree values to the projection of the base layer
847
          zoomToBounds.transform(CdmOpenLayers.projections.epsg_4326, layer.projection);
848
        } else if(layer.maxExtent) {
849
          zoomToBounds = layer.maxExtent;
850
          // no need to transform since the bounds are obtained from the layer
851
        } else {
852
          zoomToBounds = new OpenLayers.Bounds(-180, -90, 180, 90);
853
          // transform bounding box given in degree values to the projection of the base layer
854
          zoomToBounds.transform(CdmOpenLayers.projections.epsg_4326, layer.projection);
855
        }
856

    
857
        zoomToBounds = intersectionOfBounds(layer.maxExtent, zoomToBounds);
858

    
859
        return zoomToBounds;
860
      };
861

    
862
      var log = function(message, addTimeStamp){
863
        var timestamp = '';
864
        if(addTimeStamp == true){
865
          var time = new Date();
866
          timestamp = time.getSeconds() + '.' + time.getMilliseconds() + 's';
867
        }
868
        console.log(timestamp + message);
869
      };
870

    
871
      var makeWMSLayerOptions = function(projection, proj4js_def, maxExtent, units){
872
        wmsOptions = {
873
          isBaseLayer: false,
874
          displayInLayerSwitcher: true
875
        };
876

    
877
        if (projection) {
878
          if (proj4js_def) {
879
            // in case projection has been defined for the layer and if there is also
880
            // a Proj4js.defs, add it!
881
            Proj4js.defs[projection] = proj4js_def;
882
          }
883
          wmsOptions.projection = projection;
884
          if (maxExtent === null) {
885
            maxExtent = CdmOpenLayers.mapExtends.epsg_4326.clone();
886
            maxExtent.transform(CdmOpenLayers.projections.epsg_4326, projection);
887
          }
888
        } else {
889
          // use the projection and maxextent of the base layer
890
          maxExtent = map.baseLayer.maxExtent;
891
        }
892

    
893
        if (maxExtent) {
894
          wmsOptions.maxExtent = maxExtent;
895
        }
896

    
897
        if (units) {
898
          wmsOptions.units = units;
899
        }
900
        return wmsOptions;
901
      };
902

    
903
      /**
904
       * Creates a WMS Base layer
905
       * @param String name
906
       *     A name for the layer
907
       * @param String url
908
       *     Base url for the WMS (e.g.  http://wms.jpl.nasa.gov/wms.cgi)
909
       * @param Object params
910
       *     An object with key/value pairs representing the GetMap query string parameters and parameter values.
911
       * @param Object projection
912
       *    A OpenLayers.Projection object
913
       */
914
      var createWMSLayer= function(name, url, params, projection, proj4js_def, units, maxExtent){
915

    
916
        console.log("creating WMS Layer " + name);
917

    
918
        wmsOptions = makeWMSLayerOptions(projection, proj4js_def, maxExtent, units);
919

    
920
        wmsLayer = new OpenLayers.Layer.WMS(
921
            name,
922
            url,
923
            params,
924
            wmsOptions
925
          );
926

    
927
          if(wmsLayer === null){
928
            console.log("Error creating WMS Layer");
929
          }
930

    
931
          return  wmsLayer;
932
        };
933

    
934
        var layerLoadingControl = function() {
935

    
936
          var control = new OpenLayers.Control();
937

    
938
          OpenLayers.Util.extend(control, {
939

    
940
            LAYERS_LOADING: 0,
941

    
942
            updateState: function () {
943
              if(this.div != null){
944
                if (this.LAYERS_LOADING > 0) {
945
                  this.div.style.display = "block";
946
                } else {
947
                  this.div.style.display = "none";
948
                }
949
              }
950
            },
951

    
952
            updateSize: function () {
953
              this.div.style.width = this.map.size.w + "px";
954
              this.div.style.height = this.map.size.h  + "px";
955
              this.div.style.textAlign = "center";
956
              this.div.style.lineHeight = this.map.size.h  + "px";
957
            },
958

    
959
            counterIncrease: function (layer) {
960
              this.control.LAYERS_LOADING++;
961
              log(' > loading start : ' + this.layer.name + ' ' + this.control.LAYERS_LOADING, true);
962
              this.control.updateState();
963
            },
964

    
965
            counterDecrease: function (layer) {
966
              this.control.LAYERS_LOADING--;
967
              log(' > loading end : ' + this.layer.name + ' ' + this.control.LAYERS_LOADING, true);
968
              this.control.updateState();
969
            },
970

    
971
            draw: function () {
972

    
973
              // call the default draw function to initialize this.div
974
              OpenLayers.Control.prototype.draw.apply(this, arguments);
975

    
976
              this.map.events.register('updatesize', this, function(e){
977
                  this.updateSize();
978
                }
979
              );
980

    
981
              var loadingIcon = document.createElement("i");
982
              var fa_class = document.createAttribute("class");
983
              // fa-circle-o-notch fa-spin
984
              // fa-spinner fa-pulse
985
              // fa-refresh
986
              fa_class.value = "fa fa-refresh fa-spin fa-5x";
987
              loadingIcon.attributes.setNamedItem(fa_class);
988

    
989
              this.updateSize();
990

    
991
              this.div.appendChild(loadingIcon);
992

    
993
              this.registerEvents();
994

    
995
              return this.div;
996
            },
997

    
998
            registerEvents: function() {
999

    
1000
              this.map.events.register('preaddlayer', this, function(e){
1001
                console.log(" > preaddlayer " + e.layer.name);
1002
                e.layer.events.register('loadstart', {control: this, layer: e.layer}, this.counterIncrease);
1003
                e.layer.events.register('loadend', {control: this, layer: e.layer}, this.counterDecrease);
1004
              });
1005
            }
1006

    
1007
          });
1008

    
1009
          return control;
1010
        }
1011

    
1012
    }; // end of CdmOpenLayers.Map
1013
})();
1014

    
1015

    
1016

    
1017

    
1018

    
1019

    
1020

    
1021

    
1022

    
(2-2/2)