1/***************************************************************************** 2 * KmlMapParser.js 3 * KmlMapParser - A Google Maps API Extension 4 * Project: http://code.google.com/p/kmlmapparser/ 5 * Author: R. Raponi 6 * Version: 1.0 7 * 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * ----------------------------------------------------------------------------------- 21 * 22 * @param {Object} config Configuration options 23 * 24 * var grid = new KmlMapParser({ map: map, 25 * showSidebar: true, 26 * sidebarId: 'sideBar' 27 * } 28 * 29 * @param {Object} config Configuration options 30 * -------------------------- 31 * allFoldersOpen: true 32 * zoomLevel: 15 33 * zoomOnClick: true 34 * imageDirectory: 'http://localhost:8090/envistaExamples/resources/images' 35 * imageSize: {width: 32, height:32} 36 * imageHotspot: {x: 0, y:32} 37 * showImageShadow: true 38 * showSidebar: true 39 * sidebarId: 'sideBar' 40 * showSidebarDescriptions: true 41 * showOverlaysInSidebar: true 42 * showRootName: true 43 * showBubble: false 44 * showSidebarBubble: true 45 * highlightColor: 'ff0000' 46 * showFolders: false 47 * showMultiPointsAsMarkers: true 48 * useMapCenter: true 49 * afterParseFn: myCallbackFunction 50 * kml: ['../kmlFiles/sidebarMap.kml', '../kmlFiles/state_capitals.kml'] 51 * kmlFile: '../kmlFiles/sidebarMap.kml' < deprecated > 52 * 53 * 54 * sidebar CSS can be found in KmlMapParser.css 55 ******************************************************************************/ 56 57// Extend the global String object with a method to remove leading and trailing whitespace 58if (!String.prototype.trim) { 59 String.prototype.trim = function () { 60 return this.replace(/^\s+|\s+$/g, ''); 61 }; 62} 63 64 65KmlMapParser = function(config){ 66 67 //check and set config variables 68 if (config === undefined){ 69 throw 'KmlMapParser internal error: needs Configuration options especially the map!'; 70 } 71 72 this.origConfig = config; 73 this.config = config; 74 75 this.kmlFile = config.kml ? config.kml : config.kmlFile; 76 77 //TODO make map if not defined 78 this.map = config.map; 79 80 if (config.imageDirectory !== undefined){ 81 this.imageDirectory = config.imageDirectory; 82 } 83 84 this.sidebarId = config.sidebarId ? this.config.sidebarId : 'the_side_bar'; 85 this.showMarkers = (config.showMarkers!==undefined) ? this.config.showMarkers : true; 86 this.showSidebar = (config.showSidebar!==undefined) ? this.config.showSidebar : true; 87 this.showSidebarDescriptions = (config.showSidebarDescriptions!==undefined) ? this.config.showSidebarDescriptions : true; 88 89 this.showBubble = (config.showBubble!==undefined) ? this.config.showBubble : true; 90 if (this.showBubble){ 91 this.showSidebarBubble = (config.showSidebarBubble!==undefined) ? this.config.showSidebarBubble : false; 92 }else{ 93 this.showSidebarBubble = false; 94 } 95 96 this.showFolders = (config.showFolders!==undefined) ? this.config.showFolders : true;
97 if (this.showFolders){ 98 this.allFoldersOpen = (config.allFoldersOpen!==undefined) ? this.config.allFoldersOpen : undefined; 99 } 100 this.defaultImageSize = (config.imageSize!== undefined) ? this.config.imageSize : {width: 32, height:32}; 101 this.defaultHotspot = (config.imageHotspot!== undefined) ? this.config.imageHotspot : {x: 16, y:32}; 102 this.showImageShadow = (config.showImageShadow !== undefined) ? this.config.showImageShadow : true; 103 104 this.showMultiPointsAsMarkers = (config.showMultiPointsAsMarkers!==undefined) ? this.config.showMultiPointsAsMarkers : false; 105 this.showRootName = (config.showRootName!==undefined) ? this.config.showRootName : true; 106 107 this.useMapCenter = (config.useMapCenter!==undefined) ? this.config.useMapCenter : false; 108 if (this.useMapCenter){ 109 this.mapCenter = this.map.getCenter(); 110 } 111 112 this.defaultZoomLevel = (config.zoomLevel!==undefined) ? this.config.zoomLevel : 15; 113 this.shouldZoom = (config.zoomOnClick!==undefined) ? this.config.zoomOnClick : true; 114 115 if (config.highlightColor === undefined){ 116 this.highlightColor = '#aaffff'; 117 } else { 118 this.highlightColor = config.highlightColor; 119 } 120 121 if (config.markerIcon === undefined){ 122 this.markerIcon = ''; 123 } else { 124 this.markerIcon = config.markerIcon; 125 } 126 127 this.showOverlaysInSidebar = (config.showOverlaysInSidebar!==undefined) ? this.config.showOverlaysInSidebar : true; 128 129 if (config.afterParseFn === undefined){ 130 this.hasAfterParse = false;
131 } else { 132 this.hasAfterParse = true; 133 this.afterParseFn = config.afterParseFn; 134 } 135 136 //create the info window 137 this.infoWindow = new google.maps.InfoWindow(); 138 this.mapshapes = []; 139 this.folderIndex = 0; 140 this.placemarkIndex = 0; 141 this.overlayIndex = 0; 142 this.zindex=100; 143 144 if (this.kmlFile !== undefined){ 145 this.parse(this.kmlFile); 146 } 147}; 148 149KmlMapParser.prototype = { 150 151 /* 152 * Process one or more KML documents 153 */ 154 parse : function (urls) { 155 if (typeof urls === 'string') { 156 urls = [urls]; 157 } 158 this.docSet = { docs: [], remaining: urls.length}; 159 160 for (var i = 0; i < urls.length; i++) { 161 this.parseUrl(urls[i], i); 162 } 163 }, 164 165 166 /* 167 * parse and process one KML document 168 */ 169 parseUrl : function (url, num){ 170 var baseUrl = url.split('?')[0], 171 doc = { baseUrl: baseUrl, url: url, id: num }; 172 173 this.docSet.docs.push(doc); 174 175 var that = this, 176 render = this.render, 177 callback = function (responseXML) {render(responseXML, doc, that);}; 178 179 this.fetchXMLdoc(url, callback); 180 }, 181 182 183 /* 184 * Get the document associated with the id 185 * @param {Number or String} docId the document id is the index number of the KML url 186 * @return {Object} document 187 */ 188 getDocumentById : function (docId) { 189 var iDocId = (typeof docId === 'string') ? parseInt(docId, 10) : docId; 190 return this.docSet.docs[docId]; 191 }, 192 193 194 195 /* 196 * Show the map objects associated with a document 197 * by the documents id 198 * @param {String} docId 199 */ 200 hideDocumentById : function (docId) { 201 var doc = this.getDocumentById(docId); 202 if (doc && doc.isVisible){ 203 this.setVisibilityByDoc(doc, false); 204 } 205 }, 206 207 208 /* 209 * Show the map objects associated with a document 210 * by the documents id 211 * @param {String} docId 212 */ 213 showDocumentById : function (docId){ 214 var doc = this.getDocumentById(docId); 215 if (doc && !doc.isVisible ){ 216 this.setVisibilityByDoc(doc, true); 217 } 218 }, 219 220 221 /* 222 * Sets visibility on all map objects and the sidebar 223 * @param {Boolean} isVisible 224 */ 225 setVisibility : function (isVisible){ 226 this.setVisibilityOnMarkers(isVisible); 227 this.setOverlayVisibility(isVisible); 228 229 if (this.showSidebar && !!this.sidebarId){ 230 var side = document.getElementById(this.sidebarId); 231 if (side !== null){ 232 this.setVisibilitybyNode(side, isVisible); 233 } 234 } 235 }, 236 237 238 /* 239 * Sets visibility on all map markers and shapes 240 * @param {Boolean} isVisible 241 * @param {Number} docId (optional) 242 */ 243 setVisibilityOnMarkers : function (isVisible, docId){ 244 var ms = this.mapshapes, 245 mss, shapeId; 246 247 for ( shapeId in ms){ 248 if (ms.hasOwnProperty(shapeId)) { 249 mss = ms[shapeId]; 250 if ((docId !== undefined && mss.docId === docId ) || (docId === undefined)){ 251 this.setMapObjectVisibility(mss, isVisible); 252 } 253 } 254 } 255 }, 256 257 258 /* 259 * sets the visiblility on map objects 260 * by the documents id 261 * @param {Number} docId 262 * @param {boolean} isVisible 263 */ 264 setVisibilityByDoc : function (doc, isVisible) { 265 var docRoot = document.getElementById('doc-'+ doc.id), 266 i, overlayId, overlay; 267 268 if (doc !== undefined && doc.isVisible !== isVisible){ 269 //markers and shapes 270 this.setVisibilityOnMarkers(isVisible, doc.id); 271 272 //overlays 273 if (doc.hasOverlays){ 274 for (i = 0; i < doc.overlays.length; i++){ 275 this.setOverlayVisibility(doc.overlays[i].overlay, isVisible); 276 } 277 } 278 279 //folders 280 if (this.showSidebar && docRoot !== null){ 281 this.setVisibilitybyNode(docRoot, isVisible); 282 } 283 doc.isVisible = isVisible; 284 } 285 }, 286 287 288 /* 289 * set Overlay visibility on a marker or shape 290 * actually removes it form the map 291 * @param {Object} Overly 292 * @param {Boolean} isVisible 293 */ 294 setMapObjectVisibility: function (shape, isVisible) { 295 if ( typeof shape === 'object'){ 296 //shapes 297 if (isVisible){ 298 shape.setMap(this.map); 299 }else{ 300 shape.setMap(null); 301 } 302 } 303 }, 304 305 306 /* 307 * sets the overlay visibility by the documents id 308 * @param {Number} docId 309 * @param {Boolean} visibility 310 */ 311 setOverlayVisibilityByDocId : function (docId, isVisible){ 312 var doc = this.getDocumentById[docId]; 313 314 if (doc !== undefined && doc.hasOverlays){ 315 for (i = 0; i < doc.overlays.length; i++){ 316 this.setVisibilitybyOverlay(doc.overlays[i].overlay, isVisible); 317 } 318 } 319 }, 320 321 322 /* 323 * sets the overlay visibility by the overlays id 324 * @param {Number} overlayId 325 * @param {Boolean} visibility 326 */ 327 setOverlayVisibilityById: function (id, isVisible){ 328 var docs = this.docSet.docs, 329 doc, overlay, i, j; 330 331 if (docs.length > 0){ 332 for (i = 0; i < docs.length; i++){ 333 doc = docs[i]; 334 if (doc !== undefined && doc.hasOverlays){ 335 for (j = 0; j < doc.overlays.length; j++){
336 overlay = doc.overlays[j].overlay; 337 if (id && id === overlay.id_){ 338 this.setVisibilitybyOverlay(overlay, isVisible); 339 } 340 } 341 } 342 } 343 } 344 }, 345 346 347 /* 348 * set Overlay visibility 349 * @param {Object} Overly 350 * @param {Boolean} isVisible 351 */ 352 setVisibilitybyOverlay: function (overlay, isVisible) { 353 if (overlay !== undefined && overlay !== null){ 354 overlay.setVisibility(isVisible); 355 } 356 }, 357 358 359 /* 360 * sets all the visibility on all overlays 361 * @param {Boolean} isVisible 362 */ 363 setOverlayVisibility : function (isVisible) { 364 var docs = this.docSet.docs, 365 doc, overlay, i, j; 366 367 if (docs.length > 0){ 368 for (i = 0; i < docs.length; i++){ 369 doc = docs[i]; 370 if (doc !== undefined && doc.hasOverlays){ 371 for (j = 0; j < doc.overlays.length; j++){ 372 overlay = doc.overlays[j].overlay; 373 this.setVisibilitybyOverlay(overlay, isVisible); 374 } 375 } 376 } 377 } 378 }, 379 380 381 /* 382 * set Overlay opacity 383 * @param {Number} opacity 0.0 - 1.0. 384 */ 385 setOverlayOpacity: function (opacity) { 386 var docs = this.docSet.docs, 387 doc, overlay, i, j; 388 389 if (docs.length > 0){ 390 for (i = 0; i < docs.length; i++){ 391 doc = docs[i]; 392 if (doc !== undefined && doc.hasOverlays){ 393 for (j = 0; j < doc.overlays.length; j++){ 394 overlay = doc.overlays[j].overlay; 395 this.setOpacityByOverlay(overlay, opacity); 396 } 397 } 398 } 399 } 400 }, 401 402 403 /* 404 * sets the overlay opacity by the documents id 405 * @param {Number} docId 406 * @param {Number} opacity 0.0 - 1.0 407 */ 408 setOverlayOpacityByDocId : function (docId, opacity) { 409 var doc = this.getDocumentById[docId]; 410 411 if (doc !== undefined && doc.hasOverlays){ 412 for (i = 0; i < doc.overlays.length; i++){ 413 this.setOverlayOpacity(doc.overlays[i], opacity); 414 } 415 } 416 }, 417 418 419 /* 420 * set Overlay opacity 421 * @param {Object} Overly. 422 * @param {Number} opacity 0.0 - 1.0 423 */ 424 setOpacityByOverlay: function (overlay, opacity) { 425 this.setVisibilitybyOverlay(overlay, true); 426 overlay.setOpacity(opacity); 427 }, 428 429 430 /* 431 * clears Map of all object displayed on it and 432 * removes contents the side bar and destroys all references to the KML 433 * there is no recovery from this action except to re-parse the KML 434 */ 435 clearMap : function (){ 436 if (this.docSet && this.docSet.docs){ 437 var docs = this.docSet.docs, 438 ms = this.mapshapes, 439 doc, i, j, mss, shapeId, overlay, side; 440 441 if (docs.length > 0){ 442 for (i = 0; i < docs.length; i++){ 443 doc = docs[i]; 444 if (doc !== undefined && doc.hasOverlays){ 445 for (j = 0; j < doc.overlays.length; j++){ 446 overlay = doc.overlays[j].overlay; 447 overlay.setMap(null); 448 } 449 } 450 } 451 } 452 453 this.setVisibilityOnMarkers(false); 454 455 if (this.showSidebar && !!this.sidebarId){ 456 side = document.getElementById(this.sidebarId); 457 if (side !== null){ 458 side.innerHTML=''; 459 } 460 } 461 //reset 462 this.mapshapes = []; 463 this.folderIndex = 0; 464 this.placemarkIndex = 0; 465 this.zindex=100; 466 this.kmlFile=undefined; 467 this.docSet=undefined; 468 } 469 }, 470 471 472 /* 473 * Filter Sidebar 474 * @param {String} text string. 475 */ 476 filterSidebar: function (text) { 477 if (text === undefined || text === null ){ 478 text=''; 479 } 480 var t = text.toLowerCase().trim(), 481 isVisible, side; 482 483 if (this.showSidebar && !!this.sidebarId){ 484 side = document.getElementById(this.sidebarId); 485 if (side !== null){ 486 var nodes=side.getElementsByTagName("li"), 487 i, node, li; 488 489 if (nodes !== null && nodes.length > 0){ 490 for (i = 0; i < nodes.length; i++){ 491 node = nodes[i]; 492 if ( -1 !== node.className.search('placemark')) { 493 val = this.getNodeValue(node).toLowerCase(); 494 if ( t !== undefined){ 495 isVisible = (val.search(t) !== -1) ? true : false;
496 } 497 this.setVisibilitybyNode(node, isVisible); 498 } 499 } 500 } 501 } 502 } 503 }, 504 505 506 507 /* 508 * filter Markers on all map markers and shapes 509 * @param {Boolean} isVisible 510 * @param {String} text 511 */ 512 filterMarkers : function (text){ 513 if (text === undefined || text === null ){ 514 text=''; 515 } 516 var t = text.toLowerCase().trim(), 517 isVisible, 518 ms = this.mapshapes, 519 mss, shapeId, it; 520 521 for ( shapeId in ms){ 522 if (ms.hasOwnProperty(shapeId)) { 523 mss = ms[shapeId]; 524 if (t === undefined && t === ''){ 525 this.setMapObjectVisibility(mss, true); 526 }else{ 527 descrip = mss.description; 528 if ( descrip !== undefined){ 529 it = descrip.toLowerCase(); 530 isVisible = (it.search(t) !== -1) ? true : false; 531 this.setMapObjectVisibility(mss, isVisible); 532 } 533 } 534 } 535 } 536 }, 537 538 539 /* 540 * Filter Sidebar 541 * @param {String} text string. 542 */ 543 filterMap: function (text) { 544 if (text === undefined || text === null ){ 545 text=''; 546 } 547 var t = text.toLowerCase().trim(); 548 this.filterSidebar(t); 549 this.filterMarkers(t); 550 }, 551 552 553 /** 554 * Parses anXML string and returns the parsed document in a DOM data structure. 555 * Returns an empty DOM node if XML parsing is not supported in this browser. 556 * @param {string} str XML string. 557 * @return {Element|Document} DOM. 558 */ 559 xmlParse : function (str){ 560 if (typeof ActiveXObject !== 'undefined' && typeof GetObject !== 'undefined') { 561 var doc = new ActiveXObject('Microsoft.XMLDOM'); 562 doc.loadXML(str); 563 return doc; 564 } 565 if (typeof DOMParser !== 'undefined') { 566 return (new DOMParser()).parseFromString(str, 'text/xml'); 567 } 568 return createElement('div', null); 569 }, 570 571 572 fetchXMLdoc : function (url, callback){ 573 var callBack = callback, 574 xmlParse = this.xmlParse, 575 req = false; 576 577 if (window.XMLHttpRequest && !(window.ActiveXObject)) { 578 req = new window.XMLHttpRequest(); 579 } else if (window.ActiveXObject) { 580 req = new window.ActiveXObject('Microsoft.XMLHTTP'); 581 } 582 583 if (req){ 584 req.open('GET', url, true); 585 req.onreadystatechange = function (){ 586 if (req.readyState === 4) { 587 if (!!this.xhrtimeout){ 588 clearTimeout(this.xhrtimeout); 589 } 590 if (req.status === 200) { 591 callBack(xmlParse(req.responseText)); 592 } else { 593 //this.log('There was a problem retrieving the KML document for: ' + url + ' ('+ req.statusText + ' : ' req.statusText+ '). '); 594 callBack(); 595 } 596 } 597 }; 598 this.xhrtimeout = setTimeout( function(){callBack();}, 120000); 599 req.send(''); 600 } else { 601 callBack(null); 602 } 603 }, 604 605 606 //private 607 setVisibilitybyNode : function(node, isVisible) { 608 if (isVisible){ 609 node.style.display='block'; 610 }else{ 611 node.style.display='none'; 612 } 613 }, 614 615 616 getNodeValue : function(node) { 617 if (node === undefined || node === null) { 618 return ''; 619 } else { 620 return (node.innerText || node.text || node.textContent).trim(); 621 } 622 }, 623 624 625 getBooleanValue : function(node) { 626 var val = this.getNodeValue(node); 627 628 switch(val.toLowerCase()){ 629 case "true": case "yes": case "1": return true; 630 case "false": case "no": case "0": case null: return false; 631 default: return true; 632 } 633 }, 634 635 636 //private 637 findStyle: function(node, styles, styleId){ 638 var style; 639 640 if (styles[styleId] === undefined){ 641 styles[styleId] = { width: 4, fill: true, outline: true }; 642 } 643 644 var styleNodes = node.getElementsByTagName('IconStyle'); 645 if (styleNodes && styleNodes.length > 0){ 646 style = styleNodes[0]; 647 648 var hotspot = style.getElementsByTagName('hotSpot')[0], 649 scale = this.getNodeValue(style.getElementsByTagName('scale')[0]), 650 w = parseInt(this.defaultImageSize.width, 10), 651 h = parseInt(this.defaultImageSize.height, 10), 652 x = parseInt(this.defaultHotspot.x, 10), 653 y = parseInt(this.defaultHotspot.y, 10); 654 655 // the default google maps icon is 32 x 32; default bottom center is 16,32; 656 // hotspots are assumed to be pixels 657 if (hotspot !== null && hotspot !== undefined){ 658 x = parseInt(hotspot.getAttribute('x'), 10); 659 y = parseInt(hotspot.getAttribute('y'), 10); 660 } 661 if (!isNaN(scale)){ 662 scale = 1.0; 663 } 664 665 styles[styleId] = { 666 href: this.getNodeValue(style.getElementsByTagName('href')[0]), 667 size: {width: w, height: h}, 668 scale: scale, 669 anchor: {x: x, y: y} 670 }; 671 } 672 673 styleNodes = node.getElementsByTagName('LineStyle'); 674 if (styleNodes && styleNodes.length > 0){ 675 style = styleNodes[0]; 676 styles[styleId].color = this.getNodeValue(style.getElementsByTagName('color')[0]); 677 styles[styleId].width = this.getNodeValue(style.getElementsByTagName('width')[0]); 678 } 679 680 styleNodes = node.getElementsByTagName('PolyStyle'); 681 if (styleNodes && styleNodes.length > 0){ 682 style = styleNodes[0]; 683 styles[styleId].color = this.getNodeValue(style.getElementsByTagName('color')[0]); 684 styles[styleId].fill = this.getBooleanValue(style.getElementsByTagName('fill')[0]); 685 styles[styleId].outline = this.getBooleanValue(style.getElementsByTagName('outline')[0]); 686 } 687 688 return styles[styleId]; 689 }, 690 691 692 convertStyles : function(styles){ 693 var styleId; 694 for ( styleId in styles){ 695 if (styles.hasOwnProperty(styleId)){ 696 this.convertKmlStyle(styles[styleId]); 697 } 698 } 699 return styles; 700 }, 701 702 703 /* 704 * Converts the KML style into a google maps marker image with a 32 x 32 default style 705 * 706 * see http://www.mymapsplus.com/Markers for a visual marker reference 707 */ 708 convertKmlStyle : function (style) { 709 var zeroPoint = new google.maps.Point(0,0), 710 size = style.size, 711 scale = style.scale, 712 anchor = style.anchor; 713 714 if (style && style.href !== undefined && style.href !== '') { 715 var anchorPoint = new google.maps.Point(anchor.x * scale, anch
715or.y * scale), 716 imageSize = new google.maps.Size(size.width * scale, size.height * scale), 717 href = style.href; 718 719 if (this.imageDirectory !== undefined){ 720 var hrefs = href.split('/'), 721 image; 722 723 if ( hrefs.length > 0){ 724 image = hrefs[hrefs.length-1]; 725 style.href = this.imageDirectory + '/' + image; 726 href = style.href; 727 } 728 } 729 730 //now create marker image 731 style.icon = new google.maps.MarkerImage(href, imageSize, zeroPoint, anchorPoint, imageSize); 732 733 if (this.showImageShadow){ 734 // Look for a shadow on a standard marker (same as the dot marker) or push-pin; 735 var regEx = /\/(blue|red|green|ltblue|lightblue|yellow|purple|pink)\.png/, 736 shadowSize = new google.maps.Size(size.width * scale * 2, size.height * scale); 737 738 if (regEx.test(href)) { 739 style.shadow = new google.maps.MarkerImage('http://maps.google.com/mapfiles/ms/micons/msmarker.shadow.png', 740 shadowSize, 741 zeroPoint, 742 anchorPoint); 743 } else if (href.indexOf('-pushpin.png') > -1) { 744 style.shadow = new google.maps.MarkerImage('http://maps.google.com/mapfiles/ms/micons/pushpin_shadow.png', 745 shadowSize, 746 zeroPoint, 747 anchorPoint); 748 } 749 } 750 } 751 }, 752 753 754 render : function (responseXML, doc, scope) { 755 if (!responseXML) { 756 // Error retrieving the data 757 } else if (!doc) { 758 throw 'KmlMapParser error: render called with null document'; 759 } else { //no errors 760 var i, styles = {}; 761 doc.isRoot = true; 762 doc.folders = []; 763 doc.placemarks = []; 764 doc.overlays = []; 765 doc.isVisible = true; 766 767 // get KML styles if any 768 var styleId, pnNode, styleNode, styleNodeId, 769 nodes = responseXML.getElementsByTagName('Style'), 770 nodeCount = nodes.length; 771 772 for (i = 0; i < nodeCount; i++) { 773 styleNode = nodes[i]; 774 styleNodeId = styleNode.getAttribute('id'); 775 776 if (styleNodeId !== null) { 777 styleId = '#' + styleNodeId; 778 scope.findStyle(styleNode, styles, styleId); 779 } 780 } 781 782 doc.styles = scope.convertStyles(styles); 783 784 //get the file name 785 var s = doc.baseUrl.lastIndexOf('/'), 786 docFileName = doc.baseUrl; 787 788 if (s > -1){ 789 docFileName = doc.baseUrl.slice(s+1); 790 } 791 doc.fileName = docFileName; 792 793 // get the doc name if it does not have one use the file name 794 var docName = responseXML.getElementsByTagName('name')[0], 795 docTag = docName.parentNode.tagName; 796 797 if (docTag === 'Document' || docTag === 'document'){ 798 docName = scope.getNodeValue(docName); 799 }else{ 800 var p = docFileName.lastIndexOf('.'); 801 docName = (p > -1) ? docFileName.substring(0,p) : docFileName; 802 } 803 doc.name = docName; 804 805 // get folder names to show in the sidebar 806 var folderNodes = responseXML.getElementsByTagName('Folder'), 807 placemarkNodes, 808 parentFolder = doc; 809 810 //no folders found only placemarks 811 if (folderNodes === undefined || (folderNodes && folderNodes.length ===0)){ 812 doc.hasFolders = false; 813 placemarkNodes = responseXML.getElementsByTagName('Placemark'); 814 815 if (placemarkNodes && placemarkNodes.length > 0){ 816 doc.hasPlacemarks = true; 817 scope.findPlacemarks(doc, placemarkNodes, doc); 818 }else{ 819 doc.hasPlacemarks = false;
820 } 821 822 var groundNodes = responseXML.getElementsByTagName('GroundOverlay'); 823 if (groundNodes && groundNodes.length > 0){ 824 doc.hasOverlays = true; 825 scope.findOverlays(doc, groundNodes, doc); 826 } else { 827 doc.hasOverlays = false; 828 } 829 830 } else { 831 doc.hasFolders = true; 832 doc.hasPlacemarks = false; 833 doc.hasOverlays = false; 834 scope.processChildren(doc, responseXML.documentElement); 835 } 836 scope.createMapObjects(doc); 837 838 if (scope.showSidebar){ 839 scope.createSidebar(doc); 840 } 841 842 scope.docSet.remaining -= 1; 843 if (scope.docSet.remaining === 0) { 844 if (scope.useMapCenter){ 845 scope.map.setCenter(scope.mapCenter); 846 } else { 847 scope.map.fitBounds(scope.bounds); 848 } 849 if (scope.hasAfterParse){ 850 scope.afterParseFn(doc); 851 } 852 } 853 } 854 }, 855 856 857 /* 858 * parses kml lookinging for folders and placemarks 859 */ 860 processChildren : function(doc, node, parentFolder){ 861 var i, child, pf; 862 for (i = 0; i < node.childNodes.length; i++){ 863 child = node.childNodes[i]; 864 if ( child.nodeType === 1){ 865 switch (child.tagName) { 866 case 'Folder' : 867 pf = parentFolder!==undefined ? parentFolder : doc; 868 pf.hasFolders=true; 869 this.findFolders(doc, child, pf); 870 break; 871 case 'Placemark' : 872 pf = parentFolder!==undefined ? parentFolder : doc; 873 pf.hasPlacemarks=true; 874 this.createPlacemark(doc, child, pf); 875 break; 876 case 'GroundOverlay' : 877 pf = parentFolder!==undefined ? parentFolder : doc; 878 pf.hasOverlays=true; 879 this.findOverlays(doc, child, pf); 880 break; 881 case 'Document' : 882 this.processChildren(doc, child); 883 break; 884 case 'Kml' : 885 this.processChildren(doc, child); 886 break; 887 default: 888 break; 889 } 890 } 891 } 892 return; 893 }, 894 895 896 /* 897 * finds and creates a folder 898 */ 899 findFolders : function(doc, folderNode, parentFolder){ 900 var placemarkNodes, groundNodes, 901 parentName = parentFolder.name, 902 pnNode = folderNode.parentNode, 903 pnNodeName = this.getNodeValue(pnNode.getElementsByTagName('name')[0]), 904 folderName = this.getNodeValue(folderNode.getElementsByTagName('name')[0]), 905 open = (this.allFoldersOpen !== undefined) ? this.allFoldersOpen : this.getBooleanValue(folderNode.getElementsByTagName('open')[0]), 906 folderId = doc.id + '-' + this.folderIndex++, 907 folder = { id: folderId, 908 name: folderName, 909 isOpen: open, 910 folders: [], 911 hasFolders : false, 912 placemarks: [], 913 hasPlacemarks: false, 914 hasOverlays: false 915 }, 916 subNodes = folderNode.getElementsByTagName('Folder'); 917 918 if (subNodes && subNodes.length > 0){ 919 folder.hasFolders = true; 920 parentFolder.folders.push(folder); 921 this.processChildren(doc, folderNode, folder); 922 } else { 923 //this is a leaf now look for placemarks 924 placemarkNodes = folderNode.getElementsByTagName('Placemark'); 925 if (placemarkNodes && placemarkNodes.length > 0){ 926 folder.hasPlacemarks = true; 927 this.findPlacemarks(doc, placemarkNodes, folder, parentFolder); 928 } else { 929 folder.hasPlacemarks = false;
930 } 931 //look for overlays 932 groundNodes = folderNode.getElementsByTagName('GroundOverlay'); 933 if (groundNodes && groundNodes.length > 0){ 934 folder.hasOverlays = true; 935 this.findOverlays(doc, groundNodes, folder, parentFolder); 936 } else { 937 folder.hasOverlays = false; 938 } 939 parentFolder.folders.push(folder); 940 } 941 }, 942 943 944 /* 945 * parses leaf or root placemarks 946 */ 947 findPlacemarks : function(doc, placemarkNodes, folder, parentFolder){ 948 var pm, node, nodeName; 949 for (pm = 0; pm < placemarkNodes.length; pm++){ 950 node = placemarkNodes[pm]; 951 nodeName = this.getNodeValue(node.getElementsByTagName('name')[0]); 952 folder.hasPlacemarks = true; 953 doc.hasPlacemarks = true; 954 if (nodeName !== folder.name){ 955 this.createPlacemark(doc, node, folder); 956 } else { 957 folder.hasFolders = false; 958 this.createPlacemark(doc, node, folder); 959 } 960 } 961 }, 962 963 964 /* 965 * create a Placemark 966 */ 967 createPlacemark : function(doc, placemarkNode, folder){ 968 var style, 969 docStyles = doc.styles, 970 placemark = { folderId: folder.id, 971 folderName: folder.name, 972 name: this.getNodeValue(placemarkNode.getElementsByTagName('name')[0]), 973 description: this.getNodeValue(placemarkNode.getElementsByTagName('description')[0]), 974 styleUrl: this.getNodeValue(placemarkNode.getElementsByTagName('styleUrl')[0]), 975 shape: [] 976 }, 977 inlineStyles = placemarkNode.getElementsByTagName('Style'), 978 regex = /^https?:\/\//, 979 multi = placemarkNode.getElementsByTagName('MultiGeometry'); 980 981 //add style to placemark 982 placemark.style = doc.styles[placemark.styleUrl] || { width: 4, fill: true, outline: true }; 983 984 // inline style overrides shared style 985 if (inlineStyles && (inlineStyles.length > 0)){ 986 style = this.findStyle(node,docStyles,'inline'); 987 this.convertKmlStyle(style); 988 if (style){ placemark.style = style;} 989 } 990 991 //look for link in placemark 992 if (regex.test(placemark.description)){ 993 placemark.description = ['<a href="', placemark.description, '">', placemark.description, '</a>'].join(''); 994 } 995 996 // check if it is a MultiGeometry 997 placemark.multi = (multi.length > 0) ? true : false; 998 999 // process coordinates 1000 this.processPlacemarkCoords(placemark, placemarkNode); 1001 placemark.id=folder.id+'-'+this.placemarkIndex++; 1002 1003 if (folder !== doc){ 1004 doc.placemarks.push(placemark); 1005 } 1006 folder.placemarks.push(placemark); 1007 }, 1008 1009 1010 1011 /* 1012 * create Google Maps objects and shapes. 1013 * 1014 */ 1015 createMapObjects : function(doc){ 1016 if (!!google.maps) { 1017 var pm, i, j, placemark, shapes, shape, latlng, coords, coord, path, bounds, poly, 1018 found = false, 1019 placemarks = doc.placemarks; 1020 1021 //create bounds for the map 1022 this.bounds = this.bounds || new google.maps.LatLngBounds(); 1023 1024 //loop through the placemarks 1025 for (pm = 0; pm <placemarks.length; pm++){ 1026 placemark = placemarks[pm]; 1027 shapes = placemark.shape; 1028 //loop through the shapes lat/lng 1029 for (i = 0; i < shapes.length; i++){ 1030 shape = shapes[i]; 1031 if (shape.point){ 1032 coord = shape.point.coordinates[0]; 1033 latlng = new google.maps.LatLng(coord.lat, coord.lng); 1034 this.bounds.extend(latlng); 1035 placemark.points = placemark.points || []; 1036 marker = this.createMarker(doc, placemark, latlng, i); 1037 marker.active = true; 1038 } else if (shape.circle){ 1039 coord = shape.circle.coordinates[0]; 1040 latlng = new google.maps.LatLng(coord.lat, coord.lng); 1041 this.bounds.extend(latlng); 1042 placemark.circles = placemark.circles || []; 1043 circle = this.createCircle(doc, placemark, latlng, i); 1044 circle.active = true; 1045 }else if (shape.linestring || shape.polygon){ 1046 coords = shape.linestring ? shape.linestring[0].coordinates : shape.polygon[0].coordinates; 1047 path = []; 1048 bounds = new google.maps.LatLngBounds(); 1049 for (j = 0; j < coords.length; j++){ 1050 coord = coords[j]; 1051 latlng = new google.maps.LatLng(coord.lat, coord.lng); 1052 path.push(latlng); 1053 bounds.extend(latlng); 1054 } 1055 if (shape.linestring){ 1056 placemark.lines = placemark.lines || []; 1057 poly = this.createPolyline(doc, placemark, path, bounds, i); 1058 } else { //shape.polygon 1059 placemark.areas = placemark.areas || []; 1060 poly = this.createPolygon(doc, placemark, path, bounds, i); 1061 } 1062 poly.active = true; 1063 this.bounds.union(bounds); 1064 } 1065 } 1066 } 1067 } 1068 }, 1069 1070 1071 /* 1072 * create a Marker on the map 1073 */ 1074 createMarker : function(doc, placemark, latlng, shapeNumber){ 1075 var content= '<div><h3>' + placemark.name + '</h3><div>' + placemark.description + '</div></div>', 1076 marker, 1077 markerOptions = {folderId: placemark.folderId, 1078 map: this.map, 1079 position: latlng, 1080 title: placemark.name, 1081 zIndex: this.zindex++, 1082 description: content, 1083 clickable: true 1084 }; 1085 1086 if (placemark.style.icon !== undefined){ 1087 markerOptions.icon = placemark.style.icon; 1088 } 1089 if (placemark.style.shadow !== undefined){ 1090 markerOptions.shadow = placemark.style.shadow; 1091 } 1092 // Forzatura per CoopCulture 1093 markerOptions.icon=this.config.markerIcon; 1094 1095 marker = new google.maps.Marker(markerOptions); 1096 1097 marker.id = placemark.id+'-'+shapeNumber; 1098 marker.docId = doc.id; 1099 1100 if (this.showBubble){ 1101 var that = this; 1102 google.maps.event.addListener(marker, 'click', function(){ 1103 that.openBubble(marker); 1104 }); 1105 } 1106 1107 this.mapshapes[marker.id]=marker; 1108 placemark.marker=marker; 1109 placemark.points.push(marker); 1110 marker.setMap(this.map); 1111 1112 return marker; 1113 1114 }, 1115 1116 1117 /* 1118 * create a circle on the map 1119 */ 1120 createCircle : function(doc, placemark, latlng, shapeNumber) { 1121 var content= '<div><h3>' + placemark.name + '</h3><div>' + placemark.description + '</div></div>', 1122 rgb = this.getRGBColorTransparency(placemark.style.color), 1123 circleOptions = { map: this.map, 1124 center: latlng, 1125 radius: 20, 1126 position: latlng, 1127 strokeColor: rgb.color, 1128 strokeWeight: placemark.style.width, 1129 strokeOpacity: rgb.opacity, 1130 fillColor: rgb.color, 1131 fillOpacity: rgb.opacity, 1132 title: placemark.name, 1133 description: content, 1134 folderId: placemark.folderId, 1135 zIndex: this.zindex++ 1136 }, 1137 circle = new google.maps.Circle(circleOptions); 1138 1139 circle.id = placemark.id+'-'+shapeNumber; 1140 circle.docId = doc.id; 1141 1142 if (this.showBubble){ 1143 var that = this; 1144 google.maps.event.addListener(circle, 'click', function() { 1145 that.openBubble(circle); 1146 }); 1147 } 1148 this.mapshapes[circle.id]=circle; 1149 placemark.circles.push(circle); 1150 placemark.mapObject = circle; 1151 circle.setMap(this.map); 1152
1153 return circle; 1154 }, 1155 1156 1157 /* 1158 * create a polyline on the map 1159 */ 1160 createPolyline : function(doc, placemark, path, bounds, shapeNumber) { 1161 var point = path[Math.floor(path.length/2)], 1162 content= '<div><h3>' + placemark.name + '</h3><div>' + placemark.description + '</div></div>', 1163 rgb = this.getRGBColorTransparency(placemark.style.color), 1164 polyOptions = { map: this.map, 1165 path: path, 1166 position: point, 1167 strokeColor: rgb.color, 1168 strokeWeight: placemark.style.width, 1169 strokeOpacity: rgb.opacity, 1170 title: placemark.name, 1171 description: content, 1172 folderId: placemark.folderId, 1173 zIndex: this.zindex++}, 1174 poly = new google.maps.Polyline(polyOptions); 1175 1176 poly.bounds = bounds; 1177 poly.id = placemark.id+'-'+shapeNumber; 1178 poly.docId = doc.id; 1179 1180 if (this.showBubble){ 1181 var that = this; 1182 google.maps.event.addListener(poly, 'click', function() { 1183 that.openBubble(poly); 1184 }); 1185 } 1186 1187 this.mapshapes[poly.id] = poly; 1188 placemark.lines.push(poly); 1189 placemark.mapObject = poly; 1190 poly.setMap(this.map); 1191 1192 return poly; 1193 }, 1194 1195 1196 1197 /** 1198 * create a polygon on the map 1199 * 1200 */ 1201 createPolygon : function(doc, placemark, paths, bounds,shapeNumber) { 1202 var point = bounds.getCenter(), 1203 content= '<div><h3>' + placemark.name + '</h3><div>' + placemark.description + '</div></div>', 1204 rgb = this.getRGBColorTransparency(placemark.style.color); 1205 1206 var polyOptions = { map: this.map, 1207 paths: paths, 1208 title: placemark.name, 1209 position: point, 1210 strokeColor: rgb.color, 1211 strokeWeight: placemark.style.width, 1212 strokeOpacity: rgb.opacity, 1213 fillColor: rgb.color, 1214 fillOpacity: rgb.opacity, 1215 description: content, 1216 folderId: placemark.folderId, 1217 zIndex: this.zindex++ 1218 }; 1219 1220 var poly = new google.maps.Polygon(polyOptions); 1221 1222 poly.bounds = bounds; 1223 poly.id = placemark.id+'-'+shapeNumber; 1224 poly.docId = doc.id; 1225 1226 if (this.showBubble){ 1227 var that = this; 1228 google.maps.event.addListener(poly, 'click', function() { 1229 that.openBubble(poly); 1230 }); 1231 } 1232 1233 this.mapshapes[poly.id]= poly; 1234 placemark.areas.push(poly); 1235 placemark.mapObject = poly; 1236 poly.setMap(this.map); 1237 1238 return poly; 1239 }, 1240 1241 /** 1242 * process the shape coordinates 1243 * linearring is really a polygon 1244 */ 1245 processShape : function(geometry, placemark, node){ 1246 switch(geometry) { 1247 case "MultiGeometry": 1248 this.processPlacemarkCoords(placemark, node); 1249 break; 1250 case "LinearRing": 1251 placemark.shape.push({ polygon: this.getCoords(node,"LinearRing")}); 1252 break; 1253 case "Polygon": 1254 placemark.shape.push({ polygon: this.getCoords(node,"LinearRing")}); 1255 break; 1256 case "Point": 1257 placemark.shape.push({ point: this.getCoords(node, "Point")[0]}); 1258 break; 1259 case "Circle": 1260 placemark.shape.push({ circle: this.getCoords(node, "Point")[0]}); 1261 break; 1262 case "LineString": 1263 placemark.shape.push({ linestring: this.getCoords(node,"LineString")}); 1264 break; 1265 default: 1266 break; 1267 } 1268 return placemark; 1269 }, 1270 1271 1272 /* 1273 * 1274 * process Placemark Coordinates 1275 * multi geometries can be made up of multiple points, lines and polygons 1276 * 1277 */ 1278 processPlacemarkCoords : function (placemark, node){ 1279 var shapeNodes = node.getElementsByTagName('Point'), 1280 i; 1281 1282 if ( shapeNodes.length > 0){ 1283 for (i=0; i< shapeNodes.length; i++ ){ 1284 if (placemark.multi && !this.showMultiPointsAsMarkers){ 1285 this.processShape('Circle', placemark, shapeNodes[i]); 1286 }else{ 1287 this.processShape('Point', placemark, shapeNodes[i]); 1288 } 1289 } 1290 } 1291 1292 this.processShapeNodes(placemark, node, 'LineString'); 1293 this.processShapeNodes(placemark, node, 'LinearRing'); 1294 this.processShapeNodes(placemark, node, 'Polygon'); 1295 1296 return placemark; 1297 }, 1298 1299 1300 /* 1301 * process the shape node for a given KML shape 1302 * except for points 1303 */ 1304 processShapeNodes : function (placemark, node, shape) { 1305 var shapeNodes = node.getElementsByTagName(shape); 1306 if ( shapeNodes.length > 0){ 1307 for (i=0; i< shapeNodes.length; i++ ){ 1308 this.processShape(shape, placemark, shapeNodes[i]); 1309 } 1310 } 1311 }, 1312 1313 1314 /* 1315 * get coordinates for lat/longs and return them in an array (currently, altitude is not being used). 1316 */ 1317 getCoords : function (node, tag) { 1318 var coordListA = [], i, j, coords, path, pathLength, coordList, k, 1319 coordNodes = node.getElementsByTagName('coordinates'); 1320 1321 if (!coordNodes){ 1322 return [{coordinates: []}]; 1323 } 1324 1325 for (j=0; j<coordNodes.length;j++){ 1326 coords = this.getNodeValue(coordNodes[j]).trim(); 1327 coords = coords.replace(/,\s+/g, ','); 1328 path = coords.split(/\s+/g); 1329 pathLength = path.length; 1330 coordList = []; 1331 for (k = 0; k < pathLength; k++){ 1332 coords = path[k].split(','); 1333 coordList.push({ lat: parseFloat(coords[1]), lng: parseFloat(coords[0]), alt: parseFloat(coords[2])}); 1334 } 1335 coordListA.push({coordinates: coordList}); 1336 } 1337 1338 return coordListA; 1339 }, 1340 1341 1342 /* 1343 * find map overlays 1344 */ 1345 findOverlays: function (doc, groundNodes, folder, parentFolder) {
1346 var node, groundOverlay, color, overlay, id; 1347 1348 doc.overlays = doc.overlays || []; 1349 for (i = 0; i < groundNodes.length; i++) { 1350 node = groundNodes[i]; 1351 1352 // Init the ground overlay object 1353 groundOverlay = { name: this.getNodeValue(node.getElementsByTagName('name')[0]), 1354 description: this.getNodeValue(node.getElementsByTagName('description')[0]), 1355 icon: {href: this.getNodeValue(node.getElementsByTagName('href')[0])}, 1356 latLonBox: { north: parseFloat(this.getNodeValue(node.getElementsByTagName('north')[0])), 1357 east: parseFloat(this.getNodeValue(node.getElementsByTagName('east')[0])), 1358 south: parseFloat(this.getNodeValue(node.getElementsByTagName('south')[0])), 1359 west: parseFloat(this.getNodeValue(node.getElementsByTagName('west')[0]))} 1360 }; 1361 1362 //look to see if the overlay has an id 1363 id = node.getAttribute('id'); 1364 groundOverlay.id = (id !== null) ? id : 'overlayview-'+ this.overlayIndex++; 1365 1366 //get bounds 1367 var box = groundOverlay.latLonBox, 1368 bounds = new google.maps.LatLngBounds(new google.maps.LatLng(box.south, box.west), 1369 new google.maps.LatLng(box.north, box.east)); 1370 groundOverlay.bounds = bounds; 1371 1372 if (this.bounds) { 1373 this.bounds.union(bounds); 1374 } 1375 1376 // Opacity is encoded in the kml color node 1377 color = this.getNodeValue(node.getElementsByTagName('color')[0]); 1378 if ((color !== '') && (color.length === 8)) { 1379 var rgb = this.getRGBColorTransparency(color); 1380 this.overlayOpacity = rgb.opacity; 1381 } 1382 1383 if (groundOverlay.opacity === undefined) { 1384 groundOverlay.opacity = 0.7; 1385 this.overlayOpacity = 0.7; 1386 } 1387 1388 this.createOverlay(doc, groundOverlay, folder); 1389 } 1390 }, 1391 1392 1393 /* 1394 * Add a ProjectedOverlay to the map from a groundOverlay KML object 1395 */ 1396 createOverlay : function (doc, groundOverlay, folder){ 1397 if (!window.KmlOverlayView){ 1398 throw 'KmlMapParser error: KmlOverlayView not found while rendering GroundOverlay from KML'; 1399 } 1400 var overlay = new KmlOverlayView({ map: this.map, href: groundOverlay.icon.href, percentOpacity: groundOverlay.opacity, bounds: groundOverlay.bounds, id: groundOverlay.id}); 1401 1402 groundOverlay.overlay = overlay; 1403 groundOverlay.id = overlay.id_; 1404 1405 if (folder !== undefined) { 1406 folder.overlays = folder.overlays || []; 1407 groundOverlay.folderId = folder.id; 1408 groundOverlay.folderName = folder.name; 1409 folder.overlays.push(groundOverlay); 1410 } 1411 1412 if (folder !== doc){ 1413 doc.overlays.push(groundOverlay); 1414 doc.hasOverlays=true; 1415 } 1416 1417 return overlay; 1418 }, 1419 1420 1421 createSidebar : function(doc){ 1422 if (!!this.sidebarId){ 1423 var childFolders = doc.folders, i, placemarks, pm, folder, folderName, 1424 side = document.getElementById(this.sidebarId), id, 1425 contents = '', 1426 innerContents =''; 1427 folderName = doc.name; 1428 1429 if (side !== null){
1430 if (this.showFolders && doc.hasFolders){ 1431 innerContents += this.addSidebarFolder(folderName, doc.folders); 1432 } else { 1433 placemarks = doc.placemarks; 1434 innerContents += this.addSidebarList(placemarks); 1435 1436 //overlays 1437 overlays = doc.overlays; 1438 if (this.showOverlaysInSidebar && overlays !== undefined){ 1439 innerContents += this.addSidebarOverlayList(overlays); 1440 } 1441 } 1442 if (this.showRootName && innerContents !==''){ 1443 contents += '<li class="docroot" id="doc-'+doc.id+'" style="display:block"><span class="open"></span>'+ folderName +'<ul>'+ innerContents + '</ul></li>'; 1444 } else if (innerContents !== ''){ 1445 contents += '<li class="docroot" id="doc-'+doc.id+'" style="display:block"><ul>'+ innerContents + '</ul></li>'; 1446 } 1447 1448 var root = document.getElementById('root'); 1449 if (root !== null){ 1450 var c = document.createElement('div'); 1451 c.innerHTML=contents; 1452 root.appendChild(c); 1453 } else { 1454 side.innerHTML = '<ul id="root" >'+ contents + '</ul>'; 1455 1456 //add click listener 1457 var scope=this, 1458 clickSidebar = function(e){ 1459 var t, child, className; 1460 if (!e){ 1461 t = window.event.srcElement; 1462 className = window.event.srcElement.className; 1463 }else{ 1464 t = e.target; 1465 if (!t){ 1466 t = window.event.srcElement; 1467 className = window.event.srcElement.className; 1468 }else{ 1469 className = t.className; 1470 } 1471 } 1472 1473 switch(className) { 1474 case "placemark": 1475 if (scope.showBubble){ 1476 if (scope.showSidebarBubble){ 1477 scope.openBubbleById(t.id); 1478 }else { 1479 scope.hilightShapesById(t.id); 1480 } 1481 } 1482 break; 1483 case "open": 1484 t.className='closed'; 1485 scope.setVisibilitybyNode(t.parentNode.getElementsByTagName('ul')[0], false); 1486 break; 1487 case "closed": 1488 t.className='open'; 1489 scope.setVisibilitybyNode(t.parentNode.getElementsByTagName('ul')[0], true); 1490 break; 1491 case "checked": 1492 t.className='unchecked'; 1493 scope.setOverlayVisibilityById(t.id.replace('-check', ''),false); 1494 break; 1495 case "unchecked": 1496 t.className='checked'; 1497 scope.setOverlayVisibilityById(t.id.replace('-check', ''),true); 1498 break; 1499 } 1500 }; 1501 1502 if (side.addEventListener){ 1503 side.addEventListener('click',clickSidebar,false); 1504 } else if (side.attachEvent){ 1505 side.attachEvent('onclick',clickSidebar); 1506 } 1507 }//end root null 1508 } 1509 } 1510 }, 1511 1512 1513 /** 1514 * adds an entry to the sidebar 1515 */ 1516 addSidebarFolder : function(parentName, childFolders) { 1517 var folder, i, folderName, cls, 1518 contents='', folderContents='', placemarkContents='', 1519 overlayContents='', placemarks, sameName = false;
1520 1521 if (!!parentName && childFolders.length > 0){ 1522 for (i = 0; i < childFolders.length; i++){ 1523 folder = childFolders[i]; 1524 folderName = folder.name; 1525 cls = folder.isOpen ? 'open' : 'closed'; 1526 if (folder.hasPlacemarks ){ 1527 placemarks = folder.placemarks; 1528 if (folderName === placemarks[0].name){ 1529 sameName = true; 1530 } else{ 1531 sameName = false; 1532 } 1533 placemarkContents = this.addSidebarList(placemarks); 1534 }else{ 1535 placemarkContents=''; 1536 } 1537 1538 if (this.showOverlaysInSidebar && folder.hasOverlays){ 1539 overlayContents = this.addSidebarOverlayList(folder.overlays); 1540 } else { 1541 overlayContents=''; 1542 } 1543 1544 if (folder.hasFolders){ 1545 folderContents = this.addSidebarFolder(folderName, folder.folders); 1546 } else { 1547 folderContents=''; 1548 } 1549 1550 if (sameName){ 1551 contents += placemarkContents+overlayContents; 1552 }else{ 1553 var d = folder.isOpen ? 'block' : 'none'; 1554 contents += '<li><span class="'+cls+'"></span>'+ folderName +'<ul style="display:'+d+';">'+folderContents+placemarkContents+overlayContents+'</ul></li>'; 1555 } 1556 } 1557 } 1558 return contents; 1559 }, 1560 1561 1562 /** 1563 * createMarkerIconString 1564 */ 1565 createMarkerIconString: function(markerIcon) { 1566 if (markerIcon !== undefined ){ 1567 return '<img src="'+markerIcon+'" />'; 1568 }else{ 1569 return ''; 1570 } 1571 }, 1572 1573 1574 /** 1575 * adds an entry to the sidebar 1576 */ 1577 addSidebarList : function(placemarks) { 1578 var pm, placemark, marker, icon, contents='', innerContents='', descrip='', 1579 markerId, markerIcon, id, 1580 itemList = [], itemListContents=[], 1581 folderHtml = '<span class="closed"></span>'; 1582 1583 //look for the placemarks 1584 for (pm = 0; pm < placemarks.length; pm++){ 1585 placemark = placemarks[pm]; 1586 id = placemark.id; 1587 if ( placemark.marker){ 1588 marker = placemark.marker; 1589 id = marker.id; 1590 markerIcon = placemark.style.href; 1591 icon=this.createMarkerIconString(markerIcon); 1592 } 1593 1594 if (this.showSidebarDescriptions){ 1595 innerContents = '<li class="placemark" id="'+ id + '">'+ folderHtml + icon + placemark.name; 1596 descrip = this.createDescriptionString(placemark.description); 1597 if (descrip !== undefined && itemListContents[placemark.name] === undefined){ 1598 itemListContents[placemark.name]=descrip; 1599 } 1600 } else { 1601 if (placemark.marker){ 1602 innerContents = '<li class="placemark" id="'+ id + '">'+ icon + placemark.name; 1603 } else { 1604 innerContents = '<li class="placemark" id="'+ id + '">'+ placemark.name; 1605 } 1606 } 1607 1608 1609 itemList[placemark.name]=innerContents; 1610 1611 } 1612 1613 var placemarkId, lc; 1614 for ( placemarkId in itemList){ 1615 if (itemList.hasOwnProperty(placemarkId)) { 1616 lc = itemListContents[placemarkId]; 1617 if (this.showSidebarDescriptions){ 1618 if (lc === undefined ){ 1619 contents += itemList[placemarkId] +'</li>'; 1620 }else{ 1621 contents += itemList[placemarkId] + '<ul style="display:none;">'+lc+'</ul></li>'; 1622 } 1623 } else { 1624 contents += itemList[placemarkId] + '</li>'; 1625 } 1626 } 1627 } 1628 1629 return contents; 1630 }, 1631 1632 1633 /** 1634 * adds an overlay to the sidebar 1635 */ 1636 addSidebarOverlayList : function(overlays) {
1637 var i, groundOverlay, overlay, contents='', innerContents='', descrip='', 1638 itemList = [], itemListContents=[], 1639 folderHtml = '<span class="closed"></span>'; 1640 1641 //look for the overlays 1642 for (i = 0; i < overlays.length; i++){ 1643 groundOverlay = overlays[i]; 1644 if (groundOverlay.overlay){ 1645 overlay = groundOverlay.overlay; 1646 overlayId = groundOverlay.id; 1647 1648 if (this.showSidebarDescriptions){ 1649 descrip = this.createDescriptionString(groundOverlay.description); 1650 innerContents = '<li class="overlay">'+ folderHtml + '<span id="'+overlayId + '-check" class="checked"></span>' + groundOverlay.name+ '<ul style="display:none;">'+ descrip +'</ul></li>'; 1651 } else { 1652 innerContents = '<li class="overlay">' + '<span id="'+overlayId + '-check" class="checked"></span>' + groundOverlay.name; 1653 } 1654 } 1655 contents += innerContents; 1656 } 1657 return contents; 1658 }, 1659 1660 1661 /** 1662 * create a description for a placemark 1663 */ 1664 createDescriptionString : function(description){ 1665 if (description !== undefined && description !== ''){ 1666 var descrip = description.replace('<a name="JR_PAGE_ANCHOR_0_1"></a>', ''); 1667 return '<li class="description" style="color: black;">'+ descrip +'</li>'; 1668 } 1669 return undefined; 1670 }, 1671 1672 1673 /** 1674 * gets the placemark from the id 1675 */ 1676 getPlacemarkById : function(id){ 1677 var aId = id.split('-'); 1678 if (aId.length>0){ 1679 var docId = aId[0], 1680 j = id.lastIndexOf('-'), 1681 newId = id.slice(0,j); 1682 if (docId){ 1683 var placemark, placemarkId, pm, 1684 placemarks = this.docSet.docs[docId].placemarks; 1685 for (pm = 0; pm < placemarks.length; pm++){ 1686 placemark = placemarks[pm]; 1687 placemarkId = placemark.id; 1688 if (placemark && placemark.id === newId){ 1689 return placemark; 1690 } 1691 } 1692 } 1693 } 1694 return undefined; 1695 }, 1696 1697 1698 /** 1699 * gets the doc id from a placemark or folder id. 1700 */ 1701 getDocFolderIds: function(id){ 1702 if (!!id && typeof id !== 'number'){ 1703 var aId = id.split('-'); 1704 if (aId.length>0){ 1705 return aId; 1706 } 1707 } 1708 return undefined; 1709 }, 1710 1711 1712 /** 1713 * returns the placemarks for a folder and placemark name 1714 */ 1715 getPlacemarksByName : function(folderId, placemarkName) { 1716 if (folderId){ 1717 var ids = this.getDocFolderIds(folderId), 1718 placemarks, pm, placemark, aPlacemarks=[], doc; 1719 1720 if (ids !== undefined){ 1721 doc = this.getDocumentById(ids[0]); 1722 } 1723 if (doc !== undefined && doc.placemarks){ 1724 placemarks = doc.placemarks; 1725 1726 //loop through the placemarks 1727 for (pm = 0; pm <placemarks.length; pm++){ 1728 placemark = placemarks[pm]; 1729 if (placemark && placemark.folderId === folderId && placemark.name === placemarkName){ 1730 aPlacemarks.push(placemark); 1731 } 1732 } 1733 return aPlacemarks; 1734 } 1735 } 1736 return undefined; 1737 }, 1738 1739 1740 /** 1741 * Opens the shared google info window, anchors it to the specified marker or map object, and 1742 * displays the marker content. 1743 */ 1744 hilightShapesById : function(id) { 1745 var placemark, center, 1746 object = this.mapshapes[id]; 1747 1748 if (object === undefined){ 1749 object = this.mapshapes[id+'-0']; 1750 } 1751 if (object && object.folderId){ 1752 var placemarks = this.getPlacemarksByName(object.folderId, object.title); 1753 if (placemarks){ 1754 center = this.hilightShapes(placemarks); 1755 } 1756 this.zoomMap(); 1757 } 1758 return false;
1759 }, 1760 1761 1762 /** 1763 * hilights and unhilight shapes 1764 */ 1765 hilightShapes : function(placemarks) { 1766 if (this.lastSelectedPlacemark === placemarks){ 1767 return; 1768 } 1769 //unhighlight the last shapes 1770 if (this.lastSelectedPlacemark !== undefined){ 1771 this.changeShapeColors(this.lastSelectedPlacemark, false); 1772 } 1773 var markerLatLng = this.changeShapeColors(placemarks, true); 1774 if (markerLatLng !== undefined){ 1775 this.map.setCenter(markerLatLng); 1776 } 1777 this.lastSelectedPlacemark=placemarks; 1778 }, 1779 1780 1781 /** 1782 * hilights and unhilight shapes 1783 */ 1784 changeShapeColors : function(placemarks, hilight) { 1785 var pm, placemark, points, point, lines, line, areas, area, circles, circle, markerLatLng, i, 1786 hilite = (hilight!==undefined) ? hilight : true, 1787 hiliteColor; 1788 1789 if (hilite){ 1790 this.lastSelectedPlacemarks=placemarks; 1791 hiliteColor = this.highlightColor; 1792 } 1793 //look for the placemarks 1794 for (pm = 0; pm < placemarks.length; pm++){ 1795 placemark = placemarks[pm]; 1796 points = placemark.points; 1797 circles = placemark.circles; 1798 lines = placemark.lines; 1799 areas = placemark.areas; 1800 marker = placemark.marker; 1801 if (!!marker){ 1802 markerLatLng = marker.getPosition(); 1803 } 1804 if (points!== undefined){ 1805 for (i = 0; i < points.length; i++){ 1806 point = points[i]; 1807 if (hilite){ 1808 point.setOptions({zIndex:this.zindex++}); 1809 } 1810 } 1811 }else if (circles !== undefined){ 1812 for (i = 0; i < circles.length; i++){ 1813 circle = circles[i]; 1814 if (hilite){ 1815 circle.origStrokeColor = circle.strokeColor; 1816 circle.origFillColor = circle.strokeColor; 1817 circle.setOptions({strokeColor:hiliteColor, fillColor: hiliteColor, zIndex:this.zindex++}); 1818 } else { 1819 circle.setOptions({strokeColor:circle.origStrokeColor, fillColor: circle.origFillColor}); 1820 } 1821 } 1822 }else if (lines!== undefined){ 1823 for (i = 0; i < lines.length; i++){ 1824 line = lines[i]; 1825 if (hilite){ 1826 line.origStrokeColor = line.strokeColor; 1827 line.setOptions({strokeColor:hiliteColor, zIndex:this.zindex++}); 1828 } else { 1829 line.setOptions({strokeColor:line.origStrokeColor}); 1830 } 1831 } 1832 }else if (areas!== undefined){ 1833 for (i = 0; i < areas.length; i++){ 1834 area = areas[i]; 1835 if (hilite){ 1836 area.origStrokeColor = area.strokeColor; 1837 area.origFillColor = area.strokeColor; 1838 area.setOptions({strokeColor:hiliteColor, fillColor: hiliteColor, zIndex:this.zindex++}); 1839 } else { 1840 area.setOptions({strokeColor:area.origStrokeColor, fillColor: area.origFillColor}); 1841 } 1842 } 1843 } 1844 } 1845 return markerLatLng; 1846 }, 1847 1848 1849 /** 1850 * Opens the shared google info window, anchors it to the specified marker or map object, and 1851 * displays the marker content. 1852 */ 1853 openBubble : function(object){ 1854 if (object !== undefined){ 1855 this.zoomMap(); 1856 if (this.infoWindow){ 1857 if (object.description !== undefined){ 1858 this.infoWindow.setContent(object.description); 1859 } 1860 if (object.position !== undefined){ 1861 this.infoWindow.setPosition(object.position); 1862 } 1863 this.infoWindow.open(this.map, object); 1864 } 1865 var placemarks = this.getPlacemarksByName(object.folderId, object.title); 1866 if (placemarks){ 1867 this.hilightShapes(placemarks); 1868 } 1869 } 1870 }, 1871 1872 1873 /** 1874 * zooms map 1875 */ 1876 zoomMap : function(zoom){ 1877 if (this.shouldZoom){ 1878 if (zoom === undefined){ 1879 zoom = this.defaultZoomLevel; 1880 } 1881 if (this.map.getZoom() < zoom+1){ 1882 this.map.setZoom(zoom); 1883 } 1884 } 1885 }, 1886 1887 1888 /**
1889 * Opens the shared google info window, anchors it to the specified marker or map object, and 1890 * displays the marker content. 1891 */ 1892 openBubbleById : function(id) { 1893 var m = this.mapshapes[id]; 1894 if (m === undefined){ 1895 m = this.mapshapes[id+'-0']; 1896 } 1897 this.openBubble(m); 1898 }, 1899 1900 1901 /** 1902 * Called when clicking anywhere on the map and closes the info window. 1903 */ 1904 closeBubble : function() { 1905 if (this.infoWindow){ 1906 this.infoWindow.close(); 1907 } 1908 }, 1909 1910 1911 /* 1912 * KML color and opacity (alpha) values are expressed in hexadecimal notation. The range of values for any one color is 0 to 255 (00 to ff). 1913 * For alpha, 00 is fully transparent and ff is fully opaque. 1914 * The order of expression is aabbggrr, where aa=alpha (00 to ff); bb=blue (00 to ff); gg=green (00 to ff); rr=red (00 to ff). 1915 * 1916 * For example, if you want to apply a blue color with 50 percent opacity to an overlay, 1917 * you would specify the following: <color>7fff0000</color>, where alpha=0x7f, blue=0xff, green=0x00, and red=0x00. 1918 */ 1919 getRGBColorTransparency: function (kmlColor) { 1920 var color = {}; 1921 if (kmlColor) { 1922 aa = kmlColor.substr(0,2); 1923 bb = kmlColor.substr(2,2); 1924 gg = kmlColor.substr(4,2); 1925 rr = kmlColor.substr(6,2); 1926 color.color = "#" + rr + gg + bb; 1927 color.opacity = parseFloat(parseInt(aa,16)/256).toFixed(1); 1928 } 1929 if (isNaN(color.opacity)){ 1930 color.color = this.getStrokeColor(); 1931 color.opacity = 1.0; 1932 } 1933 return color; 1934 }, 1935 /* 1936 * getStrokeColor 1937 */ 1938 getStrokeColor : function(){ 1939 // Forzatura per CoopCulture 1940 return '#'+this.highlightColor; 1941 //return '#' + Math.round(0xffffff * Math.random()).toString(16); 1942 } 1943};
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.