1// Source: https://github.com/JasonSanford/GeoJSON-to-Google-Maps 2var GeoJSON = function( geojson, options ){ 3 var _geometryToGoogleMaps = function( geojsonGeometry, opts, geojsonProperties ){ 4 5 var googleObj; 6 7 switch ( geojsonGeometry.type ){ 8 case "Point": 9 opts.position = new google.maps.LatLng(geojsonGeometry.coordinates[1], geojsonGeometry.coordinates[0]); 10 var bounds = new google.maps.LatLngBounds(); 11 bounds.extend(opts.position); 12 googleObj = new google.maps.Marker(opts); 13 googleObj.set('bounds', bounds); 14 if (geojsonProperties) { 15 googleObj.set("geojsonProperties", geojsonProperties); 16 } 17 break; 18 19 case "MultiPoint": 20 googleObj = []; 21 var bounds = new google.maps.LatLngBounds(); 22 for (var i = 0; i < geojsonGeometry.coordinates.length; i++){ 23 opts.position = new google.maps.LatLng(geojsonGeometry.coordinates[i][1], geojsonGeometry.coordinates[i][0]); 24 bounds.extend(opts.position); 25 googleObj.push(new google.maps.Marker(opts)); 26 } 27 if (geojsonProperties) { 28 for (var k = 0; k < googleObj.length; k++){ 29 googleObj[k].set("geojsonProperties", geojsonProperties); 30 } 31 } 32 for (var k = 0; k < googleObj.length; k++) { 33 googleObj[k].set('bounds', bounds); 34 } 35 break; 36 37 case "LineString": 38 var path = []; 39 var bounds = new google.maps.LatLngBounds(); 40 for (var i = 0; i < geojsonGeometry.coordinates.length; i++){ 41 var coord = geojsonGeometry.coordinates[i]; 42 var ll = new google.maps.LatLng(coord[1], coord[0]); 43 bounds.extend(ll); 44 path.push(ll); 45 } 46 opts.path = path; 47 googleObj = new google.maps.Polyline(opts); 48 googleObj.set('bounds', bounds); 49 if (geojsonProperties) { 50 googleObj.set("geojsonProperties", geojsonProperties); 51 } 52 break; 53 54 case "MultiLineString": 55 googleObj = []; 56 var bounds = new google.maps.LatLngBounds(); 57 for (var i = 0; i < geojsonGeometry.coordinates.length; i++){ 58 var path = []; 59 for (var j = 0; j < geojsonGeometry.coordinates[i].length; j++){ 60 var coord = geojsonGeometry.coordinates[i][j]; 61 var ll = new google.maps.LatLng(coord[1], coord[0]); 62 bounds.extend(ll); 63 path.push(ll); 64 } 65 opts.path = path; 66 googleObj.push(new google.maps.Polyline(opts)); 67 } 68 if (geojsonProperties) { 69 for (var k = 0; k < googleObj.length; k++){ 70 googleObj[k].set("geojsonProperties", geojsonProperties); 71 } 72 } 73 for (var k = 0; k < googleObj.length; k++) { 74 googleObj[k].set('bounds', bounds); 75 } 76 break; 77 78 case "Polygon": 79 var paths = []; 80 var bounds = new google.maps.LatLngBounds(); 81 for (var i = 0; i < geojsonGeometry.coordinates.length; i++){ 82 var path = []; 83 for (var j = 0; j < geojsonGeometry.coordinates[i].length; j++){ 84 var ll = new google.maps.LatLng(geojsonGeometry.coordinates[i][j][1], geojsonGeometry.coordinates[i][j][0]); 85 bounds.extend(ll); 86 path.push(ll) 87 } 88 paths.push(path); 89 } 90 opts.paths = paths; 91 googleObj = new google.maps.Polygon(opts); 92 googleObj.set('bounds', bounds); 93 if (geojsonProperties) { 94 googleObj.set("geojsonProperties", geojsonProperties); 95 } 96 break; 97 98 case "MultiPolygon": 99 googleObj = []; 100 var bounds = new google.maps.LatLngBounds(); 101 for (var i = 0; i < geojsonGeometry.coordinates.length; i++){ 102 var paths = []; 103 for (var j = 0; j < geojsonGeometry.coordinates[i].length; j++){ 104 var path = []; 105 for (var k = 0; k < geojsonGeometry.coordinates[i][j].length; k++){ 106 var ll = new google.maps.LatLng(geojsonGeometry.coordinates[i][j][k][1], geojsonGeometry.coordinates[i][j][k][0]); 107 bounds.extend(ll); 108 path.push(ll); 109 } 110 paths.push(path); 111 } 112 opts.paths = paths; 113 googleObj.push(new google.maps.Polygon(opts)); 114 } 115 if (geojsonProperties) { 116 for (var k = 0; k < googleObj.length; k++){ 117 googleObj[k].set("geojsonProperties", geojsonProperties); 118 } 119 } 120 for (var k = 0; k < googleObj.length; k++) { 121 googleObj[k].set('bounds', bounds); 122 } 123 break; 124 125 case "GeometryCollection": 126 googleObj = []; 127 if (!geojsonGeometry.geometries){ 128 googleObj = _error("Invalid GeoJSON object: GeometryCollection object missing \"geometries\" member."); 129 }else{ 130 for (var i = 0; i < geojsonGeometry.geometries.length; i++){ 131 googleObj.push(_geometryToGoogleMaps(geojsonGeometry.geometries[i], opts, geojsonProperties || null)); 132 } 133 } 134 break; 135 136 default: 137 googleObj = _error("Invalid GeoJSON object: Geometry object must be one of \"Point\", \"LineString\", \"Polygon\" or \"MultiPolygon\"."); 138 } 139 140 return googleObj; 141 142 }; 143 144 var _error = function( message ){ 145 146 return { 147 type: "Error", 148 message: message 149 }; 150 151 }; 152 153 var obj; 154 155 var opts = options || {}; 156 157 switch ( geojson.type ){ 158 159 case "FeatureCollection": 160 if (!geojson.features){ 161 obj = _error("Invalid GeoJSON object: FeatureCollection object missing \"features\" member."); 162 }else{ 163 obj = []; 164 for (var i = 0; i < geojson.features.length; i++){ 165 obj.push(_geometryToGoogleMaps(geojson.features[i].geometry, opts, geojson.features[i].properties)); 166 } 167 } 168 break; 169 170 case "GeometryCollection": 171 if (!geojson.geometries){ 172 obj = _error("Invalid GeoJSON object: GeometryCollection object missing \"geometries\" member."); 173 }else{ 174 obj = []; 175 for (var i = 0; i < geojson.geometries.length; i++){ 176 obj.push(_geometryToGoogleMaps(geojson.geometries[i], opts, geojson.geometries[i].properties)); 177 } 178 } 179 break; 180 181 case "Feature": 182 if (!( geojson.properties && geojson.geometry )){ 183 obj = _error("Invalid GeoJSON object: Feature object missing \"properties\" or \"geometry\" member."); 184 }else{ 185 obj = _geometryToGoogleMaps(geojson.geometry, opts, geojson.properties); 186 } 187 break; 188 189 case "Point": case "MultiPoint": case "LineString": case "MultiLineString": case "Polygon": case "MultiPolygon": 190 obj = geojson.coordinates 191 ? obj = _geometryToGoogleMaps(geojson, opts, geojson.properties) 192 : _error("Invalid GeoJSON object: Geometry object missing \"coordinates\" member."); 193 break; 194 195 default: 196 obj = _error("Invalid GeoJSON object: GeoJSON object must be one of \"Point\", \"LineString\", \"Polygon\", \"MultiPolygon\", \"Feature\", \"FeatureCollection\" or \"GeometryCollection\"."); 197 198 } 199 200 return obj; 201}; 202; 203(function ($) { 204 Drupal.behaviors.geofieldMap = { 205 attach: function(context, settings) { 206 Drupal.geoField = Drupal.geoField || {}; 207 Drupal.geoField.maps = Drupal.geoField.maps || {}; 208 209 $('.geofieldMap', context).once('geofield-processed', function(index, element) { 210 var data = undefined; 211 var map_settings = []; 212 var pointCount = 0; 213 var resetZoom = true; 214 var elemID = $(element).attr('id'); 215 216 if(settings.geofieldMap[elemID]) { 217 data = settings.geofieldMap[elemID].data; 218 map_settings = settings.geofieldMap[elemID].map_settings; 219 } 220 221 // Checking to see if google variable exists. We need this b/c views breaks this sometimes. Probably 222 // an AJAX/external javascript bug in core or something. 223 if (typeof google != 'undefined' && typeof google.maps.ZoomControlStyle != 'undefined' && data != undefined) { 224 var features = GeoJSON(data); 225 // controltype 226 var controltype = map_settings.controltype; 227 if (controltype == 'default') { controltype = google.maps.ZoomControlStyle.DEFAULT; } 228 else if (controltype == 'small') { controltype = google.maps.ZoomControlStyle.SMALL; } 229 else if (controltype == 'large') { controltype = google.maps.ZoomControlStyle.LARGE; } 230 else { controltype = false } 231 232 // map type 233 var maptype = map_settings.maptype; 234 if (maptype) { 235 if (maptype == 'map' && map_settings.baselayers_map) { maptype = google.maps.MapTypeId.ROADMAP; } 236 if (maptype == 'satellite' && map_settings.baselayers_satellite) { maptype = google.maps.MapTypeId.SATELLITE; } 237 if (maptype == 'hybrid' && map_settings.baselayers_hybrid) { maptype = google.maps.MapTypeId.HYBRID; } 238 if (maptype == 'physical' && map_settings.baselayers_physical) { maptype = google.maps.MapTypeId.TERRAIN; } 239 } 240 else { maptype = google.maps.MapTypeId.ROADMAP; } 241 242 // menu type 243 var mtc = map_settings.mtc; 244 if (mtc == 'standard') { mtc = google.maps.MapTypeControlStyle.HORIZONTAL_BAR; } 245 else if (mtc == 'menu' ) { mtc = google.maps.MapTypeControlStyle.DROPDOWN_MENU; } 246 else { mtc = false; } 247 248 var myOptions = { 249 zoom: parseInt(map_settings.zoom), 250 minZoom: parseInt(map_settings.min_zoom), 251 maxZoom: parseInt(map_settings.max_zoom), 252 mapTypeId: maptype, 253 mapTypeControl: (mtc ? true : false), 254 mapTypeControlOptions: {style: mtc}, 255 zoomControl: ((controltype !== false) ? true : false), 256 zoomControlOptions: {style: controltype}, 257 panControl: (map_settings.pancontrol ? true : false), 258 scrollwheel: (map_settings.scrollwheel ? true : false), 259 draggable: (map_settings.draggable ? true : false), 260 overviewMapControl: (map_settings.overview ? true : false), 261 overviewMapControlOptions: {opened: (map_settings.overview_opened ? true : false)}, 262 streetViewControl: (map_settings.streetview_show ? true : false), 263 scaleControl: (map_settings.scale ? true : false), 264 scaleControlOptions: {style: google.maps.ScaleControlStyle.DEFAULT} 265 }; 266 267 var map = new google.maps.Map($(element).get(0), myOptions);
268 // Store a reference to the map object so other code can interact 269 // with it. 270 Drupal.geoField.maps[elemID] = map; 271 272 var range = new google.maps.LatLngBounds(); 273 274 var infowindow = new google.maps.InfoWindow({ 275 content: '' 276 }); 277 278 if (features.setMap) { 279 placeFeature(features, map, range); 280 // Don't move the default zoom if we're only displaying one point. 281 if (features.getPosition) { 282 resetZoom = false; 283 } 284 } else { 285 for (var i in features) { 286 if (features[i].setMap) { 287 placeFeature(features[i], map, range); 288 } else { 289 for (var j in features[i]) { 290 if (features[i][j].setMap) { 291 placeFeature(features[i][j], map, range); 292 } 293 } 294 } 295 } 296 } 297 298 for (first in features) break; 299 if (first!='type') { 300 if (resetZoom) { 301 map.fitBounds(range); 302 } else { 303 map.setCenter(range.getCenter()); 304 } 305 } else { 306 var center = map_settings.center; 307 map.setCenter(new google.maps.LatLng(center.lat, center.lon)); 308 } 309 } 310 311 function placeFeature(feature, map, range) { 312 var properties = feature.get('geojsonProperties'); 313 if (feature.setTitle && properties && properties.title) { 314 feature.setTitle(properties.title); 315 } 316 feature.setMap(map); 317 if (feature.getPosition) { 318 range.extend(feature.getPosition()); 319 } else { 320 var path = feature.getPath(); 321 path.forEach(function(element) { 322 range.extend(element); 323 }); 324 } 325 326 if (properties && properties.description) { 327 var bounds = feature.get('bounds'); 328 google.maps.event.addListener(feature, 'click', function() { 329 infowindow.setPosition(bounds.getCenter()); 330 infowindow.setContent(properties.description); 331 infowindow.open(map); 332 }); 333 } 334 } 335 }); 336 } 337 } 338})(jQuery); 339; 340/** 341 * @file 342 * Some basic behaviors and utility functions for Views. 343 */ 344(function ($) { 345 346 Drupal.Views = {}; 347 348 /** 349 * JQuery UI tabs, Views integration component. 350 */ 351 Drupal.behaviors.viewsTabs = { 352 attach: function (context) { 353 if ($.viewsUi && $.viewsUi.tabs) { 354 $('#views-tabset').once('views-processed').viewsTabs({ 355 selectedClass: 'active' 356 }); 357 } 358 359 $('a.views-remove-link').once('views-processed').click(function(event) { 360 var id = $(this).attr('id').replace('views-remove-link-', ''); 361 $('#views-row-' + id).hide(); 362 $('#views-removed-' + id).get(0).checked = true; 363 event.preventDefault(); 364 }); 365 // Here is to handle display deletion 366 // (checking in the hidden checkbox and hiding out the row). 367 $('a.display-remove-link') 368 .addClass('display-processed') 369 .click(function() { 370 var id = $(this).attr('id').replace('display-remove-link-', ''); 371 $('#display-row-' + id).hide(); 372 $('#display-removed-' + id).get(0).checked = true; 373 return false; 374 }); 375 } 376 }; 377 378 /** 379 * Helper function to parse a querystring. 380 */ 381 Drupal.Views.parseQueryString = function (query) { 382 var args = {}; 383 var pos = query.indexOf('?'); 384 if (pos != -1) { 385 query = query.substring(pos + 1); 386 } 387 var pairs = query.split('&'); 388 for (var i in pairs) { 389 if (typeof(pairs[i]) == 'string') { 390 var pair = pairs[i].split('='); 391 // Ignore the 'q' path argument, if present. 392 if (pair[0] != 'q' && pair[1]) { 393 args[decodeURIComponent(pair[0].replace(/\+/g, ' '))] = decodeURIComponent(pair[1].replace(/\+/g, ' ')); 394 } 395 } 396 } 397 return args; 398 }; 399 400 /** 401 * Helper function to return a view's arguments based on a path. 402 */ 403 Drupal.Views.parseViewArgs = function (href, viewPath) { 404 // Provide language prefix. 405 if (Drupal.settings.pathPrefix) { 406 var viewPath = Drupal.settings.pathPrefix + viewPath; 407 } 408 var returnObj = {}; 409 var path = Drupal.Views.getPath(href); 410 // Ensure there is a correct path. 411 if (viewPath && path.substring(0, viewPath.length + 1) == viewPath + '/') { 412 var args = decodeURIComponent(path.substring(viewPath.length + 1, path.length)); 413 returnObj.view_args = args; 414 returnObj.view_path = path; 415 } 416 return returnObj; 417 }; 418 419 /** 420 * Strip off the protocol plus domain from an href. 421 */ 422 Drupal.Views.pathPortion = function (href) { 423 // Remove e.g. http://example.com if present. 424 var protocol = window.location.protocol; 425 if (href.substring(0, protocol.length) == protocol) { 426 // 2 is the length of the '//' that normally follows the protocol. 427 href = href.substring(href.indexOf('/', protocol.length + 2)); 428 } 429 return href; 430 }; 431 432 /** 433 * Return the Drupal path portion of an href. 434 */ 435 Drupal.Views.getPath = function (href) { 436 href = Drupal.Views.pathPortion(href); 437 href = href.substring(Drupal.settings.basePath.length, href.length); 438 // 3 is the length of the '?q=' added to the URL without clean URLs.
439 if (href.substring(0, 3) == '?q=') { 440 href = href.substring(3, href.length); 441 } 442 var chars = ['#', '?', '&']; 443 for (var i in chars) { 444 if (href.indexOf(chars[i]) > -1) { 445 href = href.substr(0, href.indexOf(chars[i])); 446 } 447 } 448 return href; 449 }; 450 451})(jQuery); 452; 453(function ($) { 454 455/** 456 * A progressbar object. Initialized with the given id. Must be inserted into 457 * the DOM afterwards through progressBar.element. 458 * 459 * method is the function which will perform the HTTP request to get the 460 * progress bar state. Either "GET" or "POST". 461 * 462 * e.g. pb = new progressBar('myProgressBar'); 463 * some_element.appendChild(pb.element); 464 */ 465Drupal.progressBar = function (id, updateCallback, method, errorCallback) { 466 var pb = this; 467 this.id = id; 468 this.method = method || 'GET'; 469 this.updateCallback = updateCallback; 470 this.errorCallback = errorCallback; 471 472 // The WAI-ARIA setting aria-live="polite" will announce changes after users 473 // have completed their current activity and not interrupt the screen reader. 474 this.element = $('<div class="progress" aria-live="polite"></div>').attr('id', id); 475 this.element.html('<div class="bar"><div class="filled"></div></div>' + 476 '<div class="percentage"></div>' + 477 '<div class="message"> </div>'); 478}; 479 480/** 481 * Set the percentage and status message for the progressbar. 482 */ 483Drupal.progressBar.prototype.setProgress = function (percentage, message) { 484 if (percentage >= 0 && percentage <= 100) { 485 $('div.filled', this.element).css('width', percentage + '%'); 486 $('div.percentage', this.element).html(percentage + '%'); 487 } 488 $('div.message', this.element).html(message); 489 if (this.updateCallback) { 490 this.updateCallback(percentage, message, this); 491 } 492}; 493 494/** 495 * Start monitoring progress via Ajax. 496 */ 497Drupal.progressBar.prototype.startMonitoring = function (uri, delay) { 498 this.delay = delay; 499 this.uri = uri; 500 this.sendPing(); 501}; 502 503/** 504 * Stop monitoring progress via Ajax. 505 */ 506Drupal.progressBar.prototype.stopMonitoring = function () { 507 clearTimeout(this.timer); 508 // This allows monitoring to be stopped from within the callback. 509 this.uri = null; 510}; 511 512/** 513 * Request progress data from server. 514 */ 515Drupal.progressBar.prototype.sendPing = function () { 516 if (this.timer) { 517 clearTimeout(this.timer); 518 } 519 if (this.uri) { 520 var pb = this; 521 // When doing a post request, you need non-null data. Otherwise a 522 // HTTP 411 or HTTP 406 (with Apache mod_security) error may result. 523 $.ajax({ 524 type: this.method, 525 url: this.uri, 526 data: '', 527 dataType: 'json', 528 success: function (progress) { 529 // Display errors. 530 if (progress.status == 0) { 531 pb.displayError(progress.data); 532 return; 533 } 534 // Update display. 535 pb.setProgress(progress.percentage, progress.message); 536 // Schedule next timer. 537 pb.timer = setTimeout(function () { pb.sendPing(); }, pb.delay); 538 }, 539 error: function (xmlhttp) { 540 pb.displayError(Drupal.ajaxError(xmlhttp, pb.uri)); 541 } 542 }); 543 } 544}; 545 546/** 547 * Display errors on the page. 548 */ 549Drupal.progressBar.prototype.displayError = function (string) { 550 var error = $('<div class="messages error"></div>').html(string); 551 $(this.element).before(error).hide(); 552 553 if (this.errorCallback) { 554 this.errorCallback(this); 555 } 556}; 557 558})(jQuery); 559; 560/** 561 * @file 562 * Handles AJAX fetching of views, including filter submission and response. 563 */ 564(function ($) { 565 566 /** 567 * Attaches the AJAX behavior to exposed filter forms and key views links. 568 */ 569 Drupal.behaviors.ViewsAjaxView = {}; 570 Drupal.behaviors.ViewsAjaxView.attach = function() { 571 if (Drupal.settings && Drupal.settings.views && Drupal.settings.views.ajaxViews) { 572 $.each(Drupal.settings.views.ajaxViews, function(i, settings) { 573 Drupal.views.instances[i] = new Drupal.views.ajaxView(settings); 574 }); 575 } 576 }; 577 578 Drupal.views = {}; 579 Drupal.views.instances = {}; 580 581 /** 582 * JavaScript object for a certain view. 583 */ 584 Drupal.views.ajaxView = function(settings) { 585 var selector = '.view-dom-id-' + settings.view_dom_id; 586 this.$view = $(selector); 587 588 // If view is not present return to prevent errors. 589 if (!this.$view.length) { 590 return; 591 } 592 593 // Retrieve the path to use for views' ajax. 594 var ajax_path = Drupal.settings.views.ajax_path; 595 596 // If there are multiple views this might've ended up showing up multiple 597 // times. 598 if (ajax_path.constructor.toString().indexOf("Array") != -1) { 599 ajax_path = ajax_path[0]; 600 } 601
602 // Check if there are any GET parameters to send to views. 603 var queryString = window.location.search || ''; 604 if (queryString !== '') { 605 // Remove the question mark and Drupal path component if any. 606 var queryString = queryString.slice(1).replace(/q=[^&]+&?|&?render=[^&]+/, ''); 607 if (queryString !== '') { 608 // If there is a '?' in ajax_path, clean url are on and & should be 609 // used to add parameters. 610 queryString = ((/\?/.test(ajax_path)) ? '&' : '?') + queryString; 611 } 612 } 613 614 this.element_settings = { 615 url: ajax_path + queryString, 616 submit: settings, 617 setClick: true, 618 event: 'click', 619 selector: selector, 620 progress: { 621 type: 'throbber' 622 } 623 }; 624 625 this.settings = settings; 626 627 // Add the ajax to exposed forms. 628 this.$exposed_form = $('#views-exposed-form-' + settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-')); 629 this.$exposed_form.once(jQuery.proxy(this.attachExposedFormAjax, this)); 630 631 // Store Drupal.ajax objects here for all pager links. 632 this.links = []; 633 634 // Add the ajax to pagers. 635 this.$view 636 .once(jQuery.proxy(this.attachPagerAjax, this)); 637 638 // Add a trigger to update this view specifically. In order to trigger a 639 // refresh use the following code. 640 // 641 // @code 642 // jQuery('.view-name').trigger('RefreshView'); 643 // @endcode 644 // Add a trigger to update this view specifically. 645 var self_settings = this.element_settings; 646 self_settings.event = 'RefreshView'; 647 var self = this; 648 this.$view.once('refresh', function () { 649 self.refreshViewAjax = new Drupal.ajax(self.selector, self.$view, self_settings); 650 }); 651 }; 652 653 Drupal.views.ajaxView.prototype.attachExposedFormAjax = function() { 654 var button = $('input[type=submit], button[type=submit], input[type=image]', this.$exposed_form); 655 button = button[0]; 656 657 // Call the autocomplete submit before doing AJAX. 658 $(button).click(function () { 659 if (Drupal.autocompleteSubmit) { 660 Drupal.autocompleteSubmit(); 661 } 662 }); 663 664 this.exposedFormAjax = new Drupal.ajax($(button).attr('id'), button, this.element_settings); 665 }; 666 667 /** 668 * Attach the ajax behavior to each link. 669 */ 670 Drupal.views.ajaxView.prototype.attachPagerAjax = function() { 671 this.$view.find('ul.pager > li > a, ol.pager > li > a, th.views-field a, .attachment .views-summary a') 672 .each(jQuery.proxy(this.attachPagerLinkAjax, this)); 673 }; 674 675 /** 676 * Attach the ajax behavior to a single link. 677 */ 678 Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function(id, link) { 679 var $link = $(link); 680 var viewData = {}; 681 var href = $link.attr('href'); 682 // Don't attach to pagers inside nested views. 683 if ($link.closest('.view')[0] !== this.$view[0] && 684 $link.closest('.view').parent().hasClass('attachment') === false) { 685 return; 686 } 687 688 // Provide a default page if none has been set. This must be done 689 // prior to merging with settings to avoid accidentally using the 690 // page landed on instead of page 1. 691 if (typeof(viewData.page) === 'undefined') { 692 viewData.page = 0; 693 } 694 695 // Construct an object using the settings defaults and then overriding 696 // with data specific to the link. 697 $.extend( 698 viewData, 699 this.settings, 700 Drupal.Views.parseQueryString(href), 701 // Extract argument data from the URL. 702 Drupal.Views.parseViewArgs(href, this.settings.view_base_path) 703 ); 704 705 // For anchor tags, these will go to the target of the anchor rather 706 // than the usual location. 707 $.extend(viewData, Drupal.Views.parseViewArgs(href, this.settings.view_base_path)); 708 709 // Construct an object using the element settings defaults, 710 // then overriding submit with viewData. 711 var pager_settings = $.extend({}, this.element_settings); 712 pager_settings.submit = viewData; 713 this.pagerAjax = new Drupal.ajax(false, $link, pager_settings); 714 this.links.push(this.pagerAjax); 715 }; 716 717 Drupal.ajax.prototype.commands.viewsScrollTop = function (ajax, response, status) { 718 // Scroll to the top of the view. This will allow users 719 // to browse newly loaded content after e.g. clicking a pager 720 // link. 721 var offset = $(response.selector).offset(); 722 // We can't guarantee that the scrollable object should be 723 // the body, as the view could be embedded in something 724 // more complex such as a modal popup. Recurse up the DOM 725 // and scroll the first element that has a non-zero top. 726 var scrollTarget = response.selector; 727 while ($(scrollTarget).scrollTop() == 0 && $(scrollTarget).parent()) { 728 scrollTarget = $(scrollTarget).parent(); 729 } 730 // Only scroll upward. 731 if (offset.top - 10 < $(scrollTarget).scrollTop()) { 732 $(scrollTarget).animate({scrollTop: (offset.top - 10)}, 500); 733 } 734 }; 735 736})(jQuery); 737; 738(function ($) { 739 740 Drupal.behaviors.leaflet = { 741 attach:function (context, settings) { 742 743 $(settings.leaflet).each(function () { 744 // skip to the next iteration if the map already exists 745 var container = L.DomUtil.get(this.mapId); 746 if (!container || container._leaflet_id) { 747 return; 748 } 749 750 // load a settings object with all of our map settings 751 var settings = {}; 752 for (var setting in this.map.settings) { 753 settings[setting] = this.map.settings[setting]; 754 } 755 756 // instantiate our new map 757 var lMap = new L.Map(this.mapId, settings); 758 lMap.bounds = []; 759 760 // add map layers 761 var layers = {}, overlays = {}; 762 var i = 0; 763 for (var key in this.map.layers) { 764 var layer = this.map.layers[key]; 765 var map_layer = Drupal.leaflet.create_layer(layer, key); 766 //layers[key] = map_layer; 767 768 // Distinguish between "base layers" and "overlays". 769 // Fall back to "base" in case "layer_type" has not been defined in 770 // hook_leaflet_map_info() 771 layer.layer_type = (typeof layer.layer_type === 'undefined') ? 'base' : layer.layer_type; 772 // As stated in http://leafletjs.com/examples/layers-control, 773 // when using multiple base layers, only one of them should be added 774 // to the map at instantiation, but all of them should be present in 775 // the base layers object when creating the layers control. 776 // See statement L.control.layers(layers, overlays) much further below. 777 switch (layer.layer_type) { 778 case 'overlay': 779 //lMap.addLayer(map_layer); 780 overlays[key] = map_layer; 781 break; 782 default: 783 if (i === 0 /*|| !this.map.settings.layerControl*/) { 784 lMap.addLayer(map_layer); 785 i++; 786 } 787 layers[key] = map_layer; 788 break; 789 } 790 i++; 791 } 792 793 var switchEnable = false;
794 for (var key in layers) { 795 if (layers[key].options.switchLayer) { 796 layers[key].setSwitchLayer(layers[layers[key].options.switchLayer]); 797 switchEnable = true; 798 } 799 } 800 if (switchEnable) { 801 switchManager = new SwitchLayerManager(lMap, {baseLayers: layers}); 802 } 803 804 // keep an instance of leaflet layers 805 this.map.lLayers = layers; 806 807 // keep an instance of map_id 808 this.map.map_id = this.mapId; 809 810 // add features 811 for (i = 0; i < this.features.length; i++) { 812 var feature = this.features[i]; 813 var lFeature; 814 815 // dealing with a layer group 816 if (feature.group) { 817 var lGroup = new L.LayerGroup(); 818 for (var groupKey in feature.features) { 819 var groupFeature = feature.features[groupKey]; 820 lFeature = leaflet_create_feature(groupFeature, lMap); 821 if (groupFeature.popup) { 822 lFeature.bindPopup(groupFeature.popup); 823 } 824 lGroup.addLayer(lFeature); 825 826 // Allow others to do something with the feature within a group. 827 $(document).trigger('leaflet.feature', [lFeature, feature]); 828 } 829 830 // add the group to the layer switcher 831 overlays[feature.label] = lGroup; 832 833 lMap.addLayer(lGroup); 834 } 835 else { 836 lFeature = leaflet_create_feature(feature, lMap); 837 lMap.addLayer(lFeature); 838 839 if (feature.popup) { 840 lFeature.bindPopup(feature.popup); 841 } 842 843 // Allow others to do something with the feature. 844 $(document).trigger('leaflet.feature', [lFeature, feature]); 845 } 846 847 } 848 849 // add layer switcher 850 if (this.map.settings.layerControl) { 851 L.control.layers(layers, overlays).addTo(lMap); 852 } 853 854 // center the map 855 var zoom = this.map.settings.zoom ? this.map.settings.zoom : this.map.settings.zoomDefault; 856 if (this.map.center && (this.map.center.force || this.features.length === 0)) { 857 lMap.setView(new L.LatLng(this.map.center.lat, this.map.center.lon), zoom); 858 } 859 else if (this.features.length > 0) { 860 Drupal.leaflet.fitbounds(lMap); 861 if (this.map.settings.zoom) { // or: if (zoom) ? 862 lMap.setZoom(zoom); 863 } 864 } 865 866 // add attribution 867 if (this.map.settings.attributionControl && this.map.attribution) { 868 lMap.attributionControl.setPrefix(this.map.attribution.prefix); 869 lMap.attributionControl.addAttribution(this.map.attribution.text); 870 } 871 872 // add the leaflet map to our settings object to make it accessible 873 this.lMap = lMap; 874 875 // allow other modules to get access to the map object using jQuery's trigger method 876 $(document).trigger('leaflet.map', [this.map, lMap]); 877 878 // Destroy features so that an AJAX reload does not get parts of the old set. 879 // Required when the View has "Use AJAX" set to Yes. 880 this.features = null; 881 }); 882 883 function leaflet_create_feature(feature, lMap) { 884 var lFeature; 885 switch (feature.type) { 886 case 'point': 887 lFeature = Drupal.leaflet.create_point(feature, lMap); 888 break; 889 case 'linestring': 890 lFeature = Drupal.leaflet.create_linestring(feature, lMap); 891 break; 892 case 'polygon': 893 lFeature = Drupal.leaflet.create_polygon(feature, lMap); 894 break; 895 case 'multipolyline': 896 feature.multipolyline = true; 897 // no break; 898 case 'multipolygon': 899 lFeature = Drupal.leaflet.create_multipoly(feature, lMap); 900 break; 901 case 'json': 902 lFeature = Drupal.leaflet.create_json(feature.json, lMap); 903 break; 904 case 'popup': 905 lFeature = Drupal.leaflet.create_popup(feature, lMap); 906 break; 907 case 'circle': 908 lFeature = Drupal.leaflet.create_circle(feature, lMap); 909 break; 910 case 'circlemarker': 911 lFeature = Drupal.leaflet.create_circlemarker(feature, lMap); 912 break; 913 case 'rectangle': 914 lFeature = Drupal.leaflet.create_rectangle(feature, lMap); 915 break; 916 } 917 918 // assign our given unique ID, useful for associating nodes 919 if (feature.leaflet_id) { 920 lFeature._leaflet_id = feature.leaflet_id; 921 } 922 923 var options = {}; 924 if (feature.options) { 925 for (var option in feature.options) { 926 options[option] = feature.options[option]; 927 } 928 lFeature.setStyle(options); 929 } 930 931 return lFeature; 932 } 933 934 } 935 }; 936 937 Drupal.leaflet = { 938 939 isOldVersion: function () { 940 return !(parseInt(L.version) >= 1); // version may start with '0' or '.' 941 }, 942 943 create_layer: function (layer, key) { 944 // Use a Zoomswitch Layer extension to enable zoom-switch option. 945 var map_layer = new L.TileLayerZoomSwitch(layer.urlTemplate); 946 map_layer._leaflet_id = key; 947 948 if (layer.options) { 949 for (var option in layer.options) { 950 map_layer.options[option] = layer.options[option]; 951 } 952 } 953 954 // layers served from TileStream need this correction in the y coordinates 955 // TODO: Need to explore this more and find a more elegant solution 956 if (layer.type == 'tilestream') { 957 map_layer.getTileUrl = function (tilePoint) { 958 this._adjustTilePoint(tilePoint); 959 var zoom = this._getZoomForUrl(); 960 return L.Util.template(this._url, L.Util.extend({ 961 s: this._getSubdomain(tilePoint), 962 z: zoom, 963 x: tilePoint.x, 964 y: Math.pow(2, zoom) - tilePoint.y - 1 965 }, this.options)); 966 }; 967 } 968 return map_layer; 969 }, 970 971 create_circle: function(circle, lMap) { 972 var latLng = new L.LatLng(circle.lat, circle.lon); 973 latLng = latLng.wrap(); 974 lMap.bounds.push(latLng); 975 if (circle.radius) { 976 // @deprecated 977 return L.circle(latLng, circle.radius, circle.options); 978 } 979 return new L.Circle(latLng, circle.options); 980 }, 981 982 create_circlemarker: function(circle, lMap) { 983 var latLng = new L.LatLng(circle.lat, circle.lon); 984 latLng = latLng.wrap(); 985 lMap.bounds.push(latLng); 986 return new L.CircleMarker(latLng, circle.options); 987 }, 988 989 create_rectangle: function(box, lMap) { 990 var bounds = box.bounds, 991 southWest = new L.LatLng(bounds.s, bounds.w), 992 northEast = new L.LatLng(bounds.n, bounds.e), 993 latLng = new L.LatLngBounds(southWest, northEast); 994 lMap.bounds.push(latLng); 995 return new L.Rectangle(latLng, box.settings); 996 }, 997 998 create_point: function(marker, lMap) { 999 var latLng = new L.LatLng(marker.lat, marker.lon); 1000 latLng = latLng.wrap(); 1001 lMap.bounds.push(latLng); 1002 var lMarker; 1003 1004 if (marker.html) { 1005 if (marker.html_class) { 1006 var icon = new L.DivIcon({html: marker.html, className: marker.html_class}); 1007 } 1008 else { 1009 var icon = new L.DivIcon({html: marker.html}); 1010 } 1011 // override applicable marker defaults 1012 if (marker.icon.iconSize) { 1013 icon.options.iconSize = new L.Point(parseInt(marker.icon.iconSize.x, 10), parseInt(marker.icon.iconSize.y, 10)); 1014 } 1015 if (marker.icon.iconAnchor) { 1016 icon.options.iconAnchor = new L.Point(parseFloat(marker.icon.iconAnchor.x), parseFloat(marker.icon.iconAnchor.y)); 1017 } 1018 lMarker = new L.Marker(latLng, {icon:icon}); 1019 } 1020 else if (marker.icon) { 1021 var icon = new L.Icon({iconUrl: marker.icon.iconUrl}); 1022 1023 // override applicable marker defaults 1024 if (marker.icon.iconSize) { 1025 icon.options.iconSize = new L.Point(parseInt(marker.icon.iconSize.x, 10), parseInt(marker.icon.iconSize.y, 10)); 1026 } 1027 if (marker.icon.iconAnchor) { 1028 icon.options.iconAnchor = new L.Point(parseFloat(marker.icon.iconAnchor.x), parseFloat(marker.icon.iconAnchor.y)); 1029 } 1030 if (marker.icon.popupAnchor) { 1031 icon.options.popupAnchor = new L.Point(parseFloat(marker.icon.popupAnchor.x), parseFloat(marker.icon.popupAnchor.y)); 1032 } 1033 if (marker.icon.shadowUrl !== undefined) { 1034 icon.options.shadowUrl = marker.icon.shadowUrl; 1035 } 1036 if (marker.icon.shadowSize) { 1037 icon.options.shadowSize = new L.Point(parseInt(marker.icon.shadowSize.x, 10), parseInt(marker.icon.shadowSize.y, 10)); 1038 } 1039 if (marker.icon.shadowAnchor) { 1040 icon.options.shadowAnchor = new L.Point(parseInt(marker.icon.shadowAnchor.x, 10), parseInt(marker.icon.shadowAnchor.y, 10)); 1041 } 1042 if (marker.icon.zIndexOffset) { 1043 icon.options.zIndexOffset = marker.icon.zIndexOffset; 1044 } 1045 if (marker.icon.className) { 1046 icon.options.className = marker.icon.className; 1047 } 1048 var options = {icon:icon}; 1049 if (marker.zIndexOffset) { 1050 options.zIndexOffset = marker.zIndexOffset; 1051 } 1052 lMarker = new L.Marker(latLng, options); 1053 } 1054 else { 1055 lMarker = new L.Marker(latLng); 1056 } 1057 1058 if (marker.label) { 1059 lMarker.options.title = marker.label; 1060 } 1061 1062 return lMarker; 1063 }, 1064 1065 create_linestring: function(polyline, lMap) { 1066 var latlngs = []; 1067 for (var i = 0; i < polyline.points.length; i++) { 1068 var latlng = new L.LatLng(polyline.points[i].lat, polyline.points[i].lon); 1069 latlng = latlng.wrap(); 1070 latlngs.push(latlng); 1071 lMap.bounds.push(latlng); 1072 } 1073 return new L.Polyline(latlngs); 1074 }, 1075
1076 create_polygon: function(polygon, lMap) { 1077 var latlngs = []; 1078 for (var i = 0; i < polygon.points.length; i++) { 1079 var latlng = new L.LatLng(polygon.points[i].lat, polygon.points[i].lon); 1080 latlng = latlng.wrap(); 1081 latlngs.push(latlng); 1082 lMap.bounds.push(latlng); 1083 } 1084 return new L.Polygon(latlngs); 1085 }, 1086 1087 create_multipoly: function(multipoly, lMap) { 1088 var polygons = []; 1089 for (var x = 0; x < multipoly.component.length; x++) { 1090 var latlngs = []; 1091 var polygon = multipoly.component[x]; 1092 for (var i = 0; i < polygon.points.length; i++) { 1093 var latlng = new L.LatLng(polygon.points[i].lat, polygon.points[i].lon); 1094 latlng = latlng.wrap(); 1095 latlngs.push(latlng); 1096 lMap.bounds.push(latlng); 1097 } 1098 polygons.push(latlngs); 1099 } 1100 if (this.isOldVersion()) { 1101 return multipoly.multipolyline ? new L.MultiPolyline(polygons) : new L.MultiPolygon(polygons); 1102 } 1103 return multipoly.multipolyline ? new L.Polyline(polygons): new L.Polygon(polygons); 1104 }, 1105 1106 create_json:function(json, lMap) { 1107 lJSON = new L.GeoJSON(json, { 1108 onEachFeature:function (feature, layer) { 1109 var has_properties = (typeof feature.properties != 'undefined'); 1110 1111 // bind popups 1112 if (has_properties && typeof feature.properties.popup != 'undefined') { 1113 layer.bindPopup(feature.properties.popup); 1114 } 1115 1116 for (var layer_id in layer._layers) { 1117 for (var i in layer._layers[layer_id]._latlngs) { 1118 lMap.bounds.push(layer._layers[layer_id]._latlngs[i]); 1119 } 1120 } 1121 1122 if (has_properties && typeof feature.properties.style != 'undefined') { 1123 layer.setStyle(feature.properties.style); 1124 } 1125 1126 if (has_properties && typeof feature.properties.leaflet_id != 'undefined') { 1127 layer._leaflet_id = feature.properties.leaflet_id; 1128 } 1129 } 1130 }); 1131 1132 return lJSON; 1133 }, 1134 1135 create_popup: function(popup) { 1136 var latLng = new L.LatLng(popup.lat, popup.lon); 1137 this.bounds.push(latLng); 1138 var lPopup = new L.Popup(); 1139 lPopup.setLatLng(latLng); 1140 if (popup.content) { 1141 lPopup.setContent(popup.content); 1142 } 1143 return lPopup; 1144 }, 1145 1146 fitbounds:function (lMap) { 1147 if (lMap.bounds.length > 0) { 1148 lMap.fitBounds(new L.LatLngBounds(lMap.bounds)); 1149 } 1150 } 1151 }; 1152 1153 // Zoomswitch method cribbed liberally from: 1154 // http://www.makina-corpus.org/blog/leaflet-zoom-switcher 1155 L.TileLayerZoomSwitch = L.TileLayer.extend({ 1156 includes: L.Mixin.Events, 1157 1158 options: { 1159 // switchZoomUnder: when zoom < switchZoomUnder, then switch to switchLayer 1160 switchZoomUnder: -1, 1161 // switchZoomAbove: when zoom >= switchZoomAbove, then switch to switchLayer 1162 switchZoomAbove: -1, 1163 switchLayer: null 1164 }, 1165 1166 setSwitchLayer: function (layer) { 1167 this.options.switchLayer = layer; 1168 }, 1169 1170 getSwitchZoomUnder: function () { 1171 return this.options.switchZoomUnder; 1172 }, 1173 1174 getSwitchZoomAbove: function () { 1175 return this.options.switchZoomAbove; 1176 }, 1177 1178 getSwitchLayer: function () { 1179 return this.options.switchLayer; 1180 } 1181 1182 }); 1183 1184 L.tileLayerZoomSwitch = function (url, options) { 1185 return new L.TileLayerZoomSwitch(url, options); 1186 }; 1187 1188 /* 1189 * SwitchLayerManager is a custom class for managing base layer automatic switching according to the current zoom level 1190 */ 1191 1192 SwitchLayerManager = L.Class.extend({ 1193 1194 _map: null, 1195 1196 options: { 1197 baseLayers: null 1198 }, 1199 1200 initialize: function (map, options) { 1201 this._map = map; 1202 L.Util.setOptions(this, options); 1203 1204 this._map.on({ 1205 'zoomend': this._update 1206 }, this) 1207 1208 }, 1209 1210 _update: function (e) { 1211 var zoom = this._map.getZoom(); 1212 1213 for (var i in this.options.baseLayers) { 1214 var curBL = this.options.baseLayers[i]; 1215 var zoomUnder = curBL.getSwitchZoomUnder(); 1216 var zoomAbove = curBL.getSwitchZoomAbove(); 1217 var switchLayer = curBL.getSwitchLayer(); 1218 1219 // If layer got a switchlayer, and if layer actually displayed 1220 if (switchLayer && curBL._map != null) { 1221 //if (switchLayer) { 1222 if(zoomUnder != -1 && zoom < zoomUnder) { 1223 this._map.removeLayer(curBL); 1224 this._map.addLayer(switchLayer, false); 1225 } 1226 1227 if(zoomAbove != -1 && zoom >= zoomAbove) { 1228 this._map.removeLayer(curBL); 1229 this._map.addLayer(switchLayer, false); 1230 } 1231 } 1232 } 1233 } 1234 }); 1235 1236})(jQuery); 1237;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.