Project

General

Profile

Download (37.2 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: 15,
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
                //  Spherical Mercator epsg_900913 is not suppporting the whole marble
99
                epsg_900913: new OpenLayers.Bounds(-179, -85, 179, 85),
100
                //  Spherical Mercator
101
                epsg_3857: new OpenLayers.Bounds(-179, -85, 179, 85)
102
        };
103
        // transform epsg_900913 to units meter
104
        mapExtends.epsg_900913.transform(projections.epsg_4326, projections.epsg_900913);
105
        mapExtends.epsg_3857.transform(projections.epsg_4326, projections.epsg_3857);
106

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

    
115
    })(); // end of namespace definition for CdmOpenLayers
116

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

    
127
      var mapServicePath = '/edit_wp5';
128

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

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

    
141

    
142
      var legendImgSrc = null;
143

    
144
      var map = null;
145

    
146
      var infoElement = null;
147

    
148
      var baseLayers = [];
149

    
150
      var defaultBaseLayer = null;
151

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

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

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

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

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

    
201
      var zoomToClosestLevel = true;
202

    
203
      var LAYER_DATA_CNT = 0;
204

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

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

    
219

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

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

    
237
        /**
238
         *
239
         */
240
        this.create = function(){ // public function
241

    
242
          // set the height of the container element
243
          adjustHeight();
244

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

    
251
          createBaseLayers(opts.baseLayerNames, opts.defaultBaseLayerName, opts.customWMSBaseLayerData);
252

    
253
          initializeMap();
254

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

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

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

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

    
280
            mapServiceRequest = mapserverBaseUrl + mapServicePath + '/' + mapserverVersion + '/rest_gen.php?' + distributionQuery;
281

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

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

    
302

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

    
312
            mapServiceRequest = mapserverBaseUrl + mapServicePath + '/' + mapserverVersion + '/rest_gen.php?' + occurrenceQuery;
313

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

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

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

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

    
354
          log("Map viewer creation complete.");
355

    
356
        };
357

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

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

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

    
375

    
376
          if(map.getZoom() > opts.maxZoom){
377
            map.zoomTo(opts.maxZoom);
378
          } else if(map.getZoom() < opts.minZoom){
379
            map.zoomTo(opts.minZoom);
380
          }
381

    
382
          // make sure the wmsOverlay is still on top
383
          if(wmsOverlay){
384
            map.setLayerIndex(wmsOverlay, 100);
385
          }
386

    
387
          log(" > zoomToExtend done", true);
388
        };
389

    
390
      /**
391
       * Returns  the projection of the defaultBaseLayer which is the
392
       * the projection to which all other layers and locations must be transformed.
393
       */
394
      var referenceProjection = function() {
395
        if(defaultBaseLayer){
396
          return defaultBaseLayer.projection;
397
        } else {
398
          log("Error - referenceProjection() defaultBaseLayer not set");
399
          return null;
400
        }
401
      };
402

    
403
      /**
404
       * Returns the maxExtent of the defaultBaseLayer.
405
       */
406
      var referenceMaxExtent = function() {
407
        if(defaultBaseLayer){
408
          return defaultBaseLayer.maxExtent;
409
        } else {
410
          log("Error - referenceMaxExtent() defaultBaseLayer not set");
411
          return null;
412
        }
413
      };
414

    
415
        var getHeight = function(){
416
          return mapContainerElement.width() / opts.aspectRatio;
417
        };
418

    
419
        var getWidth = function(){
420
          return mapContainerElement.width();
421
        };
422

    
423
        var adjustHeight = function() {
424
          mapContainerElement.css("height", getHeight());
425
        };
426

    
427
        /**
428
         * public function
429
         */
430
        this.registerEvents = function(events){
431
            for (var key in events) {
432
                if (events.hasOwnProperty(key)) {
433
                    map.events.register(key, map , events[key]);
434
                }
435
            }
436
        };
437

    
438

    
439
        /**
440
         * public function
441
         */
442
        this.getMap = function(){
443
            return map;
444
        };
445

    
446
        /**
447
         * Prints info on the current map into the jQuery element
448
         * as set in the options (opts.infoElement)
449
         * public function
450
         *
451
         */
452
        this.printInfo = function(){
453

    
454

    
455
            var mapExtendDegree = null;
456
            if(map.getExtent() != null){
457
              // If the baselayer is not yet set, getExtent() returns null.
458
              mapExtendDegree = map.getExtent().clone();
459
              mapExtendDegree.transform(map.baseLayer.projection, CdmOpenLayers.projections.epsg_4326);
460
            }
461

    
462
            var info = "<dl>";
463
            info += "<dt>zoom:<dt><dd>" + map.getZoom() + "</dd>";
464
            if(opts.debug){
465
                info += "<dt>map resolution:<dt><dd>" + map.getResolution() + "</dd>";
466
                info += "<dt>map max resolution:<dt><dd>" + map.getMaxResolution() + "</dd>";
467
                info += "<dt>map scale:<dt><dd>" + map.getScale() + "</dd>";
468
                info += "<dt>map width, height:<dt><dd>" + mapContainerElement.width() +  ", " + mapContainerElement.height() + "</dd>";
469
                info += "<dt>map aspect ratio:<dt><dd>" + mapContainerElement.width() / mapContainerElement.height() + "</dd>";
470
                if(map.getExtent() != null){
471
                  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>";
472
                  info += "<dt>map maxExtent bbox:<dt><dd>" + map.getMaxExtent().toBBOX() + "</dd>";
473
                  info += "<dt>baselayer extent bbox:<dt><dd class=\"baselayer-extent-bbox\">" +  map.baseLayer.getExtent().toBBOX() + ", <strong>degree:</strong> <span class=\"degree-value\">"
474
                    + map.baseLayer.getExtent().clone().transform(map.baseLayer.projection, CdmOpenLayers.projections.epsg_4326) + "</span></dd>"
475
                  info += "<dt>baselayer projection:<dt><dd>" + map.baseLayer.projection.getCode() + "</dd>";
476
                }
477
            } else {
478
                info += "<dt>bbox:<dt><dd>" + (mapExtendDegree !== null ? mapExtendDegree.toBBOX() : 'NULL') + "</dd>";
479
            }
480
            info += "</dl>";
481

    
482
            if(infoElement === null){
483
                infoElement = jQuery('<div class="map_info"></div>');
484
                mapElement.parent().after(infoElement);
485
            }
486
            infoElement.html(info);
487
        };
488

    
489
        /**
490
         * Initialize the Openlayers Map with the base layer
491
         */
492
        var initializeMap = function(){
493

    
494
          if(opts.showLayerSwitcher === true){
495
              defaultControls.push(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
496
          }
497

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

    
500
//          var maxExtentByAspectRatio = cropBoundsToAspectRatio(defaultBaseLayer.maxExtent, getWidth/getHeight);
501
          var maxResolution = null;
502
          // gmaps has no maxExtent at this point, need to check for null
503
          if(referenceMaxExtent() !== null){
504
              maxResolution = Math[(opts.displayOutsideMaxExtent ? 'max' : 'min')](
505
                referenceMaxExtent().getWidth() / getWidth(),
506
                referenceMaxExtent().getHeight() / getHeight()
507
              );
508
          }
509
          console.log("mapOptions.maxResolution: " + maxResolution);
510
          console.log("mapOptions.restrictedExtent: " + referenceMaxExtent());
511

    
512
          map = new OpenLayers.Map(
513
            mapElement.attr('id'),
514
            {
515
              // defines the map ui elements and interaction features
516
              controls: defaultControls,
517

    
518
              // maxResolution determines the lowest zoom level and thus places the map
519
              // in its maximum extent into the available view port so that no additinal
520
              // gutter is visible and no parts of the map are hidden
521
              // see http://trac.osgeo.org/openlayers/wiki/SettingZoomLevels
522
              // IMPORTANT!!!
523
              // the maxResulution set here will be overwritten if the baselayers maxResolution
524
              // it is set
525
              maxResolution: maxResolution,
526

    
527
              // setting restrictedExtent the the maxExtent prevents from panning the
528
              // map out of its bounds
529
              restrictedExtent: referenceMaxExtent(),
530
//                      maxExtent: referenceMaxExtent(),
531

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

    
539
              eventListeners: opts.eventListeners,
540
              // creating the map with a null theme, since we include the stylesheet directly in the page
541
              theme: null
542

    
543
            }
544
          );
545

    
546
          //add the base layers
547

    
548
          addLayers(baseLayers);
549
          map.setBaseLayer(defaultBaseLayer);
550

    
551
          // calculate the bounds to zoom to
552
          zoomToBounds = calculateZoomToBounds(opts.boundingBox ? opts.boundingBox : defaultBaseLayerBoundingBox);
553
          // zoomToBounds = cropBoundsToAspectRatio(zoomToBounds, map.getSize().w / map.getSize().h);
554
          console.log("baselayer zoomToBounds: " + zoomToBounds);
555

    
556
        };
557

    
558
        var addLayers = function(layers){
559

    
560
          layers.forEach(function(layer){
561
            // layer.setVisibility(false);
562
          });
563

    
564
          map.addLayers(layers);
565
        };
566

    
567
        /**
568
         * add a distribution or occurrence layer
569
         *
570
         * @param mapResponseObj
571
         *   The reponse object returned by the edit map service
572
         * @param dataType
573
         *   either "AREA" or "POINT"
574
         */
575
        var createDataLayer = function(mapResponseObj, dataType){
576

    
577
          console.log("creating data layer of type " + dataType);
578

    
579
          dataLayerOptions = makeWMSLayerOptions();
580
          dataLayerOptions.displayOutsideMaxExtent = true; // move into makeWMSLayerOptions?
581

    
582
          var layers = [];
583
          // add additional layers, get them from the mapResponseObj
584
          if(mapResponseObj !== undefined){
585
            if(dataType === "POINT" && mapResponseObj.points_sld !== undefined){
586
              var pointLayer;
587
              // it is a response for an point map
588
              var geoserverUri;
589
              if(mapResponseObj.geoserver) {
590
                  geoserverUri = mapResponseObj.geoserver;
591
              } else {
592
                  // it is an old service which is not providing the corresponding geoserver URI, so we guess it
593
                  geoserverUri = mapserverBaseUrl + "/geoserver/wms";
594
              }
595

    
596
              //TODO points_sld should be renamed to sld in response + fill path to sld should be given
597
              pointLayer = new OpenLayers.Layer.WMS(
598
                'points',
599
                geoserverUri,
600
                {
601
                    layers: 'topp:rest_points',
602
                    transparent:"true",
603
                    format:"image/png"
604
                },
605
                dataLayerOptions
606
              );
607

    
608
              var sld = mapResponseObj.points_sld;
609
              if(sld.indexOf("http://") !== 0){
610
                  // it is an old servive which is not providing the full sdl URI, so we guess it
611
                  //  http://edit.africamuseum.be/synthesys/www/v1/sld/
612
                  //  http://edit.br.fgov.be/synthesys/www/v1/sld/
613
                  sld =  mapserverBaseUrl + "/synthesys/www/v1/sld/" + sld;
614
              }
615
              pointLayer.params.SLD = sld;
616

    
617
              layers.push(pointLayer);
618
            } else {
619
              // it is a response from for a distribution map
620
              console.log("start with adding distribution layers :");
621
              for ( var i in mapResponseObj.layers) {
622
                var layerData = mapResponseObj.layers[i];
623

    
624
                console.log(" " + i +" -> " + layerData.tdwg);
625
                var layer = new OpenLayers.Layer.WMS(
626
                  layerData.tdwg,
627
                  mapResponseObj.geoserver + "/wms",
628
                  {
629
                      layers: layerByNameMap[layerData.tdwg],
630
                      transparent:"true",
631
                      format:"image/png"
632
                  },
633
                  dataLayerOptions
634
                  );
635
                layer.params.SLD = layerData.sld;
636
                layer.setOpacity(opts.distributionOpacity);
637

    
638
                layers.push(layer);
639
              }
640
            }
641

    
642
            if(layers.length > 0) {
643
              // calculate zoomBounds using the first layer
644
              if(mapResponseObj.bbox !== undefined){
645
                // mapResponseObj.bbox are bounds for the projection of the specific layer
646
                var newBounds =  OpenLayers.Bounds.fromString( mapResponseObj.bbox );
647
                newBounds.transform(layers[0].projection, map.getProjectionObject());
648
                if(dataBounds !== null){
649
                  dataBounds.extend(newBounds);
650
                } else if(newBounds !== undefined){
651
                  dataBounds = newBounds;
652
                }
653

    
654
                zoomToBounds = dataBounds;
655
                console.log("data layer zoomToBounds: " + zoomToBounds);
656
                zoomToClosestLevel = false;
657
              }
658
            }
659

    
660

    
661

    
662
            if(legendImgSrc != null && opts.legendPosition !== undefined && mapResponseObj.legend !== undefined){
663
                var legendSrcUrl = mapResponseObj.geoserver + legendImgSrc + mapResponseObj.legend;
664
                addLegendAsElement(legendSrcUrl);
665
                //addLegendAsLayer(legendSrcUrl, map);
666
            }
667

    
668
            return layers;
669
          }
670

    
671
        };
672

    
673
        /**
674
         *
675
         */
676
        var addLegendAsElement= function(legendSrcUrl){
677

    
678
            var legendElement = jQuery('<div class="openlayers_legend"></div>');
679
            var legendImage = jQuery('<img src="' + legendSrcUrl + '"/>');
680
            legendElement
681
                .css('opacity', opts.legendOpacity)
682
                .css('position', 'relative')
683
                .css('z-index', '1002')
684
                .css('top', -mapElement.height());
685
            legendImage.load(function () {
686
                jQuery(this).parent()
687
                    .css('left', getWidth() - jQuery(this).width())
688
                    .width(jQuery(this).width());
689
                // reset height to original value
690
                adjustHeight();
691
            });
692
            legendElement.html(legendImage);
693
            mapElement.after(legendElement);
694
        };
695

    
696
         var adjustLegendAsElementPosition = function (){
697
           var legendContainer = mapContainerElement.children('.openlayers_legend');
698
           var legendImage = legendContainer.children('img');
699
           legendContainer.css('top', -mapElement.height())
700
             .css('left', getWidth() - legendImage.width());
701
         };
702

    
703

    
704
        var addLegendAsLayer= function(legendSrcUrl, map){
705
            var w, h;
706

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

    
711
                w = mapElement.next('.openlayers_legend').find('img').width();
712
                h = mapElement.next('.openlayers_legend').find('img').height();
713
                mapElement.next('.openlayers_legend').remove();
714

    
715
//              createLegendLayer();
716
//              // 2. create the Legend Layer
717
                //TODO createLegendLayer as inner function seems like an error
718
//              var createLegendLayer = function(){
719
                //
720
                //
721
//              var legendLayerOptions={
722
//              maxResolution: '.$maxRes.',
723
//              maxExtent: new OpenLayers.Bounds(0, 0, w, h)
724
//              };
725
                //
726
//              var legendLayer = new OpenLayers.Layer.Image(
727
//              'Legend',
728
//              legendSrcUrl,
729
//              new OpenLayers.Bounds(0, 0, w, h),
730
//              new OpenLayers.Size(w, h),
731
//              imageLayerOptions);
732
//              };
733
            });
734

    
735

    
736
        };
737

    
738
        /**
739
         * merge 2 Url query strings
740
         */
741
        var mergeQueryStrings = function(queryStr1, queryStr2){
742
            if(queryStr1.charAt(queryStr1.length - 1) != '&'){
743
                queryStr1 += '&';
744
            }
745
            if(queryStr2.charAt(0) == '&'){
746
                return queryStr1 + queryStr2.substr(1);
747
            } else {
748
                return queryStr1 + queryStr2;
749
            }
750

    
751
        };
752

    
753
        /**
754
         *
755
         */
756
        var createBaseLayers = function( baseLayerNames, defaultBaseLayerName, customWMSBaseLayerData){
757

    
758
            for(var i = 0; i <  baseLayerNames.length; i++) {
759
                // create the layer
760
                if (baseLayerNames[i] === "custom_wms_base_layer_1"){
761
                    wmsBaseLayer =createWMSLayer(
762
                            customWMSBaseLayerData.name,
763
                            customWMSBaseLayerData.url,
764
                            customWMSBaseLayerData.params,
765
                            customWMSBaseLayerData.projection,
766
                            customWMSBaseLayerData.proj4js_def,
767
                            customWMSBaseLayerData.units,
768
                            customWMSBaseLayerData.max_extent
769
                    );
770
                  wmsBaseLayer.setIsBaseLayer(true);
771
                  baseLayers[i] = wmsBaseLayer;
772
                } else {
773
                    baseLayers[i] = window.CdmOpenLayers.getLayerByName(baseLayerNames[i]);
774
                }
775
                // set default baselayer
776
                if(baseLayerNames[i] === defaultBaseLayerName){
777
                    defaultBaseLayer = baseLayers[i];
778
                }
779

    
780
            }
781
        };
782

    
783
        /**
784
         * returns the intersection of the bounds b1 and b2.
785
         * The b1 and b2 do not intersect b1 will be returned.
786
         *
787
         * @param OpenLayers.Bounds b1
788
         * @param OpenLayers.Bounds b2
789
         *
790
         * @return the bounds of the intersection between both rectangles
791
         */
792
        var intersectionOfBounds = function (b1, b2){
793

    
794
            if(b1.intersectsBounds(b2)){
795

    
796
                var left = Math.max(b1.left, b2.left);
797
                var bottom = Math.max(b1.bottom, b2.bottom);
798
                var right = Math.min(b1.right, b2.right);
799
                var top = Math.min(b1.top, b2.top);
800

    
801
                return new OpenLayers.Bounds(left, bottom, right, top);
802

    
803
            } else {
804
                return b1;
805
            }
806
        };
807

    
808
        /**
809
         *
810
         * @param b OpenLayers.Bounds to crop
811
         * @param aspectRatio as fraction of width/height as float value
812
         *
813
         * @return the bounds cropped to the given aspectRatio
814
         */
815
        var cropBoundsToAspectRatio = function (b, aspectRatio){
816

    
817
            var cropedB = b.clone();
818

    
819
            if(aspectRatio === 1){
820
                return cropedB;
821
            }
822

    
823
            /*
824
             * LonLat:
825
             *   lon {Float} The x-axis coordinate in map units
826
             *   lat {Float} The y-axis coordinate in map units
827
             */
828
            var center = cropedB.getCenterLonLat();
829
            var dist;
830
            if(aspectRatio < 1){
831
                dist = (b.getHeight() / 2) * aspectRatio;
832
                cropedB.top = center.lat + dist;
833
                cropedB.cropedBottom = center.lat - dist;
834
            } else if(aspectRatio > 1){
835
                dist = (b.getWidth() / 2) / aspectRatio;
836
                cropedB.left = center.lon - dist;
837
                cropedB.right = center.lon + dist;
838
            }
839
            return cropedB;
840
        };
841

    
842
        /**
843
         * returns the version number contained in the version string:
844
         *   v1.1 --> 1.1
845
         *   v1.2_dev --> 1.2
846
         */
847
        var mapServerVersionNumber = function() {
848
            var pattern = /v([\d\.]+).*$/;
849
            var result;
850
            if (result = mapserverVersion.match(pattern) !== null) {
851
                return result[0];
852
            } else {
853
                return null;
854
            }
855
        };
856

    
857

    
858

    
859
      /**
860
       * returns the zoom to bounds.
861
       *
862
       * @param bboxString
863
       *     a string representation of the bounds in degree for epsg_4326
864
       *
865
       * @return the bboxstring projected onto the layer and intersected with the maximum extent of the layer
866
       */
867
      var calculateZoomToBounds = function(bboxString){
868
        var zoomToBounds;
869
        if(bboxString) {
870
          zoomToBounds = OpenLayers.Bounds.fromString(bboxString);
871
          if(referenceProjection().proj.projName){
872
            // SpericalMercator is not supporting the full extent -180,-90,180,90
873
            // crop if need to -179, -85, 179, 85
874
            if(zoomToBounds.left < -179){
875
              zoomToBounds.left =  -179;
876
            }
877
            if(zoomToBounds.bottom < -85){
878
              zoomToBounds.bottom =  -85;
879
            }
880
            if(zoomToBounds.right > 179){
881
              zoomToBounds.right =  179;
882
            }
883
            if(zoomToBounds.top > 85){
884
              zoomToBounds.top = 85;
885
            }
886
          }
887
          // transform bounding box given in degree values to the projection of the base layer
888
          zoomToBounds.transform(CdmOpenLayers.projections.epsg_4326, referenceProjection());
889
        } else if(referenceMaxExtent()) {
890
          zoomToBounds = referenceMaxExtent();
891
          // no need to transform since the bounds are obtained from the layer
892
        } else {
893
          // use the more narrow bbox of the SphericalMercator to avoid reprojection problems
894
          // SpericalMercator is not supporting the full extent!
895
          zoomToBounds = CdmOpenLayers.mapExtends.epsg_900913;
896
          // transform bounding box given in degree values to the projection of the base layer
897
          zoomToBounds.transform(CdmOpenLayers.projections.epsg_4326, referenceProjection());
898
        }
899

    
900
        zoomToBounds = intersectionOfBounds(referenceMaxExtent(), zoomToBounds);
901

    
902
        log("zoomBounds calculated: " + zoomToBounds.toString());
903

    
904
        return zoomToBounds;
905
      };
906

    
907
      var log = function(message, addTimeStamp){
908
        var timestamp = '';
909
        if(addTimeStamp === true){
910
          var time = new Date();
911
          timestamp = time.getSeconds() + '.' + time.getMilliseconds() + 's';
912
        }
913
        console.log(timestamp + message);
914
      };
915

    
916
      var makeWMSLayerOptions = function(projection, proj4js_def, maxExtent, units){
917
        wmsOptions = {
918
          isBaseLayer: false,
919
          displayInLayerSwitcher: true
920
        };
921

    
922
        if (projection) {
923
          if (proj4js_def) {
924
            // in case projection has been defined for the layer and if there is also
925
            // a Proj4js.defs, add it!
926
            Proj4js.defs[projection] = proj4js_def;
927
          }
928
          wmsOptions.projection = projection;
929
          if (maxExtent === null) {
930
            maxExtent = CdmOpenLayers.mapExtends.epsg_4326.clone();
931
            maxExtent.transform(CdmOpenLayers.projections.epsg_4326, projection);
932
          }
933
        } else {
934
          // use the projection and maxextent of the base layer
935
          maxExtent = referenceMaxExtent();
936
        }
937

    
938
        if (maxExtent) {
939
          wmsOptions.maxExtent = maxExtent;
940
        }
941

    
942
        if (units) {
943
          wmsOptions.units = units;
944
        }
945
        return wmsOptions;
946
      };
947

    
948
      /**
949
       * Creates a WMS Base layer
950
       * @param String name
951
       *     A name for the layer
952
       * @param String url
953
       *     Base url for the WMS (e.g.  http://wms.jpl.nasa.gov/wms.cgi)
954
       * @param Object params
955
       *     An object with key/value pairs representing the GetMap query string parameters and parameter values.
956
       * @param Object projection
957
       *    A OpenLayers.Projection object
958
       */
959
      var createWMSLayer= function(name, url, params, projection, proj4js_def, units, maxExtent){
960

    
961
        console.log("creating WMS Layer " + name);
962

    
963
        wmsOptions = makeWMSLayerOptions(projection, proj4js_def, maxExtent, units);
964

    
965
        wmsLayer = new OpenLayers.Layer.WMS(
966
            name,
967
            url,
968
            params,
969
            wmsOptions
970
          );
971

    
972
          if(wmsLayer === null){
973
            console.log("Error creating WMS Layer");
974
          }
975

    
976
          return  wmsLayer;
977
        };
978

    
979
        var layerLoadingControl = function() {
980

    
981
          var control = new OpenLayers.Control();
982

    
983
          OpenLayers.Util.extend(control, {
984

    
985
            LAYERS_LOADING: 0,
986

    
987
            updateState: function () {
988
              if(this.div != null){
989
                if (this.LAYERS_LOADING > 0) {
990
                  this.div.style.display = "block";
991
                } else {
992
                  this.div.style.display = "none";
993
                }
994
              }
995
            },
996

    
997
            updateSize: function () {
998
              this.div.style.width = this.map.size.w + "px";
999
              this.div.style.height = this.map.size.h  + "px";
1000
              this.div.style.textAlign = "center";
1001
              this.div.style.lineHeight = this.map.size.h  + "px";
1002
            },
1003

    
1004
            counterIncrease: function (layer) {
1005
              this.control.LAYERS_LOADING++;
1006
              log(' > loading start : ' + this.layer.name + ' ' + this.control.LAYERS_LOADING, true);
1007
              this.control.updateState();
1008
            },
1009

    
1010
            counterDecrease: function (layer) {
1011
              this.control.LAYERS_LOADING--;
1012
              log(' > loading end : ' + this.layer.name + ' ' + this.control.LAYERS_LOADING, true);
1013
              this.control.updateState();
1014
            },
1015

    
1016
            draw: function () {
1017

    
1018
              // call the default draw function to initialize this.div
1019
              OpenLayers.Control.prototype.draw.apply(this, arguments);
1020

    
1021
              this.map.events.register('updatesize', this, function(e){
1022
                  this.updateSize();
1023
                }
1024
              );
1025

    
1026
              var loadingIcon = document.createElement("i");
1027
              var fa_class = document.createAttribute("class");
1028
              // fa-circle-o-notch fa-spin
1029
              // fa-spinner fa-pulse
1030
              // fa-refresh
1031
              fa_class.value = "fa fa-refresh fa-spin fa-5x";
1032
              loadingIcon.attributes.setNamedItem(fa_class);
1033

    
1034
              this.updateSize();
1035

    
1036
              this.div.appendChild(loadingIcon);
1037

    
1038
              this.registerEvents();
1039

    
1040
              return this.div;
1041
            },
1042

    
1043
            registerEvents: function() {
1044

    
1045
              this.map.events.register('preaddlayer', this, function(e){
1046
                console.log(" > preaddlayer " + e.layer.name);
1047
                e.layer.events.register('loadstart', {control: this, layer: e.layer}, this.counterIncrease);
1048
                e.layer.events.register('loadend', {control: this, layer: e.layer}, this.counterDecrease);
1049
              });
1050
            }
1051

    
1052
          });
1053

    
1054
          return control;
1055
        }
1056

    
1057
    }; // end of CdmOpenLayers.Map
1058
})();
1059

    
1060

    
1061

    
1062

    
1063

    
1064

    
1065

    
1066

    
1067

    
(2-2/2)