1(function (root) { 2 var q = { 3 poll: 100, 4 jqueryLoadWait: 30, 5 markerClustererUrl: document.getElementsByClassName('Terratype.GoogleMapsV3')[0].getAttribute('data-markerclusterer-url'), 6 maps: [], 7 mapTypeIds: function (basic, satellite, terrain) { 8 var mapTypeIds = []; 9 if (basic) { 10 mapTypeIds.push('roadmap'); 11 } 12 if (satellite) { 13 mapTypeIds.push('satellite'); 14 } 15 if (terrain) { 16 mapTypeIds.push('terrain'); 17 } 18 19 if (mapTypeIds.length == 0) { 20 mapTypeIds.push('roadmap'); 21 } 22 return mapTypeIds; 23 }, 24 init: function () { 25 q.load(); 26 if (q.domDetectionType == 1) { 27 counter = 0; 28 var t = setInterval(function () { 29 // Is jquery loaded 30 if (root.jQuery) { 31 clearInterval(t); 32 q.updateJquery(); 33 } 34 if (++counter > q.jqueryLoadWait) { 35 // We have waited long enough for jQuery to load, and nothing, so default to javascript 36 console.warn("Terratype was asked to use jQuery to monitor DOM changes, yet no jQuery library was detected. Terratype has defaulted to using javascript to detect DOM changes instead"); 37 clearInterval(t); 38 q.domDetectionType = 0; 39 q.updateJs(); 40 } 41 }, q.poll); 42 } else { 43 q.updateJs(); 44 } 45 }, 46 updateJs: function () { 47 // Use standard JS to monitor page resizes, dom changes, scrolling 48 var counter = 0; 49 var mapsRunning = 0; 50 var timer = setInterval(function () { 51 if (counter == q.maps.length) { 52 if (mapsRunning == 0) { 53 // There are no maps running 54 clearInterval(timer); 55 } 56 counter = 0; 57 mapsRunning = 0; 58 } 59 var m = q.maps[counter]; 60 if (m.status != -1 && m.positions.length != 0) { 61 mapsRunning++; 62 if (m.status == 0) { 63 q.render(m); 64 } else { 65 if (m.domDetectionType == 2) { 66 m.status = -1; 67 } else if (m.domDetectionType == 1 && root.jQuery) { 68 q.idleJquery(m); 69 } else { 70 q.idleJs(m); 71 } 72 } 73 } 74 counter++; 75 }, q.poll); 76 }, 77 updateJquery: function () { 78 // Can only be used, if all DOM updates happen via jQuery. 79 var counter = 0; 80 var timer = setInterval(function () { 81 if (counter == q.maps.length) { 82 clearInterval(timer); 83 if (q.domDetectionType != 2) { 84 jQuery(window).on('DOMContentLoaded load resize scroll touchend', function () { 85 counter = 0; 86 var timer2 = setInterval(function () { 87 if (counter == q.maps.length) { 88 clearInterval(timer2); 89 } else { 90 var m = q.maps[counter]; 91 if (m.status > 0 && m.positions.length != 0) { 92 if (m.domDetectionType == 1) { 93 q.idleJquery(m); 94 } else { 95 q.idleJs(m); 96 } 97 } 98 counter++; 99 } 100 }, q.poll); 101 }); 102 } 103 } else { 104 var m = q.maps[counter]; 105 if (m.status == 0 && m.positions.length != 0) { 106 q.render(m); 107 } 108 counter++; 109 } 110 }, q.poll); 111 }, 112 getMap: function (mapId) { 113 for (var i = 0; i != q.maps.length; i++) { 114 if (q.maps[i].id == mapId) { 115 return q.maps[i]; 116 } 117 } 118 return null; 119 }, 120 defaultProvider: { 121 predefineStyling: 'retro', 122 showRoads: true, 123 showLandmarks: true, 124 showLabels: true, 125 variety: { 126 basic: true, 127 satellite: false,
128 terrain: false, 129 selector: { 130 type: 1, // Horizontal Bar 131 position: 0 // Default 132 } 133 }, 134 streetView: { 135 enable: false, 136 position: 0 137 }, 138 fullscreen: { 139 enable: false, 140 position: 0 141 }, 142 scale: { 143 enable: false, 144 position: 0 145 }, 146 zoomControl: { 147 enable: true, 148 position: 0, 149 }, 150 panControl: { 151 enable: false 152 }, 153 draggable: true 154 }, 155 mergeJson: function (aa, bb) { // Does not merge arrays 156 var mi = function (c) { 157 var t = {}; 158 for (var k in c) { 159 if (typeof c[k] === 'object' && c[k].constructor.name !== 'Array') { 160 t[k] = mi(c[k]); 161 } else { 162 t[k] = c[k]; 163 } 164 } 165 return t; 166 } 167 var mo = function (a, b) { 168 var r = (a) ? mi(a) : {}; 169 if (b) { 170 for (var k in b) { 171 if (r[k] && typeof r[k] === 'object' && r[k].constructor.name !== 'Array') { 172 r[k] = mo(r[k], b[k]); 173 } else { 174 r[k] = b[k]; 175 } 176 } 177 } 178 return r; 179 } 180 return mo(aa, bb); 181 }, 182 domDetectionType: 99, 183 load: function () { 184 var matches = document.getElementsByClassName('Terratype.GoogleMapsV3'); 185 for (var i = 0; i != matches.length; i++) { 186 mapId = matches[i].getAttribute('data-map-id'); 187 id = matches[i].getAttribute('data-id'); 188 var domDetectionType = parseInt(matches[i].getAttribute('data-dom-detection-type')); 189 if (q.domDetectionType > domDetectionType) { 190 q.domDetectionType = domDetectionType; 191 } 192 var model = JSON.parse(unescape(matches[i].getAttribute('data-googlemapsv3'))); 193 var datum = q.parse(model.position.datum); 194 var latlng = new root.google.maps.LatLng(datum.latitude, datum.longitude); 195 var m = q.getMap(mapId); 196 if (m == null) { 197 m = { 198 id: mapId, 199 div: id, 200 zoom: model.zoom, 201 provider: q.mergeJson(q.defaultProvider, model.provider), 202 positions: [], 203 center: latlng, 204 divoldsize: 0, 205 status: 0, 206 visible: false, 207 domDetectionType: domDetectionType 208 }; 209 matches[i].style.display = 'block'; 210 q.maps.push(m); 211 } 212 if (model.icon && model.icon.url) { 213 m.positions.push({ 214 id: id, 215 label: matches[i].getAttribute('data-label-id'), 216 latlng: latlng, 217 icon: { 218 url: q.configIconUrl(model.icon.url), 219 scaledSize: new root.google.maps.Size(model.icon.size.width, model.icon.size.height), 220 anchor: new root.google.maps.Point( 221 q.getAnchorHorizontal(model.icon.anchor.horizontal, model.icon.size.width), 222 q.getAnchorVertical(model.icon.anchor.vertical, model.icon.size.height)) 223 } 224 }); 225 } 226 } 227 }, 228 render: function (m) { 229 m.ignoreEvents = 0; 230 var mapTypeIds = q.mapTypeIds(m.provider.variety.basic, m.provider.variety.satellite, m.provider.variety.terrain); 231 m.gmap = new root.google.maps.Map(document.getElementById(m.div), { 232 disableDefaultUI: false, 233 scrollwheel: false, 234 panControl: false, // Has been depricated 235 center: m.center, 236 zoom: m.zoom, 237 draggable: true, 238 fullScreenControl: m.provider.fullscreen.enable, 239 fullscreenControlOptions: m.provider.fullscreen.position, 240 styles: m.provider.styles, 241 mapTypeId: mapTypeIds[0], 242 mapTypeControl: (mapTypeIds.length > 1), 243 mapTypeControlOptions: { 244 style: m.provider.variety.selector.type,
245 mapTypeIds: mapTypeIds, 246 position: m.provider.variety.selector.position 247 }, 248 scaleControl: m.provider.scale.enable, 249 scaleControlOptions: { 250 position: m.provider.scale.position 251 }, 252 streetViewControl: m.provider.streetView.enable, 253 streetViewControlOptions: { 254 position: m.provider.streetView.position 255 }, 256 zoomControl: m.provider.zoomControl.enable, 257 zoomControlOptions: { 258 position: m.provider.zoomControl.position 259 } 260 }); 261 with ({ 262 mm: m 263 }) { 264 root.google.maps.event.addListener(mm.gmap, 'zoom_changed', function () { 265 if (mm.ignoreEvents > 0) { 266 return; 267 } 268 q.closeInfoWindows(mm); 269 mm.zoom = mm.gmap.getZoom(); 270 }); 271 root.google.maps.event.addListenerOnce(mm.gmap, 'tilesloaded', function () { 272 if (mm.ignoreEvents > 0) { 273 return; 274 } 275 q.refresh(mm); 276 mm.status = 2; 277 }); 278 root.google.maps.event.addListener(mm.gmap, 'resize', function () { 279 if (mm.ignoreEvents > 0) { 280 return; 281 } 282 q.checkResize(mm); 283 }); 284 root.google.maps.event.addListener(mm.gmap, 'click', function () { 285 if (mm.ignoreEvents > 0) { 286 return; 287 } 288 q.closeInfoWindows(mm); 289 }); 290 } 291 m.ginfos = []; 292 m.gmarkers = []; 293 294 for (var p = 0; p != m.positions.length; p++) { 295 var item = m.positions[p]; 296 m.gmarkers[p] = new root.google.maps.Marker({ 297 map: m.gmap, 298 position: item.latlng, 299 id: item.id, 300 draggable: false, 301 icon: item.icon 302 }); 303 304 m.ginfos[p] = null; 305 var l = (item.label) ? document.getElementById(item.label) : null; 306 if (l) { 307 308 m.ginfos[p] = new root.google.maps.InfoWindow({ 309 content: l 310 }); 311 with ({ 312 mm: m, 313 pp: p 314 }) { 315 mm.gmarkers[p].addListener('click', function () { 316 //console.warn(mm.id + ': iconClick(): ignoreEvents = ' + mm.ignoreEvents); 317 if (mm.ignoreEvents > 0) { 318 return; 319 } 320 q.closeInfoWindows(mm); 321 if (mm.ginfos[pp] != null) { 322 mm.ginfos[pp].open(mm.gmap, mm.gmarkers[pp]); 323 } 324 }); 325 } 326 } 327 } 328 329 if (m.positions.length > 1) { 330 m.markerclusterer = new MarkerClusterer(m.gmap, m.gmarkers, { imagePath: q.markerClustererUrl }); 331 } 332 m.status = 1; 333 }, 334 closeInfoWindows: function (m) { 335 for (var p = 0; p != m.positions.length; p++) { 336 if (m.ginfos[p] != null) { 337 m.ginfos[p].close(); 338 } 339 } 340 }, 341 checkResize: function (m) { 342 if (!m.gmap.getBounds().contains(m.center)) { 343 q.refresh(m); 344 } 345 }, 346 refresh: function (m) { 347 m.ignoreEvents++; 348 m.gmap.setZoom(m.zoom); 349 q.closeInfoWindows(m); 350 m.gmap.setCenter(m.center); 351 with ({ 352 mm: m 353 }) { 354 root.google.maps.event.addListenerOnce(mm.gmap, 'idle', function () { 355 if (mm.idle == null) { 356 //console.warn(mm.id + ': refresh() end: already ran backup timer'); 357 return; 358 } 359 mm.ignoreEvents--; 360 if (mm.ignoreEvents == 0) { 361 mm.gmap.setCenter(mm.center); 362 clearTimeout(mm.idle); 363 mm.idle = null; 364 } 365 //console.warn(mm.id + ': refresh() end: ignoreEvents = ' + mm.ignoreEvents); 366 }); 367 if (mm.idle) { 368 clearTimeout(mm.idle); 369 } 370 mm.idle = setTimeout(function () { 371 if (mm.ignoreEvents != 0) { 372 //console.warn(mm.id + ': refresh() end: running backup timer'); 373 mm.gmap.setCenter(mm.center); 374 mm.ignoreEvents = 0 375 } 376 clearTimeout(mm.idle); 377 mm.idle = null; 378 }, 5000); 379 } 380 root.google.maps.event.trigger(m.gmap, 'resize'); 381 //console.warn(m.id + ' refresh(): ignoreEvents = ' + m.ignoreEvents); 382 }, 383 configIconUrl: function (url) { 384 if (typeof (url) === 'undefined' || url == null) { 385 return ''; 386 } 387 if (url.indexOf('//') != -1) { 388 // Is an absolute address 389 return url; 390 } 391 // Must be a relative address 392 if (url.substring(0, 1) != '/') { 393 url = '/' + url; 394 } 395 396 return root.location.protocol + '//' + root.location.hostname + (root.location.port ? ':' + root.location.port : '') + url; 397 }, 398 getAnchorHorizontal: function (text, width) { 399 if (typeof text == 'string') { 400 switch (text.charAt(0)) { 401 case 'l': 402 case 'L': 403 return 0; 404 405 case 'c': 406 case 'C': 407 case 'm': 408 case 'M': 409 return width / 2; 410 411 case 'r': 412 case 'R': 413 return width - 1; 414 } 415 } 416 return Number(text); 417 }, 418 getAnchorVertical: function (text, height) { 419 if (typeof text == 'string') { 420 switch (text.charAt(0)) { 421 case 't': 422 case 'T': 423 return 0; 424 425 case 'c': 426 case 'C': 427 case 'm': 428 case 'M': 429 return height / 2; 430 431 case 'b': 432 case 'B': 433 return height - 1; 434 } 435 } 436 return Number(text); 437 }, 438 parse: function (text) { 439 var args = text.trim().split(','); 440 if (args.length < 2) { 441 return false; 442 } 443 var lat = parseFloat(args[0].substring(0, 10)); 444 if (isNaN(lat) || lat > 90 || lat < -90) { 445 return false; 446 } 447 var lng = parseFloat(args[1].substring(0, 10)); 448 if (isNaN(lng) || lng > 180 || lng < -180) { 449 return false; 450 } 451 return { 452 latitude: lat, 453 longitude: lng 454 }; 455 }, 456 isElementInViewport: function (el) { 457 var rect = el.getBoundingClientRect(); 458 return ( 459 (rect.top <= (window.innerHeight || document.documentElement.clientHeight)) && ((rect.top + rect.height) >= 0) && 460 (rect.left <= (window.innerWidth || document.documentElement.clientWidth)) && ((rect.left + rect.width) >= 0) 461 ); 462 }, 463 idleJs: function (m) { 464 // Monitor dom changes via Javascript 465 var element = document.getElementById(m.div); 466 var newValue = element.parentElement.offsetTop + element.parentElement.offsetWidth; 467 var newSize = element.clientHeight * element.clientWidth; 468 var show = !(element.style.display && typeof element.style.display == 'string' && element.style.display.toLowerCase() == 'none'); 469 var visible = show && q.isElementInViewport(element); 470 if (newValue != 0 && show == false) {
471 //console.log('A ' + m.id + ': in viewport = ' + visible + ', showing = ' + show); 472 // Was hidden, now being shown 473 document.getElementById(m.div).style.display = 'block'; 474 } else if (newValue == 0 && show == true) { 475 //console.log('B ' + m.id + ': in viewport = ' + visible + ', showing = ' + show); 476 // Was shown, now being hidden 477 document.getElementById(m.div).style.display = 'none'; 478 m.visible = false; 479 } 480 else if (visible == true && m.divoldsize != 0 && newSize != 0 && m.divoldsize != newSize) { 481 //console.log('C ' + m.id + ': in viewport = ' + visible + ', showing = ' + show); 482 // showing, just been resized and map is visible 483 q.refresh(m); 484 m.visible = true; 485 } else if (visible == true && m.visible == false) { 486 //console.log('D ' + m.id + ': in viewport = ' + visible + ', showing = ' + show); 487 // showing and map just turned visible 488 q.refresh(m); 489 m.visible = true; 490 } else if (visible == false && m.visible == true) { 491 //console.log('E ' + m.id + ': in viewport = ' + visible + ', showing = ' + show); 492 // was visible, but now hiding 493 m.visible = false; 494 } 495 m.divoldsize = newSize; 496 }, 497 idleJquery: function (m) { 498 // Monitor dom changes via jQuery 499 var element = jQuery(document.getElementById(m.div)); 500 var show = !(element.is(':hidden')); 501 var visible = element.is(':visible'); 502 if (show == visible) { 503 if (show) { 504 var newSize = element.height() * element.width(); 505 if (newSize != m.divoldsize) { 506 q.refresh(m); 507 } 508 m.divoldsize = newSize; 509 } 510 return; 511 } 512 if (show) { 513 element.hide(); 514 m.divoldsize = 0; 515 return; 516 } 517 element.show(); 518 q.refresh(m); 519 m.divoldsize = element.height() * element.width(); 520 } 521 } 522 523 root.TerratypeGoogleMapsV3CallbackRender = function () { 524 q.init(); 525 } 526}(window)); 527 528
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.