//tool to update dataase: display markers and edit positions //http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback //nb in google maps it says "DIT" in the middle of the provost's stables /* showPlaces(type) showPlace(index) Tim Redfern: 20-05-13 --> added static display of 'popular places' switched permalinks to index by number */ //------------------------------------------------------------------------globals var http = getHTTPObject(); //old ajax method var markers=[]; var markertypes=['Building','Parking','Entrances']; //--lat/lng based tables to create markers var tables=[]; var tablenames=['AZ','Lecture_theatres','Pacr','Libraries','Loops','Enabled_toilets']; //--tables reference building table var tablescreennames={'Lecture_theatres':"Lecture theatres",'Pacr':"Public access computer rooms",'Libraries':"Libraries",'Loops':"Hearing aid looops",'Enabled_toilets':"Enabled toilets"}; var icontypes=['Loops','Enabled_toilets']; var places=[]; var placetypes=new Array('Lecture_theatres','Libraries','Pacr'); var screenplacetypes=new Array('Lecture theatres','Libraries','Public access computer rooms'); for (i=0;i>> 0; // Hack to convert O.length to a UInt32 // 4. If IsCallable(callback) is false, throw a TypeError exception. // See: http://es5.github.com/#x9.11 if ( {}.toString.call(callback) !== "[object Function]" ) { throw new TypeError( callback + " is not a function" ); } // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. if ( thisArg ) { T = thisArg; } // 6. Let k be 0 k = 0; // 7. Repeat, while k < len while( k < len ) { var kValue; // a. Let Pk be ToString(k). // This is implicit for LHS operands of the in operator // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. // This step can be combined with c // c. If kPresent is true, then if ( Object.prototype.hasOwnProperty.call(O, k) ) { // i. Let kValue be the result of calling the Get internal method of O with argument Pk. kValue = O[ k ]; // ii. Call the Call internal method of callback with T as the this value and // argument list containing kValue, k, and O. callback.call( T, kValue, k, O ); } // d. Increase k by 1. k++; } // 8. return undefined }; } // DS changed to declare map globally to avoid issue in IE8 //http://stackoverflow.com/questions/10729421/what-is-causing-a-google-maps-error-in-ie8 var map; // DS using DOM onload instead of window.onload $(function() { var mapEl = document.getElementById("map"); if(mapEl) { var mapOptions = { center: STARTPOS, zoom: 17, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map"), mapOptions); directionsService = new G.DirectionsService(); directionsDisplay = new G.DirectionsRenderer({Map:map}); //load data via ajax - chaining other loading functions loadTables(tablenames); } callback_for_resizing(); }); function loadTables(t) { t.forEach(function(table) { $.getJSON("./loadTable.php","table="+table,function(d) { $.each(d, function(idx,v) { tables[idx]=[]; for (i in v) { // DS to account for forEach polyfill if (i != 'foreach') { tables[idx].push(v[i]); } } if (DEBUG) console.log("loaded table "+Object.keys(tables).length+":"+idx+","+tables[idx].length+" items"); if (Object.keys(tables).length==tablenames.length) loadMarkers(markertypes); }); }); }); } //how to know when everything is loaded via ajax and data can be processed function loadMarkers(m) { //---------build customised markers from a database table m.forEach(function(marker) { $.getJSON("./loadTable.php","table="+marker,function(d) { $.each(d, function(idx,v) { markers[idx]=[]; for (i in v) { // DS to account for forEach polyfill if (i != 'foreach') { markers[idx][i]=makeMarker(v[i],idx); //console.log("making "+i+": "+ } } markers[idx].visible=false; if (DEBUG) console.log("loaded markers "+Object.keys(markers).length+":"+idx+","+markers[idx].length+" items"); if (Object.keys(markers).length==markertypes.length) { prepareData(); do_menuchoices(); //console.log("search:"+search_posted); // Check if the POST search variables (query/building) was passed to Javascript. if (building_posted != ''&&parseInt(building_posted)>0) { show_building(parseInt(building_posted)); } else if (search_posted != '') { onsearch(search_posted); } } }); }); }); } function makeMarker(data,type) { if (DEBUG) console.log(type+":"+data['lat']+","+data['lng']); //alert doesn't work within a jquery callback but console.log does var m=new G.Marker({position:new G.LatLng(data['lat'],data['lng']),map:null,draggable:EDITABLE}); m["type"]=type; for (j in data) m[j]=data[j]; m.places=[]; m.tabVisible=false; m.visible=false; if (EDITABLE){ G.event.addListener(m,"dragend",setMarkerPosition); G.event.addListener(m,"click",displayMarkerInfo); if (type=="Building"&&m.google_coords==1) { m.setIcon(new G.MarkerImage("http://maps.google.com/mapfiles/marker_orange.png")); } } switch (type) { case "Parking": m.setIcon(new G.MarkerImage("img/marker_parking.png")); break; case 'Entrances': m.setIcon(new G.MarkerImage("img/marker_entrance.png")); break; case 'Loops': m.setIcon(new G.MarkerImage("img/marker_loop.png")); break; case 'Enabled_toilets': m.setIcon(new G.MarkerImage("img/marker_accessible_toilet.png")); break; case 'Ramps': m.setIcon(new G.MarkerImage("img/marker_ramp.png")); break; default: break; } m.setShadow(new G.MarkerImage("img/marker_shadow.png",new G.Size(30,30),new G.Point(0,0),new G.Point(6,29))); if (type=="Building") { m.sortPlaces=function() {m.places.sort(function(a,b) {if (a.name1||this.description) { //multi-tab this.showtab = function() { purgeInfoWindow(); InfoWindow=new InfoBubble({disableAnimation:true}); InfoWindow.addTab('Building',this.getPlacesTab()); InfoWindow.addTab('More',this.getInfoTab()); InfoWindow.open(map,this); this.tabVisible=true; } } //single tab else { this.showtab = function() { purgeInfoWindow(); InfoWindow=new InfoBubble({content:this.getPlacesTab(),disableAnimation:true});; InfoWindow.open(map,this); this.tabVisible=true; } } G.event.addListener(this,"click",this.showtab); this.setMap(map); var boundscheck=map.getBounds(); if (boundscheck && (!boundscheck.contains(this.getPosition()))&&this.type=="Building") //only zoom to accomodate buildings { boundscheck.extend(this.getPosition()); var newzoom = getZoomByBounds( map, boundscheck ); map.setZoom(newzoom); map.setCenter(boundscheck.getCenter()); } this.visible=true; } if (tab) this.showtab(); } } if (type=="Entrances") { //construct tabs m.show = function (tab){ this.showtab = function() { purgeInfoWindow(); InfoWindow=new InfoBubble({content:this.getEntranceTab(),disableAnimation:true}); InfoWindow.open(map,this); this.tabVisible=true; } G.event.addListener(this,"click",this.showtab); this.setMap(map); var boundscheck=map.getBounds(); if ((!boundscheck.contains(this.getPosition()))&&this.type=="Building") //only zoom to accomodate buildings { boundscheck.extend(this.getPosition()); var newzoom = getZoomByBounds( map, boundscheck ); if (newzoom<15) map.setMapType(G_NORMAL_MAP); map.setZoom(newzoom); map.setCenter(boundscheck.getCenter()); } this.visible=true; if (tab) this.showtab(); } } if (type=="Enabled_toilets") { //construct tabs m.show = function (tab){ if (this.data !="") { this.showtab = function() { purgeInfoWindow(); InfoWindow=new InfoBubble({content:this.getToiletTab(),disableAnimation:true}); InfoWindow.open(map,this); this.tabVisible=true; } } G.event.addListener(this,"click",this.showtab); this.setMap(map); var boundscheck=map.getBounds(); if ((!boundscheck.contains(this.getPosition()))&&this.type=="Building") //only zoom to accomodate buildings { boundscheck.extend(this.getPosition()); var newzoom = getZoomByBounds( map, boundscheck ); if (newzoom<15) map.setMapType(G_NORMAL_MAP); map.setZoom(newzoom); map.setCenter(boundscheck.getCenter()); } this.visible=true; if (tab) this.showtab(); } } if (type=="Loops"||type=="Parking") { m.show = function (tab){ this.setMap(map); var boundscheck=map.getBounds(); if ((!boundscheck.contains(this.getPosition()))&&this.type=="Building") //only zoom to accomodate buildings { boundscheck.extend(this.getPosition()); var newzoom = getZoomByBounds( map, boundscheck ); if (newzoom<15) map.setMapType(G_NORMAL_MAP); map.setZoom(newzoom); map.setCenter(boundscheck.getCenter()); } this.visible=true; } } m.hide = function() { if (!(this.type=="Loops"||this.type=="Parking")) { G.event.clearListeners(this,"click"); } if (this.tabVisible) { purgeInfoWindow(); this.tabVisible=false; } this.visible=false; this.setMap(null); } m.getPlacesTab=getPlacesTab; m.getInfoTab=getInfoTab; m.getEntranceTab=getEntranceTab; m.getToiletTab=getToiletTab; return m; } //----------------------------------------------------------------------------------functions to populate tabs called from marker function getPlacesTab() { var popup="

"+this.name+"

"; popup+="
"; if (this.dispphoto) { popup+="
"; popup+=""; popup+="
"; } if (this.opening_hours) { popup+="
"; popup +='
Building Opening Hours:
'; popup +='
'+this.opening_hours+"
"; popup+="
"; } if ((this.accessibility)||(this.accessibility_url)) { popup+="
"; if (this.accessibility) { popup+="
Accessibility:
"+this.accessibility+" "; if (this.accessibility_url) popup+="(more info)
"; } else if (this.accessibility_url) popup+=""; popup+="
"; } popup+="
"; popup+=""; return popup; } function getInfoTab() { popup=""; popup+="
"; popup+="
"; //
"; var placeoffset=0; if (this.places.length-placeoffset) { popup+="

Also in this building

    "; for (i=0;i"+this.places[i].name+""; } else { popup +="
  • "+this.places[i].name+"
  • "; } } } popup+="
"; } if (this.description) popup+="

Info

"+this.description; popup+="
"; return popup; } function getToiletTab() { popup=""; popup+="
"; popup+="
"; popup+="

Enabled toilet

" popup+="
"+this.data; popup+="
"; return popup; } function getEntranceTab() { popup=""; popup+="
"; popup+="
"; popup+="

Entrance

" popup+="
"+this.data; popup+="
"; return popup; } //----------------------------------------------------------------------------------Setting up data structures while loading function prepareData() { //create markers for ref tables for (i in icontypes) { markers[icontypes[i]]=[]; for (t in tables[icontypes[i]]) { // DS accounting for forEach if (t != 'forEach') { // DS to avoid an undefined building in IE <= 8 if (markers["Building"][tables[icontypes[i]][t].building]) { tables[icontypes[i]][t].lat=markers["Building"][tables[icontypes[i]][t].building].lat; tables[icontypes[i]][t].lng=markers["Building"][tables[icontypes[i]][t].building].lng; tables[icontypes[i]][t].id=tables[icontypes[i]][t].building; markers[icontypes[i]].push(makeMarker(tables[icontypes[i]][t],icontypes[i])); } } } markers[icontypes[i]].visible=false; } //process Building and AZ tables //create AZ -- is causing problems now for some reason WHERE THERE ARE NO ITEMS for (var i=0;i<26;i++) { tables[String.fromCharCode(i+65)]=[]; tables[String.fromCharCode(i+65)].screenname=String.fromCharCode(i+65); } //Create alphabetical lists of places including exceptions for (var i=0;i25) startlet-=32; //select small letters (which shouldn't even be there) if ((startlet==96)||(startlet==128)) startlet=0; //catch Á if (startlet==104) startlet=4; //catch É if (startlet==108) startlet=8; //catch Í //find array number of building index as buildingindex number can be non-consecutive var bb=tables["AZ"][i].building; for (j in markers['Building']) { if (markers['Building'][j].id==bb) { numplaces=tables[String.fromCharCode(startlet+65)].length; tables[String.fromCharCode(startlet+65)].push(tables["AZ"][i]); //add reference to place tables[String.fromCharCode(startlet+65)][numplaces].building=j; //resolve reference to building array tables[String.fromCharCode(startlet+65)][numplaces].index=i; //resolve reference to AZ array markers['Building'][j].places.push(tables["AZ"][i]); } } if (tables["AZ"][i].name.slice(0,3)=="St.") { startlet=tables["AZ"][i].name.charCodeAt(4) -65; if (startlet>25) startlet-=32; //select small letters //we know its doesn't start with ÁÉÍ for (j in markers['Building']) { if (markers['Building'][j].id==bb) { numplaces=tables[String.fromCharCode(startlet+65)].length; tables[String.fromCharCode(startlet+65)].push(tables["AZ"][i]); //add reference to place tables[String.fromCharCode(startlet+65)][numplaces].building=j; //resolve reference to building array markers['Building'][j].places.push(tables["AZ"][i]); } } } } } //add buildings for (i in markers['Building']) { if (markers['Building'][i].name) { //trap added 'visible' property var j=0; var startlet=0; while (markers['Building'][i].name.charCodeAt(j) <64) j++; //find 1st non-number startlet=markers['Building'][i].name.charCodeAt(j) -65; if (startlet>25) startlet-=32; //select small letters (which shouldn't even be there) if ((startlet==96)||(startlet==128)) startlet=0; //catch Á if (startlet==104) startlet=4; //catch É if (startlet==108) startlet=8; //catch Í numplaces=tables[String.fromCharCode(startlet+65)].length; tables[String.fromCharCode(startlet+65)].push(new place(markers['Building'][i].name,i,markers['Building'][i].info)); tables[String.fromCharCode(startlet+65)][numplaces].building=i; //resolve reference to building array } } //sort results alphabetically for (i=0;i<26;i++) { letter=String.fromCharCode(i+65); tables[letter].sort(function(a,b) { if (a.name"+letter+" "; } menu+=""; document.getElementById("searchoptions").innerHTML=menu; //action='map.php' menu="
"; document.getElementById("quicklinkswrap").innerHTML=menu; } //----------------------------------------------------------------------------------Editing markers while authoring function setMarkerPosition() { if (this.type=="Building") { $.ajax({ url:"setMarkerPos.php", data: "table="+this.type+"&id="+this.id+"&lat="+this.getPosition().lat()+"&lng="+this.getPosition().lng()+"&google_coords=1" }); this.setIcon(new G.MarkerImage("http://maps.google.com/mapfiles/marker_orange.png") ); } else { $.ajax({ url:"setMarkerPos.php", data: "table="+this.type+"&id="+this.id+"&lat="+this.getPosition().lat()+"&lng="+this.getPosition().lng() }); } } function displayMarkerInfo(){ if (this.type=="Building") document.getElementById("info").innerHTML=this.id+": "+this.name; else document.getElementById("info").innerHTML=this.id; } //----------------------------------------------------------------------------------Interaction handlers function shadowbox(n) { Shadowbox.open({content:"./photos/"+n+".jpg",player: "img",title:markers['Building'][n].name}); } function onsearch(query) { if (/^[0-9]+$/.test(query)) { //^\d show_building(query); } else { tables["search"]=[]; var foundbuildings=new Array(); fb=0; for (var i=0;i<26;i++) { //console.log("checking "+String.fromCharCode(i+65)); for (j in tables[String.fromCharCode(i+65)]) { if (tables[String.fromCharCode(i+65)][j]!=undefined) { //console.log("checking "+j+": "+tables[String.fromCharCode(i+65)][j].name); if ("name" in tables[String.fromCharCode(i+65)][j]) { if (tables[String.fromCharCode(i+65)][j].name.toLowerCase().indexOf(query.toLowerCase())>-1) { tables["search"].push(tables[String.fromCharCode(i+65)][j]); if (foundbuildings[tables[String.fromCharCode(i+65)][j].building]!="1") fb++; foundbuildings[tables[String.fromCharCode(i+65)][j].building]="1"; } } } } } //auto-open if 1 search result if (fb==1) { clearmarkers(); markers["Building"][tables["search"][0].building].show(true,tables["search"][0]); } tables["search"].screenname=query; tables["search"].sort(function(a,b) {if (a.name"+tables[type][i].name+""; } content+=""; document.getElementById("searchresults").innerHTML=content; if(do_menu_flag) { resize_map_and_results(); } else { do_menu_flag = true; } if (DEBUG) alert(content); } } function purgeInfoWindow() { if (InfoWindow) { //console.log("closing infowindow"); InfoWindow.close(); InfoWindow=undefined; } } function clearmarkers() { for (i in markers) { for (j in markers[i]) { if (markers[i][j] && markers[i][j].name) markers[i][j].hide; } } } function directions(lat,lng,place){ document.getElementById("searchresulttitle").innerHTML="

From Trinity College to "+place+"

"; document.getElementById("searchresults").innerHTML=""; var request = { origin:new G.LatLng(53.3445,-6.259), destination:new G.LatLng(lat,lng), travelMode: google.maps.DirectionsTravelMode.DRIVING }; directionsDisplay.setPanel(document.getElementById("searchresults")); directionsService.route(request, function(response, status) { if (status == G.DirectionsStatus.OK) { directionsDisplay.setDirections(response); } }); } //----------------------------------------------------------------------------------misc utils, legacy ajax stuff to bypass TCD fuzzy filename filter //Equivalent of getBoundsZoomLevel() in gmaps api 3 /** * Returns the zoom level at which the given rectangular region fits in the map view. * The zoom level is computed for the currently selected map type. * @param {google.maps.Map} map * @param {google.maps.LatLngBounds} bounds * @return {Number} zoom level **/ function getZoomByBounds( map, bounds ){ var MAX_ZOOM = map.mapTypes.get( map.getMapTypeId() ).maxZoom || 21 ; var MIN_ZOOM = map.mapTypes.get( map.getMapTypeId() ).minZoom || 0 ; var ne= map.getProjection().fromLatLngToPoint( bounds.getNorthEast() ); var sw= map.getProjection().fromLatLngToPoint( bounds.getSouthWest() ); var worldCoordWidth = Math.abs(ne.x-sw.x); var worldCoordHeight = Math.abs(ne.y-sw.y); //Fit padding in pixels var FIT_PAD = 40; for( var zoom = MAX_ZOOM; zoom >= MIN_ZOOM; --zoom ){ if( worldCoordWidth*(1< 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return escape(utftext); } function httpexists(url) { exists=false; http.open("GET",'httpexists-proxy.php?httpexistsurl=' + url, false); //http.open("GET", url, false); http.send(null); if (http.status == 200) { exists=true; } return exists; } function getHTTPObject() { var xmlhttp; if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp = false; } } return xmlhttp; }