1/** 2 * @file 3 * GIcon manager for GMap. 4 * Required for markers to operate properly. 5 */ 6 7/*global jQuery, Drupal, GIcon, GPoint, GSize, G_DEFAULT_ICON */ 8 9/** 10 * Get the GIcon corresponding to a setname / sequence. 11 * There is only one GIcon for each slot in the sequence. 12 * The marker set wraps around when reaching the end of the sequence. 13 * @@@ TODO: Move this directly into the preparemarker event binding. 14 */ 15Drupal.gmap.getIcon = function (setname, sequence) { 16 var othimg = ['printImage', 'mozPrintImage', 'printShadow', 'transparent']; 17 // If no setname, return google's default icon. 18 if (!setname) { 19 return; 20 } 21 if (!this.gicons) { 22 this.gicons = {}; 23 } 24 if (!this.gshadows) { 25 this.gshadows = {}; 26 } 27 28 // If no sequence, synthesise one. 29 if (!sequence) { 30 // @TODO make this per-map. 31 if (!this.sequences) { 32 this.sequences = {}; 33 } 34 if (!this.sequences[setname]) { 35 this.sequences[setname] = -1; 36 } 37 this.sequences[setname]++; 38 sequence = this.sequences[setname]; 39 } 40 41 if (!this.gicons[setname]) { 42 if (!Drupal.gmap.icons[setname]) { 43 alert('Request for invalid marker set ' + setname + '!'); 44 } 45 this.gicons[setname] = []; 46 this.gshadows[setname] = []; 47 var q = Drupal.gmap.icons[setname]; 48 var p, t; 49 for (var i = 0; i < q.sequence.length; i++) { 50 /* 51 t = new GIcon(); 52 p = q.path; 53 t.image = p + q.sequence[i].f; 54 if (q.shadow.f !== '') { 55 t.shadow = p + q.shadow.f; 56 t.shadowSize = new GSize(q.shadow.w, q.shadow.h); 57 } 58 t.iconSize = new GSize(q.sequence[i].w, q.sequence[i].h); 59 t.iconAnchor = new GPoint(q.anchorX, q.anchorY); 60 t.infoWindowAnchor = new GPoint(q.infoX, q.infoY); 61 */ 62 p = Drupal.settings.basePath + q.path; 63 t = new google.maps.MarkerImage(p + q.sequence[i].f, 64 new google.maps.Size(q.sequence[i].w, q.sequence[i].h), 65 null, 66 new google.maps.Point(q.anchorX, q.anchorY) 67 ); 68 // Only set scaledSize if the scale variable makes sense as a divisor 69 if (q.scale > 1) { 70 t.scaledSize = new google.maps.Size(q.sequence[i].w/q.scale, q.sequence[i].h/q.scale); 71 } 72 if (q.shadow.f !== '') { 73 this.gshadows[setname][i] = new google.maps.MarkerImage(p + q.shadow.f, 74 new google.maps.Size(q.shadow.w, q.shadow.h), 75 null, 76 new google.maps.Point(q.anchorX, q.anchorY) 77 ); 78 } 79 else { 80 this.gshadows[setname][i] = null; 81 } 82 83 for (var j = 0; j < othimg.length; j++) { 84 if (q[othimg[j]] !== '') { 85 t[othimg[j]] = p + q[othimg[j]]; 86 } 87 } 88 // @@@ imageMap? 89 this.gicons[setname][i] = t; 90 } 91 delete Drupal.gmap.icons[setname]; 92 } 93 // TODO: Random, other cycle methods. 94 return this.gicons[setname][sequence % this.gicons[setname].length]; 95}; 96 97Drupal.gmap.getShadow = function (setname, sequence) { 98 if (this.gshadows) return this.gshadows[setname][sequence % this.gicons[setname].length]; 99}; 100 101/** 102 * JSON callback to set up the icon defs. 103 * When doing the JSON call, the data comes back in a packed format. 104 * We need to expand it and file it away in a more useful format. 105 */ 106Drupal.gmap.iconSetup = function () { 107 Drupal.gmap.icons = {}; 108 var m = Drupal.gmap.icondata; 109 var filef, filew, fileh, files; 110 for (var path in m) { 111 if (m.hasOwnProperty(path)) { 112 // Reconstitute files array 113 filef = m[path].f; 114 filew = Drupal.gmap.expandArray(m[path].w, filef.length); 115 fileh = Drupal.gmap.expandArray(m[path].h, filef.length); 116 files = []; 117 for (var i = 0; i < filef.length; i++) { 118 files[i] = {f: filef[i], w: filew[i], h: fileh[i]}; 119 } 120 121 for (var ini in m[path].i) { 122 if (m[path].i.hasOwnProperty(ini)) { 123 jQuery.extend(Drupal.gmap.icons, Drupal.gmap.expandIconDef(m[path].i[ini], path, files)); 124 } 125 } 126 } 127 } 128}; 129 130/** 131 * Expand a compressed array.
132 * This will pad arr up to len using the last value of the old array. 133 */ 134Drupal.gmap.expandArray = function (arr, len) { 135 var d = arr[0]; 136 for (var i = 0; i < len; i++) { 137 if (!arr[i]) { 138 arr[i] = d; 139 } 140 else { 141 d = arr[i]; 142 } 143 } 144 return arr; 145}; 146 147/** 148 * Expand icon definition. 149 * This helper function is the reverse of the packer function found in 150 * gmap_markerinfo.inc. 151 */ 152Drupal.gmap.expandIconDef = function (c, path, files) { 153 var decomp = ['key', 'name', 'sequence', 'anchorX', 'anchorY', 'infoX', 154 'infoY', 'scale', 'shadow', 'printImage', 'mozPrintImage', 'printShadow', 155 'transparent']; 156 var fallback = ['', '', [], 0, 0, 0, 0, 0, {f: '', h: 0, w: 0}, '', '', '', '']; 157 var imagerep = ['shadow', 'printImage', 'mozPrintImage', 'printShadow', 158 'transparent']; 159 var defaults = {}; 160 var sets = []; 161 var i, j; 162 // Part 1: Defaults / Markersets 163 // Expand arrays and fill in missing ones with fallbacks 164 for (i = 0; i < decomp.length; i++) { 165 if (!c[0][i]) { 166 c[0][i] = [ fallback[i] ]; 167 } 168 c[0][i] = Drupal.gmap.expandArray(c[0][i], c[0][0].length); 169 } 170 for (i = 0; i < c[0][0].length; i++) { 171 for (j = 0; j < decomp.length; j++) { 172 if (i === 0) { 173 defaults[decomp[j]] = c[0][j][i]; 174 } 175 else { 176 if (!sets[i - 1]) { 177 sets[i - 1] = {}; 178 } 179 sets[i - 1][decomp[j]] = c[0][j][i]; 180 } 181 } 182 } 183 for (i = 0; i < sets.length; i++) { 184 for (j = 0; j < decomp.length; j++) { 185 if (sets[i][decomp[j]] === fallback[j]) { 186 sets[i][decomp[j]] = defaults[decomp[j]]; 187 } 188 } 189 } 190 var icons = {}; 191 for (i = 0; i < sets.length; i++) { 192 var key = sets[i].key; 193 icons[key] = sets[i]; 194 icons[key].path = path; 195 delete icons[key].key; 196 delete sets[i]; 197 for (j = 0; j < icons[key].sequence.length; j++) { 198 icons[key].sequence[j] = files[icons[key].sequence[j]]; 199 } 200 for (j = 0; j < imagerep.length; j++) { 201 if (typeof(icons[key][imagerep[j]]) === 'number') { 202 icons[key][imagerep[j]] = files[icons[key][imagerep[j]]]; 203 } 204 } 205 } 206 return icons; 207}; 208 209/** 210 * We attach ourselves if we find a map somewhere needing markers. 211 * Note: Since we broadcast our ready event to all maps, it doesn't 212 * matter which one we attached to! 213 */ 214Drupal.gmap.addHandler('gmap', function (elem) { 215 var obj = this; 216 217 obj.bind('init', function () { 218 // Only expand once. 219 if (!Drupal.gmap.icons) { 220 Drupal.gmap.iconSetup(); 221 } 222 }); 223 224 obj.bind('ready', function () { 225 // Compatibility event. 226 if (Drupal.gmap.icondata) { 227 obj.deferChange('iconsready', -1); 228 } 229 }); 230 231 // Provide icons to markers. 232 obj.bind('preparemarker', function (marker) { 233 if (!obj.vars.behavior.customicons || (marker.markername && !marker.opts.icon)) { 234 marker.opts.icon = Drupal.gmap.getIcon(marker.markername, marker.offset); 235 marker.opts.shadow = Drupal.gmap.getShadow(marker.markername, marker.offset); 236 } 237 }); 238}); 239; 240/** 241 * @file 242 * Common marker routines. 243 */ 244 245/*global jQuery, Drupal, GEvent, GInfoWindowTab, GLatLng, GLatLngBounds */ 246 247Drupal.gmap.addHandler('gmap', function (elem) { 248 var obj = this; 249 var infowindow; 250 251 if (obj.vars.styleBubble && obj.vars.styleBubble.enableBubbleStyle == 1) { 252 infowindow = new InfoBubble(obj.vars.styleBubble.styleBubbleOptions); 253 } 254 else { 255 infowindow = new google.maps.InfoWindow(); 256 } 257 258 obj.bind('init', function () { 259 if (obj.vars.behavior.autozoom) { 260 obj.bounds = new google.maps.LatLngBounds(); 261 } 262 }); 263 264 obj.bind('addmarker', function (marker) { 265 marker.opts.position = new google.maps.LatLng(marker.latitude, marker.longitude); 266 marker.opts.map = obj.map; 267 var m = Drupal.gmap.factory.marker(marker.opts); 268 marker.marker = m; 269 google.maps.event.addListener(m, 'click', function () { 270 obj.change('clickmarker', -1, marker); 271 }); 272 if (obj.vars.behavior.extramarkerevents) { 273 google.maps.event.addListener(m, 'mouseover', function () {
274 obj.change('mouseovermarker', -1, marker); 275 }); 276 google.maps.event.addListener(m, 'mouseout', function () { 277 obj.change('mouseoutmarker', -1, marker); 278 }); 279 google.maps.event.addListener(m, 'dblclick', function () { 280 obj.change('dblclickmarker', -1, marker); 281 }); 282 } 283 /** 284 * Perform a synthetic marker click on this marker on load. 285 */ 286 if (marker.autoclick || (marker.options && marker.options.autoclick)) { 287 obj.deferChange('clickmarker', -1, marker); 288 } 289 if (obj.vars.behavior.autozoom) { 290 obj.bounds.extend(new google.maps.LatLng(marker.latitude, marker.longitude)); 291 } 292 }); 293 294 // Default marker actions. 295 obj.bind('clickmarker', function (marker) { 296 // Close infowindow if open to prevent multiple windows 297 if (infowindow !== null) { 298 infowindow.close(); 299 } 300 if (marker.text) { 301 infowindow.setContent(marker.text); 302 infowindow.open(obj.map, marker.marker); 303 } 304 // Info Window Query / Info Window Offset 305 else if (marker.iwq || (obj.vars.iwq && typeof marker.iwo != 'undefined')) { 306 var iwq, iwo; 307 if (obj.vars.iwq) { 308 iwq = obj.vars.iwq; 309 } 310 if (marker.iwq) { 311 iwq = marker.iwq; 312 } 313 iwo = 0; 314 if (marker.iwo) { 315 iwo = marker.iwo; 316 } 317 // Create a container to store the cloned DOM elements. 318 var el = document.createElement('div'); 319 // Clone the matched object, run through the clone, stripping off ids, and move the clone into the container. 320 jQuery(iwq).eq(iwo).clone(false).find('*').removeAttr('id').appendTo(jQuery(el)); 321 infowindow.setContent(el); 322 infowindow.open(obj.map, marker.marker); 323 } 324 // AJAX content 325 else if (marker.rmt) { 326 //Immediately add a 'loading' bubble on click while we wait for AJAX 327 infowindow.setContent('<div class="gmap-marker-rmt-loading throbber">Loading</div>'); 328 infowindow.open(obj.map, marker.marker); 329 330 var uri = marker.rmt; 331 // If there was a callback, prefix that. 332 // (If there wasn't, marker.rmt was the FULL path.) 333 if (obj.vars.rmtcallback) { 334 uri = Drupal.absoluteUrl(obj.vars.rmtcallback + '/' + marker.rmt); 335 } 336 // @Bevan: I think it makes more sense to do it in this order. 337 // @Bevan: I don't like your choice of variable btw, seems to me like 338 // @Bevan: it belongs in the map object, or at *least* somewhere in 339 // @Bevan: the gmap settings proper... 340 //if (!marker.text && Drupal.settings.loadingImage) { 341 // marker.marker.openInfoWindowHtml(Drupal.settings.loadingImage); 342 //} 343 jQuery.get(uri, {}, function (data) { 344 infowindow.setContent(data); 345 infowindow.open(obj.map, marker.marker); 346 }); 347 } 348 // Tabbed content 349 else if (marker.tabs) { 350 var data = ""; 351 //tabs in an infowindow is no longer supported in API ver3. 352 for (var m in marker.tabs) { 353 data += marker.tabs[m]; 354 } 355 infowindow.setContent(data); 356 infowindow.open(obj.map, marker.marker); 357 } 358 // No content -- marker is a link 359 else if (marker.link) { 360 open(marker.link, '_self'); 361 } 362 }); 363 364 obj.bind('markersready', function () { 365 // If we are autozooming, set the map center at this time. 366 if (obj.vars.behavior.autozoom) { 367 if (!obj.bounds.isEmpty()) { 368 obj.map.fitBounds(obj.bounds); 369 var listener = google.maps.event.addListener(obj.map, "idle", function () { 370 if (obj.vars.maxzoom) { 371 var maxzoom = parseInt(obj.vars.maxzoom); 372 if (obj.map.getZoom() > maxzoom) obj.map.setZoom(maxzoom); 373 google.maps.event.removeListener(listener); 374 } 375 }); 376 } 377 } 378 }); 379 380 obj.bind('clearmarkers', function () { 381 // Reset bounds if autozooming 382 // @@@ Perhaps we should have a bounds for both markers and shapes? 383 if (obj.vars.behavior.autozoom) { 384 obj.bounds = new google.maps.LatLngBounds(); 385 } 386 }); 387 388 Drupal.gmap.getInfoWindow = function () { 389 return infowindow; 390 }; 391 392 // @@@ TODO: Some sort of bounds handling for deletemarker? We'd have to walk the whole thing to figure out the new bounds... 393}); 394; 395/** 396 * @file 397 * Common marker highlighting routines. 398 */ 399 400/** 401 * Highlights marker on rollover. 402 * Removes highlight on previous marker. 403 * 404 * Creates a "circle" at the given point 405 * Circle is global variable as there is only one highlighted marker at a time 406 * and we want to remove the previously placed polygon before placing a new one. 407 *
408 * Original code "Google Maps JavaScript API Example" 409 * JN201304: 410 * converted rpolygons to circles (not using the shapes.js API, should we be?) 411 * move marker highlight events to custom handler here, to handle radius in pixels (note behavior.radiusInMeters to skip geodesic calcs) 412 * removed google.events and moved events to gmaps binds 413 * added overlay object for creating a shape based on pixels instead of meters (seems to be the use case?) 414 * added gmaps binds for marker higlights, and general highlights. 415 * JN201305 refactored to use a single overlay. move functions from draw method to solve zoom problem, and multiple 416 * highlights problem. 417 * 418 * You can add highlights to a map with: 419 * obj.change('highlightAdd',-1, {latitude:#, longitude:#} ); 420 * You can highlight a marker with: 421 * obj.change('markerHighlight',-1, marker); 422 * marker: that marker object used when creating the marker. It can have options set at marker.highlight 423 * 424 * A Highlight object has to have either a <LatLng>Position or a <Number>latitude and <Number>longitude 425 * Note the new highlight options = { 426 * radius: 10, // radius in pixels 427 * color: '#777777', 428 * weight: 2, 429 * opacity: 0.7, 430 * behavior: { 431 * draggable: false, 432 * editable: false, 433 * } 434 * opts: { actual google.maps.Circle opts can be put here for super custom cases } 435 * } 436 */ 437 438Drupal.gmap.factory.highlight = function (options) { 439 /** @note it could be argued that we use the shapes library to create a circle, 440 * but this requires the shapes library be loaded and it would make all highlights 441 * repond to shapes events. 442 */ 443 return new google.maps.Circle(options); 444}; 445 446Drupal.gmap.addHandler('gmap', function (elem) { 447 var obj = this; 448 obj.highlights = {}; 449 450 /** 451 * This is a single overlay that can hold multiple highlight. 452 * All highlight shapes will be creted in this overlay, and use 453 * it to translate pixel dimensions to meters. 454 */ 455 var highlightOverlay = function () { 456 this.highlights = []; // this will hold all of the highlights that we created, in case we need to recalculate/deactivate them 457 }; 458 highlightOverlay.prototype = new google.maps.OverlayView(); 459 460 // overlay method for when you .setMap( some map ); 461 highlightOverlay.prototype.onAdd = function (map) { 462 }; 463 // overlay method for when you .setMap(null); 464 highlightOverlay.prototype.onRemove = function () { 465 // we have to recalculate radii for all shapes 466 var self = this; 467 jQuery.each(this.highlights, function (index, highlight) { 468 if (highlight.shape.getMap()) { // don't calculate if we don't have a map. 469 self.calculateHighlight(highlight); //recalculate all of those radii 470 } 471 }); 472 }; 473 474 // overlay method executed on any map change methods (zoom/move) 475 highlightOverlay.prototype.draw = function () { 476 // we have to recalculate radii for all shapes 477 var self = this; 478 jQuery.each(this.highlights, function (index, highlight) { 479 if (highlight.shape.getMap()) { // don't calculate if we don't have a map. 480 self.deactivateHighlight(highlight); //recalculate all of those radii 481 } 482 }); 483 }; 484 485 highlightOverlay.prototype.configHighlight = function (highlight) { 486 if (!highlight.opts) { 487 highlight.opts = {}; 488 } // sanity 489 if (!highlight.behavior) { 490 highlight.behavior = {}; 491 } // sanity 492 if (!highlight.position) { 493 highlight.position = new google.maps.LatLng(highlight.latitude, highlight.longitude); 494 } // if you have a pos already then use it, otherwise gimme a lat/lon 495 496 jQuery.each({ // collect the options from either the highlight.opts object, from the passed target value, as a behavior or a defaultVal value. 497 radius: {target: 'radius', defaultVal: 10}, // radius in pixels 498 strokeColor: {target: 'border', defaultVal: '#777777'}, 499 strokeWeight: {target: 'weight', defaultVal: 2}, 500 strokeOpacity: {target: 'opacity', defaultVal: 0.7}, 501 fillColor: {target: 'color', defaultVal: '#777777'}, 502 fillOpacity: {target: 'opacity', defaultVal: 0.7}, 503 draggable: {behavior: 'draggable', defaultVal: false}, 504 editable: {behavior: 'editable', defaultVal: false} 505 }, function (key, config) { 506 if (highlight.opts[key]) { // options was passed in 507 return true; 508 } 509 else if (config.target && highlight[ config.target ]) { // highight[target] can give us a setting 510 highlight.opts[key] = highlight[ config.target ]; 511 } 512 else if (config.behavior && highlight.behavior && highlight.behavior[ config.behavior ]) { // value is a behaviour, should it be enabled? 513 highlight.opts[key] = highlight.behavior[ config.behavior ]; 514 } 515 else if (config.defaultVal) { // defaultVal value 516 highlight.opts[key] = config.defaultVal; 517 } 518 }); 519 520 highlight.opts.center = highlight.position; 521 // note that there is no opts.map, unless you passed one in. maybe we should make sure that you didn't? 522 523 // add this highlight to our list, so that we can draw it in the draw method (which will also redraw it after map change events. 524 this.highlights.push(highlight); 525 }; 526 // determine how big the circle should be in meters (as we were likely passed pixels). This radius changes on zoom and move events. 527 highlightOverlay.prototype.calculateHighlight = function (highlight) { // this nees a better name 528 529 if (highlight.behavior.radiusInMeters) { 530 highligh.opts.radiusInMeters = highlight.opts.radius; 531 } 532 else { 533 var mapZoom = this.map.getZoom(); 534 var projection = this.getProjection(); 535 var center = projection.fromLatLngToDivPixel(highlight.opts.center, mapZoom); 536 var radius = highlight.opts.radius; 537 var radial = projection.fromDivPixelToLatLng(new google.maps.Point(center.x, center.y + radius), mapZoom); // find a point that is the radius distance away in pixels from the ccenter point. 538 highlight.opts.radiusInMeters = google.maps.geometry.spherical.computeDistanceBetween(highlight.opts.center, radial); 539 } 540 541 if (highlight.shape) { 542 highlight.shape.setOptions(highlight.opts); 543 // we can use this if we don't care about other options changing : highlight.shape.setRadius(highlight.opts.radiusInMeters) 544 } 545 else { 546 highlight.shape = Drupal.gmap.factory.highlight(jQuery.extend({}, highlight.opts, {radius: highlight.opts.radiusInMeters})); // only pass radiusinmeters to g.m.circle. We keep the pixel radius in case we need to calculate again after a zoom 547 } 548 }; 549 highlightOverlay.prototype.activateHighlight = function (highlight) { 550 if (!highlight.shape) { 551 this.configHighlight(highlight); 552 this.calculateHighlight(highlight); 553 } 554 highlight.shape.setMap(this.map); 555 }; 556 highlightOverlay.prototype.deactivateHighlight = function (highlight) { 557 if (highlight.shape) { 558 highlight.shape.setMap(null); 559 } 560 }; 561 highlightOverlay.prototype.updateHighlight = function (highlight) { 562 if (highlight.shape) { 563 this.configHighlight(highlight); 564 this.calculateHighlight(highlight); 565 } 566 }; 567 568 // prepare a single highlight overlay to be used for all highlights 569 obj.bind('init', function (highlight) { 570 obj.highlightOverlay = new highlightOverlay(obj.map); 571 obj.highlightOverlay.setMap(obj.map); // this will trigger the onAdd() method, and the first draw() 572 }); 573 574 // set and remove map highlights 575 obj.bind('highlightAdd', function (highlight) { // if you activate an activated highlight, nothing happens. 576 obj.highlightOverlay.activateHighlight(highlight); 577 }); 578 obj.bind('highlightRemove', function (highlight) { 579 obj.highlightOverlay.deactivateHighlight(highlight); 580 }); 581 obj.bind('highlightUpdate', function (highlight) { 582 obj.highlightOverlay.updateHighlight(highlight); 583 }); 584 585 // Marker specific highlight events: 586 var highlightedMarkers = []; // remember markers that have been highlighted. so that we can un-highlight them all at one. The defaultVal behaviour is to allow only 1 marker highlighted at any time. 587 obj.bind('markerHighlight', function (marker) { 588 highlightedMarkers.push(marker); 589 590 // If the highlight arg option is used in views highlight the marker. 591 if (!marker.highlight) { 592 marker.highlight = {}; 593 } 594 if (!marker.highlight.color && obj.vars.styles.highlight_color) { 595 marker.highlight.color = '#' + obj.vars.styles.highlight_color; 596 } 597 marker.highlight.position = marker.marker.getPosition(); 598 obj.change('highlightAdd', -1, marker.highlight); 599 }); 600 obj.bind('markerUnHighlight', function (marker) { 601 if (marker.highlight) { 602 obj.change('highlightRemove', -1, marker.highlight); 603 delete marker.highlight; 604 } 605 }); 606 obj.bind('markerUnHighlightActive', function () { 607 var marker; 608 while (!!(marker = highlightedMarkers.pop())) { 609 obj.change('highlightRemove', -1, marker); 610 } 611 }); 612 613 /** 614 * Marker Binds 615 * 616 * Marker highlight code has been moved to this file from the marker.js 617 * 618 * Note that we rely on the obj.vars.behavior.highlight var to 619 * decide if should highlight markers on events. 620 * This decision could be made as an outer if conditional, instead 621 * of repeated inside each bind, but this arrangement allows for 622 * the behaviour to change, at a small cost. 623 */ 624 obj.bind('addmarker', function (marker) { 625 if (obj.vars.behavior.highlight) { 626 google.maps.event.addListener(marker.marker, 'mouseover', function () { 627 obj.change('markerHighlight', -1, marker); 628 }); 629 google.maps.event.addListener(marker.marker, 'mouseout', function () { 630 obj.change('markerUnHighlight', -1, marker); 631 }); 632 google.maps.event.addListener(marker.marker, 'mouseout', function () { 633 obj.change('markerUnHighlight', -1, marker); 634 }); 635 } 636 // If the highlight arg option is used in views highlight the marker. 637 if (marker.opts.highlight == 1) { 638 obj.change('markerHighlight', -1, marker); 639 } 640 }); 641 642// Originally I moved mouse highlights to the extra event binds before I realized that there is likely a usecase for highlights without enabling extra events 643// obj.bind('mouseovermarker', function(marker) { 644// if (obj.vars.behavior.highlight && marker) { 645// obj.change('markerHighlight',-1,marker); 646// } 647// }); 648// obj.bind('mouseoutmarker', function(marker) { 649// if (obj.vars.behavior.highlight && marker) { 650// obj.change('markerUnHighlight',-1,marker); 651// } 652// }); 653 654}); 655; 656/** 657 * @file 658 * GPolyLine / GPolygon manager 659 */ 660 661/*global Drupal, GLatLng, GPoint */ 662 663Drupal.gmap.map.prototype.poly = {}; 664 665/** 666 * Distance in pixels between 2 points. 667 */ 668Drupal.gmap.map.prototype.poly.distance = function (point1, point2) { 669 return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2)); 670}; 671 672/** 673 * Circle -- Following projection. 674 */ 675Drupal.gmap.map.prototype.poly.computeCircle = function (obj, center, point2) { 676 var numSides = 36; 677 var sideInc = 10; // 360 / 20 = 18 degrees 678 var convFactor = Math.PI / 180; 679 var points = []; 680 var radius = obj.poly.distance(center, point2); 681 // 36 sided poly ~= circle 682 for (var i = 0; i <= numSides; i++) { 683 var rad = i * sideInc * convFactor; 684 var x = center.x + radius * Math.cos(rad); 685 var y = center.y + radius * Math.sin(rad); 686 //points.push(obj.map.getCurrentMapType().getProjection().fromPixelToLatLng(new GPoint(x,y),obj.map.getZoom())); 687 points.push(new GPoint(x, y)); 688 } 689 return points; 690}; 691 692Drupal.gmap.map.prototype.poly.calcPolyPoints = function (center, radM, numPoints, sAngle) { 693 if (!numPoints) { 694 numPoints = 32; 695 } 696 if (!sAngle) { 697 sAngle = 0; 698 } 699 700 var d2r = Math.PI / 180.0; 701 var r2d = 180.0 / Math.PI; 702 var angleRad = sAngle * d2r; 703 // earth semi major axis is about 6378137 m 704 var latScale = radM / 6378137 * r2d; 705 var lngScale = latScale / Math.cos(center.latRadians()); 706 707 var angInc = 2 * Math.PI / numPoints; 708 var points = []; 709 for (var i = 0; i < numPoints; i++) { 710 var lat = parseFloat(center.lat()) + latScale * Math.sin(angleRad); 711 var lng = parseFloat(center.lng()) + lngScale * Math.cos(angleRad); 712 points.push(new GLatLng(lat, lng)); 713 angleRad += angInc; 714 } 715 716 // close the shape and return it 717 points.push(points[0]); 718 return points; 719}; 720;
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.