1 2 3//Class Defintions ****************************************** 4class Coord{ 5 lat = 0.000000; 6 lng = 0.000000; 7 constructor(lat,lng){ 8 this.lat = lat; 9 this.lng= lng; 10 } 11} 12 13class Island{ 14 Name = ""; 15 TopLeftCoord = new Coord(0,0); 16 BottomRightCoord = new Coord(0,0); 17 XIncrement = 0.000000; 18 YIncrement = 0.000000; 19 AliasMatrix = []; 20 QiCodeMatrix = []; 21 CodePrefix = ""; 22 constructor(name, mapTopLCoord, mapbottomRCoord, xIncr, yIncr){ 23 this.Name= name; 24 this.TopLeftCoord = mapTopLCoord; 25 this.BottomRightCoord = mapbottomRCoord; 26 this.XIncrement = xIncr; 27 this.YIncrement = yIncr; 28 } 29} 30 31class QiPosition { 32 GridCoord = new Coord(0.000000,0.000000); 33 ActualCoord = new Coord(0.000000,0.000000); 34 QiCode = ""; 35 QiCodeURL = ""; 36 QiCodeAlias= ""; 37 Island = new Island(); 38 isValid = true; 39 constructor(){ 40 } 41} 42 43class MatrixPosition{ 44 Word1 = ""; //x-axis word 45 Word2 = ""; //y-axis word 46 Word1Index = -1; 47 Word2Index = -1; 48 AliasPhrase = ""; 49 CopyTo(toObject) { 50 toObject.Word1 = this.Word1; 51 toObject.Word2 = this.Word2; 52 toObject.Word1Index = this.Word1Index; 53 toObject.Word2Index = this.Word2Index; 54 toObject.AliasPhrase = this.AliasPhrase; 55 } 56 constructor(word1, word2, word1Index, word2Index){ 57 this.Word1 = word1; 58 this.Word2 = word2; 59 this.Word1Index = word1Index; 60 this.Word2Index = word2Index; 61 } 62} 63//*********************************************************** 64 65 66var strCurrentQiCode = ""; //Current QiCode entered or selected (blank for invalid direct entry) 67var elmOutputMap; //Element Container for the Map 68var objOutputMap; //The Map 69var objOutputMapMarker; //Map Marker 70//var objGeolocationOptions = {maximumAge:10000, timeout:5000, enableHighAccuracy: true}; 71var objGeolocationOptions = {maximumAge:6000, timeout:5000, enableHighAccuracy: true}; 72var objLastKnownLocation; //Coord() class - Last Known co-ordinates (lat/lng) of the user - used to helpe determine the intended island 73 74//Navigation Variables 75var objMapDirectionsService; //The Map's Direction service (google.maps.DirectionsService) 76var objMapDirectionsRenderer; //The Map's Renderer service (google.maps.DirectionsService) 77var objNavigateStartPoint; 78 79var aryIslands; //Global Array of all Islands Covered 80 81var objGeoCoder; 82 83//Grid Overlays 84var roadmapOverlay; //Map Grid overlay for Roadmaps 85var satelliteOverlay; //Map Grid overlay for Satellite 86var blnGridShown = false; 87 88 89 90 91//Sharing 92var strDomainName = window.location.hostname; 93var strDomainAddress = "https://" + strDomainName; 94//var strDomainName = window.location.hostname + ":8000"; 95//var strDomainAddress = "http://" + strDomainName; 96 97 98const strFB_href = "http://www.facebook.com/sharer.php?u={url_to_qi_code}"; 99const strTwitter_href = "http://twitter.com/intent/tweet?url=&original_referer&=hashtags=qi_code&text={url_to_qi_code}" ; 100const strWhatsApp_href="https://api.whatsapp.com/send?text={url_to_qi_code}"; 101//const strEmail_href="mailto:[email protected]?&subject=Find%20Me%20at&body=Click%20on%20this%20link%20to%20find%20the%20location%20'{qi_code}'%20I%20found%20at%20qi.gg%20:%20{url_to_qi_code}"; 102var strEmail_href="mailto:[email protected]?&subject=Find%20Me%20at&body=Click%20on%20this%20link%20to%20find%20the%20location%20'{qi_code}'%20I%20found%20at%20" + strDomainName +"%20:%20{url_to_qi_code}"; 103 104 105//Default Positions (per Island) 106//const strPlaceHolderText = "Enter a Qi code"; 107const objPosnStPP = new Coord(49.455284, -2.534757); 108const objPosnStHlr = new Coord(49.182747,-2.109142); 109 110const mapType_Satellite = 'satellite'; 111// const mapType_Hybrid = 'hybrid'; 112// const markerLatOffset = 0.000058762911; 113// const markerLngOffset = 0.000059902668; 114 115const blnUseQiMapToNavigate = false; //system setting to specify of navigation occurs in our own map or is delegated 116 117 118 119function findRowInArray(array, searchFor, lookupColNo) { 120 //Tranverse an Array Table 121 //Note : colIndex -1 means match any column value 122 123 var rowIndex = 0; 124 var colIndex = 0; 125 var row; 126 var colToLookup; 127 128 129 //if (lookupColNo == null){ 130 if (IsSet(lookupColNo) == false){ 131 colToLookup = 0; 132 } else { 133 colToLookup = lookupColNo; 134 } 135 136 if(colToLookup==-1){ 137 //Check All Columns for a match 138 for (rowIndex = 0; rowIndex < array.length; rowIndex++ ) { 139 row = array[rowIndex]; 140 for (colIndex = 0; colIndex < row.length; colIndex++ ){ 141 if (row[colIndex] == searchFor) { 142 return row; 143 } 144 } 145 } 146 } else { 147 //Check a Specific column 148 for (rowIndex = 0; rowIndex < array.length; rowIndex++ ) { 149 row = array[rowIndex]; 150 if (row[colToLookup] == searchFor) { 151 return row; 152 } 153 } 154 } 155
156 row = null; 157 return row; // value not found in array 158 } 159 160 function findRowInAliasArray(array, searchFor, lookupColNo, matchToMainSquareOnly) { 161 //Tranverse an Alias Array Table 162 //Array : QiCode | Alias | isMainSquare <-- used in case 1 alias covers multiple squares 163 //Note : colIndex -1 means match any column value 164 165 var rowIndex = 0; 166 var colIndex = 0; 167 var row; 168 var colToLookup; 169 var mustMatchMain; 170 171 if (IsSet(lookupColNo) == false){ 172 colToLookup = 0; 173 } else { 174 colToLookup = lookupColNo; 175 } 176 177 if (IsSet(matchToMainSquareOnly) == false){ 178 mustMatchMain = false; 179 } else { 180 mustMatchMain = matchToMainSquareOnly; 181 } 182 183 if (array.length>0){ 184 if(colToLookup==-1){ 185 //Check All Columns for a match 186 for (rowIndex = 0; rowIndex < array.length; rowIndex++ ) { 187 row = array[rowIndex]; 188 for (colIndex = 0; colIndex < row.length; colIndex++ ){ 189 if (row[colIndex] == searchFor.trim()){ 190 if (mustMatchMain){ 191 if (row[2] == true){ 192 return row; 193 } 194 } else { 195 return row; 196 } 197 } 198 } 199 } 200 } else { 201 //Check a Specific column 202 for (rowIndex = 0; rowIndex < array.length; rowIndex++ ) { 203 row = array[rowIndex]; 204 if (row[colToLookup] == searchFor.trim()){ 205 if (mustMatchMain){ 206 if (row[2] == true){ 207 return row; 208 } 209 } else { 210 return row; 211 } 212 } 213 } 214 } 215 } 216 row = null; 217 return row; // value not found in array 218 } 219 220 function valueInRange(val, bottomVal, topVal){ 221 var blnIsInRange = false; 222 223 if (val<=topVal && val>=bottomVal){ 224 blnIsInRange = true; 225 } 226 227 return blnIsInRange; 228 } 229 230 /* EXAMPLE ONLY 231 232function getQiCodeMatrixForGuernsey (){ 233 var matrix = []; 234 matrix.push('man'); 235 matrix.push('any'); 236 matrix.push('dinner'); 237 matrix.push('put'); 238 matrix.push('big'); 239 return matrix; 240} 241 242 243function getQiCodeAliasMatrixForGuernsey(){ 244 //Array : QiCode | Alias | isMainSquare <-- used in case 1 alias covers multiple squares 245 var matrix = []; 246 247 248 matrix.push(['happy place','mr joker',true]); 249 matrix.push(['dutch donkey','wibble', true]); 250 matrix.push(['dutch swim','wibble', false]); 251 matrix.push(['sneak donkey','wibble', false]); 252 253 254 return matrix; 255} 256 257function getIslandsList(){ 258 //Initialise a list of All the islands, their map co-ords, QiCode Matrices etc 259 var matrix = []; 260 var island;
261 var tlCoord; 262 var brCoord; 263 var xIncrement = .000075; 264 var yIncrement = .00005; 265 266 //Guernsey & Herm 267 tlCoord = new Coord(49.52,-2.69); 268 brCoord = new Coord(49.4,-2.44); 269 island = new Island("Guernsey", tlCoord, brCoord, xIncrement, yIncrement); 270 island.QiCodeMatrix = getQiCodeMatrixForGuernsey(); 271 island.AliasMatrix = getQiCodeAliasMatrixForGuernsey(); 272 island.CodePrefix = "gy"; 273 matrix.push(island); 274 275 276 // //Alderney 277 // tlCoord = new Coord(49.78,-2.39); 278 // brCoord = new Coord(49.66,-2.14); 279 // island = new Island("Alderney", tlCoord, brCoord, xIncrement, yIncrement); 280 // island.QiCodeMatrix = getQiCodeMatrixForAlderney(); 281 // island.AliasMatrix = getQiCodeAliasMatrixForAlderney(); 282 // island.CodePrefix = "ay"; 283 // matrix.push(island); 284 285 // //Sark 286 // tlCoord = new Coord(49.49,-2.42); 287 // brCoord = new Coord(49.37,-2.17); 288 // island = new Island("Sark", tlCoord, brCoord, xIncrement, yIncrement); 289 // island.QiCodeMatrix = getQiCodeMatrixForSark(); 290 // island.AliasMatrix = getQiCodeAliasMatrixForSark(); 291 // island.CodePrefix = "sk"; 292 // matrix.push(island); 293 294 return matrix; 295} 296*/ 297 298function initGlobalVariables(){ 299 //Initialise Global Variables 300 301 //Set Global HTML Element to hold the map 302 elmOutputMap = document.getElementById("outputMap"); 303 304 //Global Array of all Islands Covered (incl their Co-ordinates and Matrices) 305 aryIslands = getIslandsList(); 306 307} 308 309function createUnknownIsland(){ 310 var island = new Island("unknown"); 311 return island; 312} 313 314function isUnknownIsland(island){ 315 var isUknown = false; 316 317 if (IsSet(island)){ 318 isUknown = (island.Name =="unknown"); 319 } else { 320 isUknown = true; 321 } 322 323 return isUknown; 324} 325 326function getIslandFromCoords(posn, out_MatrixPosition){ 327 //Get an Island from the aryIslands Array based on a set of co-ordinates 328 329 var i; 330 var island;
331 var islandFound = createUnknownIsland(); 332 333 334 335 for (i=0; i<aryIslands.length; i++){ 336 island = aryIslands[i]; 337 338 if (valueInRange(posn.lat, island.BottomRightCoord.lat, island.TopLeftCoord.lat) && 339 valueInRange(Math.abs(posn.lng), Math.abs(island.BottomRightCoord.lng), Math.abs(island.TopLeftCoord.lng))){ 340 341 //Island has been Found 342 //Get Matrix Position 343 var matrixPosn = createMatrixPositionFromCoordObject(posn, island); 344 matrixPosn.CopyTo(out_MatrixPosition); 345 346 //Check the Alias Matrix (matching the Main Square) 347 //AliasArray = QiCode | Alias | isMainSquare <-- used in case 1 alias covers multiple squares 348 var row = findRowInAliasArray(island.AliasMatrix, out_MatrixPosition.Word1 + " " + out_MatrixPosition.Word2,0, false); 349 if (IsSet(row)){ 350 //There is an Alias 351 out_MatrixPosition.AliasPhrase = row[1]; 352 } 353 islandFound = island; 354 break; 355 } 356 } 357 358 return islandFound; 359} 360 361 362function getIslandFromQiCode(rawQiCode, out_MatrixPosition){ 363 //Get an Island from the aryIslands Array based on a passed qiCode 364 //out param out_MatrixPosition returns the actual underlying Matrix words and any Alias 365 366 var i; 367 var matrixPosn; 368 var strQiWord1; 369 var strQiWord2; 370 var intSpacePosn = rawQiCode.indexOf(' '); 371 var island;
372 var islandFound = createUnknownIsland(); 373 var matrixPosn; 374 375 376 //Split the Code into 2 words 377 rawQiCode = rawQiCode.trim(); 378 strQiWord1 = rawQiCode.substr(0,intSpacePosn); 379 strQiWord2 = rawQiCode.substr(intSpacePosn+1); 380 strQiWord1 = strQiWord1.replace(/ /g,''); 381 strQiWord2 = strQiWord2.replace(/ /g,''); 382 383 384 //Check if we have at least 1 word if not return UnknownIsland 385 if (strQiWord1=="" && strQiWord2==""){ 386 return islandFound; 387 } 388 389 for (i=0; i<aryIslands.length; i++){ 390 island = aryIslands[i]; 391 392 //Check the QiCodeMatrix & Exit Loop if Found 393 matrixPosn = createMatrixPositionFromQiCode(strQiWord1, strQiWord2, island); 394 if (IsSet(matrixPosn)){ 395 matrixPosn.CopyTo(out_MatrixPosition); 396 islandFound = island; 397 break; 398 } 399 400 401 //Check the Alias Matrix (matching the Main Square) 402 //AliasArray = QiCode | Alias | isMainSquare <-- used in case 1 alias covers multiple squares 403 var row = findRowInAliasArray(island.AliasMatrix, rawQiCode,1, true); 404 if (IsSet(row)) { 405 //This is an Alias so create teh MatrixPosition based on the 'real' 2 words 406 intSpacePosn = row[0].indexOf(' '); 407 strQiWord1 = row[0].substr(0,intSpacePosn); 408 strQiWord2 = row[0].substr(intSpacePosn+1); 409 matrixPosn = createMatrixPositionFromQiCode(strQiWord1, strQiWord2, island) 410 matrixPosn.AliasPhrase = rawQiCode; 411 //out_MatrixPosition = matrixPosn; 412 matrixPosn.CopyTo(out_MatrixPosition); 413 islandFound = island; 414 break; 415 } 416 } 417 418 return islandFound; 419} 420 421function createMatrixPositionFromQiCode(word1, word2, forIsland){ 422 //Create a MatrixPosition() object based on know Coord() object 423 424 var matrixPosn = null; 425 var intCodeIndex1; 426 var intCodeIndex2; 427 428 429 intCodeIndex1 = forIsland.QiCodeMatrix.indexOf(word1); 430 if (intCodeIndex1 != -1) { 431 intCodeIndex2 = forIsland.QiCodeMatrix.indexOf(word2); 432 if (intCodeIndex2 != -1) { 433 matrixPosn = new MatrixPosition(word1,word2,intCodeIndex1,intCodeIndex2); 434 matrixPosn.AliasPhrase = ""; 435 //Do a check to see if an Alias does exist and an old code has been supplied 436 var row = findRowInAliasArray(forIsland.AliasMatrix, word1 + " " + word2,0, false); 437 if (IsSet(row)) { 438 matrixPosn.AliasPhrase = row[1]; 439 } 440 441 } 442 } 443 444 445 return matrixPosn; 446} 447 448function createMatrixPositionFromCoordObject(coord, forIsland){ 449 //Create a MatrixPosition() object based on know Coord() object 450 451 var matrixPosn = new MatrixPosition(); 452 453 //Zero based array 454 //matrixPosn.Word1Index = Math.floor((Math.abs(coord.lng) - Math.abs(forIsland.BottomRightCoord.lng) )/forIsland.XIncrement) + 1; 455 //matrixPosn.Word2Index = Math.floor((Math.abs(coord.lat) - Math.abs(forIsland.BottomRightCoord.lat) )/forIsland.YIncrement) + 1; 456 matrixPosn.Word1Index = Math.floor((Math.abs(coord.lng) - Math.abs(forIsland.BottomRightCoord.lng) )/forIsland.XIncrement); 457 matrixPosn.Word2Index = Math.floor((Math.abs(coord.lat) - Math.abs(forIsland.BottomRightCoord.lat) )/forIsland.YIncrement); 458 459 matrixPosn.Word1 = forIsland.QiCodeMatrix[matrixPosn.Word1Index]; 460 matrixPosn.Word2 = forIsland.QiCodeMatrix[matrixPosn.Word2Index]; 461 462 return matrixPosn; 463} 464 465function createCoordObjectFromMatrixPositionObject(matrixPosn, forIsland){ 466 //Create a Coord() object based on know word positions in a matrix 467 468 var coord = new Coord(); 469 coord.lng = forIsland.BottomRightCoord.lng - (matrixPosn.Word1Index * forIsland.XIncrement); 470 coord.lat = forIsland.BottomRightCoord.lat + (matrixPosn.Word2Index * forIsland.YIncrement); 471 return coord; 472} 473 474 475 476 477// function getUsersIslandChoice(){ 478// //Determine which Island the User is 'using' 479// //Based on either current location or 'intention' based on any markers layed dowm 480 481// var island = createUnknownIsland(); 482 483// if (IsSet(objOutputMapMarker)){ 484// //A Marker is set so use that 485// var posn = new Coord(objOutputMapMarker.getPosition.lat(), objOutputMapMarker.getPosition.lng()) 486// island = getIslandFromCoords(posn); 487// } 488 489// if (IsSet(objLastKnownLocation) && isUnknownIsland(island)){ 490// //A last known Position is set so use that 491// island = getIslandFromCoords(objLastKnownLocation); 492// } 493 494// return island;
495// } 496 497 498function processUserEntry(posn, qiCode, setZoom, setCentre, setPlaceHolderText, markerType){ 499 //Process a User Action of either entering a QiCode or Clicking on the Map for a Posn 500 501 var blnEntryByQiCode = false; 502 503 504 //Calc Location Values 505 if (IsSet(qiCode)){ 506 if (qiCode == "") return; //don't process place holder text 507 blnEntryByQiCode = true; 508 qiCode = qiCode.toLowerCase(); 509 } 510 var objQiPositionObject = createQiPositionObject(qiCode, posn); 511 512 try{ 513 514 if (objQiPositionObject.isValid){ 515 //Code is Valid (either a QiCode entered directly or a Lat/Long is inside a recognized 'Island Area') 516 517 //Set Global Variable recording the current QiCode 518 if (objQiPositionObject.QiCodeAlias != ""){ 519 strCurrentQiCode = objQiPositionObject.QiCodeAlias; 520 } else { 521 strCurrentQiCode = objQiPositionObject.QiCode; 522 } 523 524 //Set Zoom & Position 525 if (IsSet(setZoom)){ 526 if (setZoom == true){ 527 objOutputMap.setZoom(18); 528 } 529 } 530 if (IsSet(setCentre)){ 531 if (setCentre == true){ 532 var objPosn = {lat: objQiPositionObject.ActualCoord.lat, lng: objQiPositionObject.ActualCoord.lng}; 533 objOutputMap.setCenter(objPosn); 534 } 535 } 536 537 538 //Display the Marker 539 ClearMapMarker(objOutputMapMarker); 540 createMarker(objQiPositionObject, markerType, blnEntryByQiCode, objQiPositionObject.Island); 541 542 543 //Display the QiCode 544 setCodeInputTextBoxValues(objQiPositionObject, setPlaceHolderText); 545 546 547 } else { 548 //Code is Invalid 549 550 //Reset Global Variable recording the current QiCode 551 strCurrentQiCode = ""; 552 553 //Still show the marker if entry was by clicking outside the area 554 if (!blnEntryByQiCode){ 555 //Display the Marker 556 ClearMapMarker(objOutputMapMarker); 557 createMarker(objQiPositionObject, "std", false, objQiPositionObject.Island); 558 } 559 560 setCodeInputTextBoxValues(objQiPositionObject); 561 } 562 563 } catch (err){ 564 //Display the values ********** 565 objQiPositionObject.isValid = false; 566 setCodeInputTextBoxValues(objQiPositionObject); 567 //****************************** 568 } 569 570} 571 572 573// function setControls(mode){ 574// switch (mode) { 575// case "std": 576// //Standard Map view and Marker clicks 577// $('#divMainMenu').removeClass('qi-toggle-off'); 578// $('#divNavigateMenu').addClass('qi-toggle-off'); 579// break; 580 581// case "nav": 582// //Navigate from Current Location to a QiCode 583// $('#divMainMenu').addClass('qi-toggle-off'); 584// $('#divNavigateMenu').removeClass('qi-toggle-off'); 585 586// //Also Hide any other pop-ups displayed 587// if (!$('#divCodeEntryPopUp').hasClass('qi-toggle-off')){ 588// toggleCodeEntryPopUp(); 589// } 590// if (!$('#divSharePopUp').hasClass('qi-toggle-off')){ 591// toggleSharePopUp(); 592// } 593// break; 594 595// default: 596// break; 597// } 598// } 599 600 601function createQiPositionObject(strQiCode, posn){ 602 //Create the QiPosition Object from parameters passed in 603 604 var blnPosnSupplied = false; 605 //var qiPositionObject = {PlusCode: "", lat: 0, lng: 0, QiCode: "", QiCodeURL: "", QiCodeAlias: "", isValid: true }; 606 var qiPositionObject = new QiPosition(); 607 var out_MatrixPosn = new MatrixPosition(); 608 609 610 if (IsSet(strQiCode)){ 611 //Create Object from a passed QiCode ********** 612 //Find Which Island this Code refers to 613 qiPositionObject.Island = getIslandFromQiCode(strQiCode, out_MatrixPosn); 614 //********************************************* 615 616 } else { 617 //Create Object from a Lat/Long *************** 618 blnPosnSupplied = true; 619 //Find Which Island this Coord refers to 620 qiPositionObject.Island = getIslandFromCoords(posn, out_MatrixPosn); 621 //********************************************* 622 623 } 624 625 626 //Return if the Island (& QiCode therfore) is Unknown 627 if (isUnknownIsland(qiPositionObject.Island)){ 628 qiPositionObject.isValid = false; 629 qiPositionObject.QiCode="Invalid QiCode"; 630 if (blnPosnSupplied){
631 qiPositionObject.ActualCoord = new Coord(posn.lat,posn.lng); 632 } 633 return qiPositionObject; 634 } 635 636 637 //Island and QiCode/Coords passed in are Valid 638 qiPositionObject.isValid = true; 639 qiPositionObject.GridCoord = createCoordObjectFromMatrixPositionObject(out_MatrixPosn, qiPositionObject.Island); //this will create a Grid Postion of Co-ordinates rather tnas any clicked on in the passed in posn 640 if (blnPosnSupplied){ 641 qiPositionObject.ActualCoord = new Coord(posn.lat,posn.lng); 642 } else { 643 qiPositionObject.ActualCoord = new Coord(qiPositionObject.GridCoord.lat,qiPositionObject.GridCoord.lng); 644 } 645 qiPositionObject.QiCode = out_MatrixPosn.Word1 + " " + out_MatrixPosn.Word2; 646 qiPositionObject.QiCodeAlias = out_MatrixPosn.AliasPhrase; 647 if (qiPositionObject.QiCodeAlias !=""){ 648 qiPositionObject.QiCodeURL = getQIEncodedURL(qiPositionObject.QiCodeAlias,true); 649 } else { 650 qiPositionObject.QiCodeURL = getQIEncodedURL(qiPositionObject.QiCode,true); 651 } 652 653 654 return qiPositionObject; 655} 656 657 658function getQIEncodedURL(strQICode, escapeSpaces){ 659 660 //var siteURL ="https://qi.gg"; 661 var siteURL = strDomainAddress; 662 663 if (IsSet(strQICode)){// != null 664 if (!IsSet(escapeSpaces)){ 665 escapeSpaces = true; 666 } 667 if (escapeSpaces == true){ 668 siteURL = siteURL + "/?qi=" + strQICode.replace(" ", "%20"); 669 } else { 670 siteURL = siteURL + "/?qi=" + strQICode; 671 } 672 } 673 return siteURL; 674} 675 676 677function initMap() { 678 //Main initialisation point : Call back from Google Maps 679 680 //Reset global variables 681 strCurrentQiCode = ""; 682 elmOutputMap = null; 683 objOutputMap = null; 684 objOutputMapMarker = null; 685 objLastKnownLocation = null; 686 objMapDirectionsService = null; 687 objMapDirectionsRenderer= null; 688 objNavigateStartPoint = null; 689 objGeoCoder = null; 690 roadmapOverlay = null; 691 satelliteOverlay = null; 692 blnGridShown = false; 693 694 695 696 //Initialise the Global Environment Variables 697 initGlobalVariables(); 698 699 700 //Create the Map & Set Global Variable 701 createMap(mapType_Satellite); 702 703 704 //Initialise Grid Overlays 705 initialise_GridOverlays(); 706 707 708 try{ 709 //Check if Parameters were passed in 710 var queryString = window.location.search; 711 var parms = new URLSearchParams(queryString); 712 var action = parms.get('a'); 713 var qiCode = parms.get('qi'); 714 715 716 if (IsSet(qiCode)){// != null 717 //A Code Parameter was passed so run it 718 719 processUserEntry(null,qiCode, true, true, false); 720 if (IsSet(action)){ 721 //An Action Parameter was passed 722 switch (action) { 723 // case "nav": 724 // //Display the Navigation bar 725 // setViewMode('nav'); 726 // break; 727 728 case "navgo": 729 //Trigger a Navigation Action 730 //setViewMode('nav'); 731 navigateGO(qiCode); 732 break; 733 default: 734 break; 735 } 736 737 } 738 739 } else { 740 //No Code Parameter passed so try to use Geolocation to Initialise it 741 if (navigator.geolocation) { 742 navigator.geolocation.getCurrentPosition(initialiseMap_foundGeolocationPosn ,initialiseMap_noGeolocationPosn, objGeolocationOptions); 743 } else { 744 initialiseMap_noGeolocationPosn(null); 745 } 746 } 747 } catch (err){ 748 749 initialiseMap_noGeolocationPosn(null); 750 } 751} 752 753function createMap(mapType){ 754 //Create the Map for the 1st Time 755 756 var blnShowZoomControls = !IsMobileDevice(); 757 var defaultPosn = getDefaultPosition(); 758 759 760 //Create Map, centered in St Peter (hide streetview) 761 objOutputMap = new google.maps.Map(elmOutputMap, { 762 zoomControl: blnShowZoomControls, 763 zoom: 12, 764 center: defaultPosn, 765 streetViewControl: false, 766 mapTypeId: mapType, 767 }); 768 769 770 771 //Add Custom Buttons 772 addMapCustomButtons(); 773 774 //Configure the click listener. 775 try{ 776 objOutputMap.addListener("click", ouputMap_Click); 777 } catch(listenErr){ 778 779 } 780 781} 782 783 784function getDefaultPosition(){ 785 //Get a Default Island Position 786 //Depends on the site being accessed 787 788 var defaultPosn; 789 790 switch (strDomainName){ 791 case "qicodes.je": 792 defaultPosn = objPosnStHlr; 793 case "qi.gg": 794 case "qicodes.gg": 795 default: 796 defaultPosn = objPosnStPP 797 break; 798 } 799 800 return defaultPosn; 801} 802function toggleMapZoomControls(toggleOn){ 803 if (toggleOn){ 804 map.setOptions("zoomControl", true); 805 } else { 806 map.setOptions("zoomControl", false); 807 } 808} 809 810function addMapCustomButtons(){ 811 //Add Cutom Buttons to the Map 812 /* 813 objOutputMap.controls[google.maps.ControlPosition.TOP_LEFT].push(controlMarkerUI); 814 815 Options : google.maps.ControlPosition.TOP_CENTER ; 816 TOP_CENTER 817 TOP_LEFT 818 TOP_RIGHT 819 LEFT_TOP 820 RIGHT_TOP 821 LEFT_CENTER 822 RIGHT_CENTER 823 LEFT_BOTTOM 824 RIGHT_BOTTOM 825 BOTTOM_CENTER 826 BOTTOM_LEFT 827 BOTTOM_RIGHT 828 */ 829 830 if (navigator.geolocation) { 831 //### Add a Current Position button on Google Maps ... 832 var controlPositionUI = document.createElement('DIV'); 833 controlPositionUI.className = "qi-current-location-icon"; 834 controlPositionUI.title = 'Select current location'; 835 controlPositionUI.onclick = function() { 836 navigator.geolocation.getCurrentPosition(initialiseMap_foundGeolocationPosn ,initialiseMap_noGeolocationPosn, objGeolocationOptions); 837 }; 838 objOutputMap.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlPositionUI); 839 840 //### Add a Navigate button on Google Maps ... 841 var controlNavigateUI = document.createElement('DIV'); 842 controlNavigateUI.className = "qi-navigate-icon"; 843 controlNavigateUI.title = 'Navigate from current location'; 844 controlNavigateUI.onclick = function() { 845 //toggleNavigateTo('on'); 846 performNavigate(''); 847 }; 848 objOutputMap.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlNavigateUI); 849 850 //### Add a Clear Navigate button on Google Maps ... 851 // var controlClearNavigateUI = document.createElement('DIV'); 852 // controlClearNavigateUI.className = "qi-clear-navigate-icon"; 853 // controlClearNavigateUI.title = 'Clear Navigation'; 854 // controlClearNavigateUI.onclick = function() { 855 // resetNavigationServices(); 856 // }; 857 // objOutputMap.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlClearNavigateUI); 858 859 } 860} 861
862function ClearMapMarker(marker){ 863 try{ 864 marker.setMap(null); 865 } catch (errr){ 866 //do nothing 867 } 868} 869 870//function createMarker(posn, objQiPositionObject, markerType, applyRectangleOffset, island){ 871function createMarker(objQiPositionObject, markerType, applyRectangleOffset, island){ 872 873 var googlePosn = {lat: objQiPositionObject.ActualCoord.lat, lng: objQiPositionObject.ActualCoord.lng}; 874 875 876 877 if (!IsSet(markerType)){ 878 markerType='std'; 879 } 880 881 //var iconBounceURL="https://qi.gg/images/location-bounce64.gif"; 882 //var iconRedMarkerDot = "https://qi.gg/images/marker-red-whitedot1-32x45.png"; 883 var iconBounceURL= strDomainAddress + "/images/location-bounce64.gif"; 884 var iconRedMarkerDot = strDomainAddress + "/images/marker-red-whitedot1-32x45.png"; 885 var isOptimized = false; 886 //animation : google.maps.Animation.BOUNCE, 887 var qiCode; 888 889 890 891 //Get QiCode Text to display 892 //if (objQiPositionObject.isValid){ 893 if (objQiPositionObject.QiCodeAlias !=""){ 894 qiCode = objQiPositionObject.QiCodeAlias; 895 } else { 896 qiCode = objQiPositionObject.QiCode; 897 } 898 //} 899 900 901 //If Rectangle Offset is to be applied then use GridCoords NOT Actual Position 902 if (IsSet(applyRectangleOffset)){ 903 if (applyRectangleOffset==true){ 904 googlePosn.lat = objQiPositionObject.GridCoord.lat + ((island.YIncrement)/2); 905 googlePosn.lng = objQiPositionObject.GridCoord.lng - ((island.XIncrement)/2); 906 } 907 } 908 909 910 switch (markerType) { 911 case "bounce": 912 //Blue Pulse 913 if (IsSet(qiCode)){ 914 objOutputMapMarker = new google.maps.Marker({ 915 position: googlePosn, 916 map: objOutputMap, 917 label: {text: qiCode, color:'white', className: 'qiCode-MapMarker-Label',}, 918 title: qiCode, 919 optimized : isOptimized, 920 icon: iconBounceURL, 921 }); 922 } else { 923 objOutputMapMarker = new google.maps.Marker({ 924 position: googlePosn, 925 map: objOutputMap, 926 optimized : isOptimized, 927 icon: iconBounceURL, 928 }); 929 } 930 break; 931 932 case "std": 933 default: 934 //Standard Marker 935 if (IsSet(qiCode)){ 936 objOutputMapMarker = new google.maps.Marker({ 937 position: googlePosn, 938 map: objOutputMap, 939 label: {text: qiCode, color:'white', className: 'qiCode-MapMarker-Label'}, 940 title: qiCode, 941 icon: iconRedMarkerDot, //have to use this as it removes the dot when setting the label 942 }); 943 944 } else { 945 objOutputMapMarker = new google.maps.Marker({ 946 position: googlePosn, 947 map: objOutputMap, 948 }); 949 } 950 break; 951 } 952 //marker.set('labelContent', 'sdda'); 953 954} 955 956function initialise_GridOverlays(){ 957 //Create the 2 overlays for use in the map 958 959 // Define an image map overlay in black. 960 roadmapOverlay = new google.maps.ImageMapType({ 961 getTileUrl: function(coord, zoom) { 962 // Using WMS tile numbering. 963 //window.alert(['https://grid.plus.codes/grid/wms/', zoom, '/', coord.x, '/', coord.y, '.png'].join('')); 964 return ['https://grid.plus.codes/grid/wms/', zoom, '/', coord.x, '/', coord.y, '.png'].join(''); 965 }, 966 tileSize: new google.maps.Size(256, 256) 967 }); 968 969 // Define an image map overlay in white. 970 satelliteOverlay = new google.maps.ImageMapType({ 971 getTileUrl: function(coord, zoom) { 972 // Using WMS tile numbering. 973 //window.alert(['https://grid.plus.codes/grid/wms/', zoom, '/', coord.x, '/', coord.y, '.png?col=white'].join('')); 974 return ['https://grid.plus.codes/grid/wms/', zoom, '/', coord.x, '/', coord.y, '.png?col=white'].join(''); 975 }, 976 tileSize: new google.maps.Size(256, 256) 977 }); 978 979 //Add a Listener to Change the overlay when the map type changes 980 objOutputMap.addListener('maptypeid_changed', outputMap_MapTypeChanged); 981 982} 983 984function getMapType(){ 985 var mapType; 986 try{ 987 mapType = objOutputMap.getMapTypeId(); 988 } catch (err){ 989 mapType = 'satellite'; 990 } 991 return mapType; 992} 993 994function toggleGrid(){ 995 996 if (blnGridShown == false){ 997 //Set Toggle value 998 blnGridShown = true; 999 1000 //Shoe the Grid 1001 showGrid(getMapType()); 1002 } else { 1003 //Set Toggle value 1004 blnGridShown = false; 1005 1006 //Remove Overlays 1007 hideGrid(); 1008 1009 } 1010 1011 //showTheGrid 1012 //grid = new Graticule(objOutputMap, true); 1013} 1014 1015function showGrid(mapTypeId){ 1016 //Display the Grid according to the MapTypeId 1017 1018 hideGrid(); 1019 1020 if (mapTypeId == google.maps.MapTypeId.SATELLITE || 1021 mapTypeId == google.maps.MapTypeId.HYBRID) { 1022 objOutputMap.overlayMapTypes.push(satelliteOverlay); 1023 } else { 1024 objOutputMap.overlayMapTypes.push(roadmapOverlay); 1025 } 1026 1027} 1028 1029function hideGrid(){ 1030 objOutputMap.overlayMapTypes.pop(); 1031} 1032 1033function copyURLToClipboard(callerID, copyMessageID) { 1034 1035 //var strQiCode = document.getElementById('txtNAVQICodeInput').value; 1036 var strQiCode = strCurrentQiCode; 1037 1038 var copyText = getQIEncodedURL(strQiCode, true); 1039 1040 const el = document.createElement('textarea'); 1041 el.value = copyText; 1042 el.setAttribute('readonly', ''); 1043 el.style.position = 'absolute'; 1044 el.style.left = '-9999px'; 1045 document.body.appendChild(el); 1046 el.select(); 1047 document.execCommand('copy'); 1048 document.body.removeChild(el); 1049 1050 if (IsSet(copyMessageID)){ 1051 $('#'+copyMessageID).show(); 1052 $('#'+copyMessageID).fadeOut(3500); 1053 } 1054} 1055 1056function setCodeInputTextBoxValues(objQiPositionObject, setPlaceHolderText){ 1057 //Set the Various QiCode input TextBoxes 1058 1059 var elmBoxQiCodeInput = document.getElementById("txtPOPQICodeInput"); 1060 var elmNavQiCodeInput = document.getElementById("txtNAVQICodeInput"); 1061 var qiCodeToDisplay = ""; 1062 1063 if (!IsSet(setPlaceHolderText)){ 1064 setPlaceHolderText = false; 1065 } 1066 1067 if (setPlaceHolderText){ 1068 elmBoxQiCodeInput.value = ""; 1069 elmNavQiCodeInput.value = ""; 1070 1071 //elmBoxQiCodeInput.attr("placeholder", strPlaceHolderText); 1072 //elmNavQiCodeInput.attr("placeholder", strPlaceHolderText); 1073 } else { 1074 1075 if (objQiPositionObject.isValid){ 1076 if (objQiPositionObject.QiCodeAlias !=""){ 1077 qiCodeToDisplay = objQiPositionObject.QiCodeAlias; 1078 } else { 1079 qiCodeToDisplay = objQiPositionObject.QiCode; 1080 } 1081 } else { 1082 qiCodeToDisplay = "Invalid QiCode"; 1083 } 1084 1085 elmBoxQiCodeInput.value = qiCodeToDisplay; 1086 elmNavQiCodeInput.value = qiCodeToDisplay; 1087 1088 // elmBoxQiCodeInput.attr("placeholder", ""); 1089 // elmNavQiCodeInput.attr("placeholder", ""); 1090 } 1091
1092 //Set the Share Buttons also 1093 setShareButtonsTextValues(objQiPositionObject); 1094} 1095 1096function setShareButtonsTextValues(objQiPositionObject){ 1097 1098 1099 //const strFB_href = "http://www.facebook.com/sharer.php?u={url_to_qi_code}"; 1100 //const strTwitter_href = "http://twitter.com/intent/tweet?url=&original_referer&=hashtags=qi_code&text={url_to_qi_code}" ; 1101 //const strWhatsApp_href="https://api.whatsapp.com/send?text={url_to_qi_code}"; 1102 //const strEmail_href="mailto:[email protected]?&subject=Find%20Me%20at&body=Click%20on%20this%20link%20to%20find%20the%20location%20'{qi_code}'%20I%20found%20at%20qi.gg%20:%20{url_to_qi_code}"; 1103 1104 if (!objQiPositionObject.isValid){ 1105 return; 1106 } 1107 1108 1109 var strQiCode; 1110 1111 if (objQiPositionObject.QiCodeAlias !=""){ 1112 strQiCode = objQiPositionObject.QiCodeAlias; 1113 } else { 1114 strQiCode = objQiPositionObject.QiCode; 1115 } 1116 1117 var elm; 1118 var strhref; 1119 var siteURL = getQIEncodedURL(strQiCode,true); 1120 1121 elm = document.getElementById("lnkShareFacebook"); 1122 strhref = strFB_href.replace("{url_to_qi_code}", encodeURIComponent(siteURL)); 1123 strhref = strhref.replace("{qi_code}", encodeURIComponent(strQiCode)); 1124 elm.href = strhref; 1125 1126 elm = document.getElementById("lnkShareTwitter"); 1127 strhref = strTwitter_href.replace("{url_to_qi_code}", encodeURIComponent(siteURL)); 1128 strhref = strhref.replace("{qi_code}", encodeURIComponent(strQiCode)); 1129 elm.href = strhref; 1130 1131 elm = document.getElementById("lnkShareWhatsApp"); 1132 strhref = strWhatsApp_href.replace("{url_to_qi_code}", encodeURIComponent(siteURL)); 1133 strhref = strhref.replace("{qi_code}", encodeURIComponent(strQiCode)); 1134 elm.href = strhref; 1135 1136 elm = document.getElementById("lnkShareEmail"); 1137 strhref = strEmail_href.replace("{url_to_qi_code}", encodeURIComponent(siteURL)); 1138 strhref = strhref.replace("{qi_code}", encodeURIComponent(strQiCode)); 1139 elm.href = strhref; 1140 1141} 1142 1143//Start : Events ***************************************** 1144function ouputMap_Click(pos){ 1145 //Map Click Event 1146 1147 var posn = { 1148 lat: pos.latLng.lat(), 1149 lng: pos.latLng.lng() 1150 }; 1151 1152 1153 //Trigger the Calculation 1154 processUserEntry(posn, null, false, false, false); 1155} 1156 1157function outputMap_MapTypeChanged(){ 1158 //User selected a different Map Type 1159 1160 //Show a different Overlay (if visible) Depending on the Maptype 1161 if (blnGridShown){ 1162 showGrid(getMapType()); 1163 } 1164 1165} 1166 1167function initialiseMap_foundGeolocationPosn(pos){ 1168 //Initialise the Map based on current location 1169 1170 const posn = { 1171 lat: pos.coords.latitude, 1172 lng: pos.coords.longitude, 1173 }; 1174 1175 1176 //Process as if a UserAction 1177 processUserEntry(posn, null, true, true, true, "bounce"); 1178} 1179 1180function initialiseMap_noGeolocationPosn(err){ 1181 //Geolocation Failed 1182 1183 //Check if the Error was due to a High Accuracy timeout 1184 if (err.code == err.TIMEOUT){ 1185 // Attempt to get GPS loc timed out after 5 seconds, 1186 // try low accuracy location 1187 navigator.geolocation.getCurrentPosition(initialiseMap_foundGeolocationPosn ,initialiseMap_errorCallback_lowAccuracy, {maximumAge:600000, timeout:10000, enableHighAccuracy: fal
1187se}); 1188 return; 1189 } 1190 1191 //Initialise the Map without reference to current location 1192 //Process as if a UserAction in St PP 1193 //processUserEntry(objPosnStPP, null, false, true, true); 1194 var defaultPosn = getDefaultPosition(); 1195 processUserEntry(defaultPosn, null, false, true, true); 1196} 1197 1198 1199 1200function initialiseMap_errorCallback_lowAccuracy(err) { 1201 //A Low Accuracy attempt to get geolocation was tried and has also failed 1202 1203 //Process as if a UserAction in St PP 1204 //processUserEntry(objPosnStPP, null, false, true, true); 1205 var defaultPosn = getDefaultPosition(); 1206 processUserEntry(defaultPosn, null, false, true, true); 1207} 1208 1209//End : Events ****************************************** 1210 1211 1212function IsSet(variable){ 1213 var blnIsSet = true; 1214 if (typeof variable === 'undefined') { 1215 blnIsSet=false; 1216 } else if (variable === null){ 1217 blnIsSet=false; 1218 } 1219 return blnIsSet; 1220} 1221 1222function IsMobileDevice(){ 1223 if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){ 1224 //document.write("mobile"); 1225 return true; 1226 }else{ 1227 //document.write("not mobile"); 1228 return false; 1229 } 1230} 1231 1232function navigateGO(strNavToQiCode){ 1233 //Calculate & Display the Navigation between Current Position & and End Point 1234 1235 var blnEndPointIsValid = false; 1236 1237 1238 //Check a Value has been entered 1239 if (strNavToQiCode == ""){ 1240 if (strCurrentQiCode ==""){ 1241 return; 1242 } else { 1243 strNavToQiCode = strCurrentQiCode; 1244 } 1245 } 1246 1247 //Check the Endpoint is valid 1248 strNavToQiCode = strNavToQiCode.toLowerCase(); 1249 //Set Global Variable Start Point 1250 objNavigateStartPoint = createQiPositionObject(strNavToQiCode, null); 1251 blnEndPointIsValid = objNavigateStartPoint.isValid; 1252 1253 //Keep TextBoxes Synchronized (will aslo swap in any alias discovered) 1254 setCodeInputTextBoxValues(objNavigateStartPoint); 1255 1256 //Process if invalid 1257 if (blnEndPointIsValid){ 1258 1259 if (blnUseQiMapToNavigate==true){ 1260 //Handle the Navigation ourselves : Show Navigation using our Own Map 1261 //Get Current Location (& process in the reply events) 1262 if (navigator.geolocation) { 1263 navigator.geolocation.getCurrentPosition(showNavigate_foundGeolocationPosn, showNavigate_noGeolocationPosn, objGeolocationOptions); 1264 } else { 1265 window.alert("Cannot calculate route. This browser doesn't support geolocation, or permission hasn't been given"); 1266 } 1267 } else { 1268 //Delegate the Navigation to another service 1269 /*Use Google Maps 1270 https://www.google.com/maps/dir/?api=1¶meters 1271 Example : https://www.google.com/maps/dir/?api=1&destination=49.449695,-2.533354 1272 Optional params : 1273 travelmode = driving | walking | bicycling | transit 1274 dir_action = navigate - Launches either turn-by-turn navigation or route preview to the specified destination, based on whether the origin is available. 1275 */ 1276 var googleNavURL = "https://www.google.com/maps/dir/?api=1&destination=" + objNavigateStartPoint.ActualCoord.lat + "," + objNavigateStartPoint.ActualCoord.lng; 1277 googleNavURL += "&travelmode=driving"; 1278 googleNavURL += "&dir_action=navigate"; 1279 window.open(googleNavURL, '_blank'); 1280 } 1281 } 1282 1283} 1284 1285function resetNavigationServices(){ 1286 //Clear any Existing Directions 1287 if(objMapDirectionsService != null) { 1288 objMapDirectionsRenderer.setMap(null); 1289 objMapDirectionsRenderer = null; 1290 1291 objMapDirectionsService = null; 1292 } 1293} 1294 1295function showNavigate_noGeolocationPosn(err){ 1296 //Geolocation not found (or user gave no permission) 1297 window.alert("Cannot calculate route. This browser doesn't support geolocation, or permission hasn't been given."); 1298} 1299 1300function showNavigate_foundGeolocationPosn(pos){ 1301 //Show the route based on the values of Current location and objNavigateStartPoint 1302 1303 const posn = { 1304 lat: pos.coords.latitude, 1305 lng: pos.coords.longitude, 1306 }; 1307 1308 1309 //Clear any Existing Directions 1310 resetNavigationServices(); 1311 1312 //Create the Directions Service & Renderer 1313 objMapDirectionsService = new google.maps.DirectionsService(); 1314 objMapDirectionsRenderer = new google.maps.DirectionsRenderer(); 1315 objMapDirectionsRenderer.setMap(objOutputMap); 1316 1317 //Define the Request 1318 var startPoint = new google.maps.LatLng(posn.lat, posn.lng); 1319 var endPoint = new google.maps.LatLng(objNavigateStartPoint.lat, objNavigateStartPoint.lng); 1320 1321 var request = { 1322 origin: startPoint, 1323 destination: endPoint, 1324 travelMode: 'DRIVING' 1325 }; 1326 1327 //Call for Directions & render it on the map 1328 objMapDirectionsService.route(request, function(result, status) { 1329 //window.alert(status); 1330 if (status == 'OK') { 1331 objMapDirectionsRenderer.setDirections(result); 1332 } 1333 }); 1334 1335} 1336 1337function createGeoCoder(){ 1338 objGeoCoder = new google.maps.Geocoder(); 1339} 1340 1341function createMarkerFromAddress(address) { 1342 address="GY1 1BE"; 1343 1344 objGeoCoder.geocode({ 'address': address }, function (results, status) { 1345 if (status == 'OK') { 1346 var marker = new google.maps.Marker({ 1347 position: address, 1348 map : objOutputMap, 1349 }); 1350 } else { 1351 alert('Geocode was not successful for the following reason: ' + status); 1352 } 1353 1354 }); 1355} 1356 1357 1358
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.