This is my code. I get the data from xml. What I want is:
if a piece of data is null, don't show that row. How can I do it?
downloadUrl("xml/cat.xml", function(doc) {
var xml = xmlParse(doc);
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
// obtain the attribues of each marker
var lat = parseFloat(markers[i].getAttribute("lat"));
var lng = parseFloat(markers[i].getAttribute("lng"));
var point = new google.maps.LatLng(lat,lng);
var kWa = markers[i].getAttribute("kWa");
var html = 'rows here ';
Sorry for wrong question..
i want to hide here
var html = '
id='+id+', kwa='+kwa+' // if id is null how can hide item in here..?
';
You can do this with if checks like:
if(markers[i].getAttribute("lat") != NULL) // or "NULL" as a string if thats what is returned."
var lat = parseFloat(markers[i].getAttribute("lat));
Or you could put it in a try - catch statement:
for (//codes){
try{
//try parsing here
}catch(e){
if(e) // do something with the error
}
Which has the advantage of letting you do something for each error message. But the disadvantage of being slow. (though not as slow as it used to be in javascript)
Related
I am trying to print the address and details of my clinics in various locations. However, when i try to do that it is only printing the first element in my div.
Here is my code
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var id = markerNodes[i].getAttribute("id");
var locname = markerNodes[i].getAttribute("locationName");
var locaddress = markerNodes[i].getAttribute("locationAddress1");
var address = markerNodes[i].getAttribute("locationAddress1");
var distance = parseFloat(markerNodes[i].getAttribute("distance"));
var servicename = markerNodes[i].getAttribute("serviceName");
var clinicfname= markerNodes[i].getAttribute("clinicFname");
var cliniclname= markerNodes[i].getAttribute("clinicLname");
var clinicname= clinicfname + ' ' + cliniclname ;
var clinicAddress= markerNodes[i].getAttribute("clinicAddress");
var clinicCity= markerNodes[i].getAttribute("clinicCity");
var clinicPhone= markerNodes[i].getAttribute("clinicPhone");
var cname= markerNodes[i].getAttribute("cname");
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("locationLat")),
parseFloat(markerNodes[i].getAttribute("locationLong")));
document.getElementById('details_name').innerHTML = clinicname;
//console.log (parseFloat(markerNodes[i].getAttribute("locationLong")));
createdetails(clinicname,clinicAddress)
bounds.extend(latlng);
}
In above code am calling a function name createdetails
function createdetails(clinicname,clinicAddress)
{
document.getElementById("details_name").innerHTML=clinicname;
document.getElementById("details_address").innerHTML=clinicAddress;
}
But this div is priniting only first name and first addrees.It have 9 diffrent values for name and address.When i consoled it,it prints.
What is the problem here?
When you are calling document.getElementById("details_name").innerHTML = ..., you are overwriting the current value. Maybe you should append the new name to the existing content with +=:
function createdetails(clinicname,clinicAddress)
{
document.getElementById("details_name").innerHTML+=clinicname;
document.getElementById("details_address").innerHTML+=clinicAddress;
}
I have a website that gets locations out of a MySQL database and passes it to a JavaScript function as a JSON object. The JavaScript function dynamically creates tables for each row returned from the database. Each location object returned includes a latitude and longitude and I want to create a Google map for each object. I can successfully create 1 map on the page using data returned from the database but when I add the map creation code to the loop that builds tables it begins throwing this error:
TypeError: Cannot read property 'offsetWidth' of null
I have gone through other questions that people have posted about this error. The two causes that it can have are either (1) the <div> I am trying to add the map to doesn't exist, or (2) I am trying to display the map before it is created. I know that the <div>s exist as they exist in the page when it is displayed. I am not sure how to check for or fix the other issue.
This is my JavaScript that retrieves data and builds the tables:
google.maps.event.addDomListener(window, "load");
//THIS FUNCTIONS BUILD THE MAPS
//PASS LAT, LONG, AND ID FOR DIV
function initializeMap(latitude,longitude, mapID)
{
var myCenter = new google.maps.LatLng(latitude, longitude);
var mapProp =
{
center:myCenter,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map=new google.maps.Map(document.getElementById(mapID), mapProp);
var marker=new google.maps.Marker({
position:myCenter,
});
marker.setMap(map);
}
function removeTable()
{
$("#tableID").remove();
}
/*
ajaxRequest variable receives and parses a JSON object into a 2 dimensional array
an example of what a single row returned will look like: [["2","Alexandra","33 GRANT STREET","ALEXANDRA","3714","57721040","-37.18859863281250000000","145.70799255371094000000","","security"]]
when trying to access elements in the array using a loop, columns are as follows:
ajaxRequest[i][0] = database id
ajaxRequest[i][1] = name
ajaxRequest[i][2] = address
ajaxRequest[i][3] = suburb
ajaxRequest[i][4] = postcode
ajaxRequest[i][5] = phone
ajaxRequest[i][6] = latitude
ajaxRequest[i][7] = longitude
ajaxRequest[i][8] = description
ajaxRequest[i][9] = service_type
*/
function search(option)
{
var ajaxRequest;
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
}catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
}catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
}catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
/*
1 = unsafe
2 = depressed
3 = sad
*/
if(option == 1)
{ajaxRequest.open("GET", "securitymodel.php", true);}
if(option == 2)
{ajaxRequest.open("GET", "depressedModel.php", true);}
if(option == 3)
{ajaxRequest.open("GET", "sadmodel.php", true);}
ajaxRequest.send(null);
// Create a function that will receive data
// sent from the server and will update
// div section in the same page.
var ajaxResult = 1;
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
var ajaxDisplay = document.getElementById('ajaxDiv');
//ajaxDisplay.innerHTML = ajaxRequest.responseText;
ajaxResult = JSON.parse(ajaxRequest.responseText);
if(ajaxResult.length > 0)
{
//IF SOMETHING IS RETURNED BEGIN BUILDING THE TABLE
var tableLocation = document.getElementById('suggestionTable');
var tableArea = document.createElement('table');
tableArea.id = 'tableID';
for(var i = 0; i < ajaxResult.length; i++)
{ //create inner row
var innerRow = document.createElement('tr');
var innerTD = document.createElement('td');
//WE MUST GO DEEPER!!!
var innerTable = document.createElement('table');
var superInnerTD = document.createElement('td');
var secondSuperInnerTD = document.createElement('td');
//row 1
var nameTR = document.createElement('tr');
var nameHead = document.createElement('td');
var name = document.createTextNode('Name:');
nameHead.appendChild(name);
nameTR.appendChild(nameHead);
var nameTD = document.createElement('td');
var nameText = document.createTextNode(ajaxResult[i][1]);
nameTD.appendChild(nameText);
nameTR.appendChild(nameTD);
superInnerTD.appendChild(nameTR);
//row 2
var descTR = document.createElement('tr');
var descHead = document.createElement('td');
var desc = document.createTextNode('Description:');
descHead.appendChild(desc);
descTR.appendChild(descHead);
var descTD = document.createElement('td');
var descText = document.createTextNode(ajaxResult[i][8]);
descTD.appendChild(descText);
descTR.appendChild(descTD);
superInnerTD.appendChild(descTR);
//row 3
var addTR = document.createElement('tr');
var addressHead = document.createElement('td');
var address = document.createTextNode('Address:');
addressHead.appendChild(address);
addTR.appendChild(addressHead);
var addTD = document.createElement('td');
var addressText = document.createTextNode(ajaxResult[i][2]);
addTD.appendChild(addressText);
addTR.appendChild(addTD);
superInnerTD.appendChild(addTR);
//row 4
var subTR = document.createElement('tr');
var suburbHead = document.createElement('td');
var suburb = document.createTextNode('Suburb:');
suburbHead.appendChild(suburb);
subTR.appendChild(suburbHead);
var subTD = document.createElement('td');
var subText = document.createTextNode(ajaxResult[i][3]);
subTD.appendChild(subText);
subTR.appendChild(subTD);
superInnerTD.appendChild(subTR);
//row 5
var postTR = document.createElement('tr');
var postcodeHead = document.createElement('td');
var postcode = document.createTextNode('Postcode:');
postcodeHead.appendChild(postcode);
postTR.appendChild(postcodeHead);
var postTD = document.createElement('td');
var postText = document.createTextNode(ajaxResult[i][4]);
postTD.appendChild(postText);
postTR.appendChild(postTD);
superInnerTD.appendChild(postTR);
//row 6
var phoneTR = document.createElement('tr');
var phoneHead = document.createElement('td');
var phone = document.createTextNode('Phone:');
phoneHead.appendChild(phone);
phoneTR.appendChild(phoneHead);
var phoneTD = document.createElement('td');
var phoneText = document.createTextNode(ajaxResult[i][5]);
phoneTD.appendChild(phoneText);
phoneTR.appendChild(phoneTD);
superInnerTD.appendChild(phoneTR);
//The divContainer requires an id
//ID IS AUTOMATICALLY GENERATED BY CONACTENATING THE NAME AND ADDRESS TOGETHER
var mapID = ajaxResult[i][1]+ajaxResult[i][2];
var divContainer = document.createElement("div");
divContainer.setAttribute("id", mapID);
secondSuperInnerTD.appendChild(divContainer);
initializeMap(ajaxResult[i][6],ajaxResult[i][7],mapID);
innerTable.appendChild(superInnerTD);
innerTable.appendChild(secondSuperInnerTD);
innerTD.appendChild(innerTable);
innerRow.appendChild(innerTD);
tableArea.appendChild(innerRow);
}
tableLocation.appendChild(tableArea);
}
}
}
}
An example of a completed table looks like:
We want to put the map in the <td> on the right.
To reiterate, the map generation works when we are trying to build 1 map in a <div> that is coded in html on the page. When we try to create several maps inside <div>s that are dynamically created it fails.
The call to initialize the map happens before the div is added to the DOM.
initializeMap(ajaxResult[i][6],ajaxResult[i][7],mapID);
The above line is called before the following line :
tableLocation.appendChild(tableArea);
The map divs that you create dynamically are added to the page when this line is executed. Due to this you are getting the error.
One workaround would be to use settimeout so that the initialize function is called after the map divs are added to the DOM.
setTimeout(function(){ initializeMap(ajaxResult[i][6],ajaxResult[i][7],mapID); }, 500);
Another option is to push the data into an array and iterate that array after the tableLocation.appendChild(tableArea); line and then call the intializeMap function using that data
I'm trying to get the lat and lon from a Json encoded file for use as destinations for the distance Matrix API rather than add var destinationA = new google.maps.LatLng(??.????, ???.?????); multiple times.
I thought I managed it, as both ways seem to produce the same variable destinations when viewed, yet method two produces an error Uncaught TypeError: a.lat is not a function
This is method one which gives var destination a length of 7:
var destinationA = new google.maps.LatLng(13.7373393, 100.5558883);
var destinationB = new google.maps.LatLng(13.735132, 100.55611199999998);
var destinationC = new google.maps.LatLng(13.736953, 100.55819300000007);
var destinationD = new google.maps.LatLng(13.736244, 100.55694100000005);
var destinationE = new google.maps.LatLng(13.736166, 100.557203);
var destinationF = new google.maps.LatLng(13.738747, 100.55587700000001);
var destinationG = new google.maps.LatLng(13.733558, 100.56020699999999);
var destinations = [destinationA,destinationB,destinationC,destinationD,destinationE,destinationF,destinationG];
works great, will return the distances for each from a given centre point on google map.
Method two:
This is method Two which gives var destination a length of 1, which I am stuck on finding out why its a single length and not 7 as above:
var location_lat_lon = <?php echo json_encode( $properties_data ); ?>;
var destinations = []
var first = true;
for (var i=0; i < location_lat_lon.length; i++) {
var sep = first ? '' : ',';
var lat = location_lat_lon[i].latitude;
var lon = location_lat_lon[i].longitude;
var destination1 = new google.maps.LatLng(lat, lon);
var destinations = [destinations+sep+destination1] ;
first = false;
}
which returns exactly the same result when viewing the variable destinations, yet this returns the error Uncaught TypeError: a.lat is not a function.
Any advice or guidance?
Is it not possible to pass destinations this way to the calculateDistances function?
Thanks in Advance :)
Try this:
var location_lat_lon = <?php echo json_encode( $properties_data ); ?>;
var destinations = []
for (var i=0; i < location_lat_lon.length; i++) {
var lat = location_lat_lon[i].latitude;
var lon = location_lat_lon[i].longitude;
var destination1 = new google.maps.LatLng(parseFloat(lat), parseFloat(lon));
destinations.push(destination1);
}
I'm trying to parse an xml Object in extendscript and especially deal with the Attributes. I know i can access xml attributes by
xmlObj.#attributename
and
xmlObj.attributes()
returns a list of all attributes, but I also need the attribute names not just the values. Is there anyway to get something like and associative array/object with names and values?
(I use extendscript for illustrator CS6)
thank you,
arno
The code below should get you going. Take also a look into the XMLElement Object.
var main = function() {
// create some xml and write it to file
var root = new XML("<root/>");
var child = new XML("<child/>");
child.#string = "Hello Attribute"; // jshint ignore:line
child.#num = 23; // jshint ignore:line
root.appendChild(child);
var file = new File("~/Desktop/test.xml");
var xml = root.toXMLString();
file.open("W");
file.write(xml);
file.close();
// get the current doc
var doc = app.activeDocument;
// import the xml
doc.importXML(file);
// get the elements
var xmlroot = doc.xmlElements[0];
var xmlchild = xmlroot.xmlElements[0];
// loop all attributes of element "child"
// and write them into the console
for (var i = 0; i < xmlchild.xmlAttributes.length; i++) {
var attr = xmlchild.xmlAttributes[i];
$.writeln(attr.name);
}
};
main();
i've found a way solve it with regular Expressions
function getAttributes(xml_node_str) {
// select the start tag <elem >
var reg_exp = /<[^>]*>/;
var start_tag_str = reg_exp.exec(xml_node_str);
// extract the attributes
reg_exp = /[^"\s]*="[^"]*"/g;
var result;
var attributes = [];
while ((result = reg_exp.exec(start_tag_str)) !== null) {
// the attribute (name="value")
var attr = result[0];
// array containing name and "value"
var attr_arr = attr.split('=');
// delete the "'s
attr_arr[1] = attr_arr[1].substr(1, attr_arr[1].length - 2);
attributes.push(attr_arr);
}
return attributes;
}
I still parse the xml with Extendscripts/Illustrators xml-class and then extract the attributes manually
var xml = <root><obj a1="01" a2="02" ></obj></root > ;
var attributes = getAttributes(xml.obj.toXMLString());
for (var i = 0; i < attributes.length; i++) {
alert(attributes[i][0] + ' -> ' + attributes[i][1]);
}
http://rca2.com/mapping/thispageblinks.htm
http://rca2.com/mapping/doesnotremove.htm
The second example really doesn't do anything without continuously updated xml data.
I'm converting (finally!) my map applications from Google v2 to v3. In v2, the application read in xml data every 5 seconds, cleared markers, then new markers were created and placed on the map. The ability to clear the map overlay using map.clearOverlays() no longer exists in v3. The suggested solution is to keep track of the old markers, then remove them. Clearing the markers in a loop prior to creating new markers is easy to do, and works. Except for the fact that the markers blink when replaced more often than not. This is very distracting, and highly undesirable since this did not happen in v2.
I decided that I should compare the new marker data to the old marker data. If the location and icon color stayed the same, both old and new markers are basically ignored. For the sake of clarity, the icon color signifies a status of the vehicle represented by the icon. In this case the application is to track ambulance activity, so green would be available, blue would be en-route, etc.
The code handles the checking of the new and old markers fine, but for some reason, it will never remove the old marker when a marker (unit) moves. I saw suggestions about setMap() being asynchronous. I also saw suggestions about the arrays not being google.maps.Marker objects. I believe that my code handles each of these issues correctly, however the old markers are still never removed.
I've also made sure that my marker arrays are global variables. I am also using the variable side_bar_html to display information about which markers were supposed to be removed, and which markers were supposed to be added. The added markers are being added just fine. I just don't know where to turn next. Any help you could offer would be greatly appreciated.
function getMarkers() {
// create a new connection to get our xml data
var Connect = new XMLHttpRequest();
// send the get request
Connect.open("GET", xml_file, false);
Connect.setRequestHeader("Content-Type", "text/xml");
Connect.send(null);
// Place the response in an XML document.
var xmlDoc = Connect.responseXML;
// obtain the array of markers and loop through it
var marker_data = xmlDoc.documentElement.getElementsByTagName("marker");
// hide the info window, otherwise it still stays open where a potentially removed marker used to be
infowindow.close();
// reset the side_bar and clear the arrays
side_bar_html = "";
markerInfo = [];
newMarkers = [];
remMarkers = [];
addMarkers = [];
// obtain the attributes of each marker
for (var i = 0; i < marker_data.length; i++) {
var latData = marker_data[i].getAttribute("lat");
var lngData = marker_data[i].getAttribute("lng");
var minfo = marker_data[i].getAttribute("html");
var name = marker_data[i].getAttribute("label");
var icontype = marker_data[i].getAttribute("icontype");
var unitNum = marker_data[i].getAttribute("unitNum");
var llIcon = latData + lngData + icontype;
zIndexNum = zIndexNum + 1;
// create the new marker data needed
var myLatLng = new google.maps.LatLng(parseFloat(latData), parseFloat(lngData));
var marker = {
position: myLatLng,
icon: gicons[icontype],
title: "",
unitIcon: unitNum,
unitLLIData: llIcon,
zIndex: zIndexNum
};
// add a line to the side_bar html
// side_bar_html += '<a href="javascript:myclick(' + i + ')">' + name + '<\/a><br />';
// add an event listeners on the marker
addInfoWindow(marker, minfo);
// save the current data for later comparison
markerInfo.push(minfo);
newMarkers.push(marker);
}
// now loop thru the old marker data and compare to the new, to see if we need to remove any old markers
var refreshIt = true;
var removeIt = true;
var currNumber = "";
var currLLIcon = "";
var lastNumber = "";
var lastLLIcon = "";
for (var i = 0; i < newMarkers.length; i++) {
currNumber = newMarkers[i].unitIcon;
currLLIcon = newMarkers[i].unitLLIData;
for (var j = 0; j < oldMarkers.length; j++) {
refreshIt = true;
lastNumber = oldMarkers[j].unitIcon;
lastLLIcon = oldMarkers[j].unitLLIData;
if (lastNumber == currNumber) {
if (currLLIcon == lastLLIcon) {
refreshIt = false;
} else {
refreshIt = true;
remMarkers.push(oldMarkers[j]);
}
break;
}
}
// if we need to refresh a marker, add it to our new array here
if (refreshIt == true) {
addMarkers.push(newMarkers[i]);
}
}
// then loop thru and see if any units are no longer on the map
for (var j = 0; j < oldMarkers.length; j++) {
removeIt = true;
lastNumber = oldMarkers[j].unitIcon;
for (var i = 0; i < newMarkers.length; i++) {
currNumber = newMarkers[i].unitIcon;
if (lastNumber == currNumber) {
removeIt = false;
break;
}
}
// if we need to refresh a marker, add it to our new array here
if (removeIt == true) {
remMarkers.push(oldMarkers[j]);
}
}
// now loop thru the old markers and remove them
for (var i = 0; i < remMarkers.length; i++) {
var marker = new google.maps.Marker(remMarkers[i]);
marker.setMap(null);
side_bar_html += 'removing ' + remMarkers[i].unitIcon + '<br />';
}
// then loop thru the new markers and add them
for (var i = 0; i < addMarkers.length; i++) {
var marker = new google.maps.Marker(addMarkers[i]);
marker.setMap(map);
side_bar_html += 'adding ' + addMarkers[i].unitIcon + '<br />';
}
// and last save the old markers array into oldMarkers
oldMarkers = [];
for (var i = 0; i < newMarkers.length; i++) {
oldMarkers.push(newMarkers[i]);
}
// put the assembled side_bar_html contents into the side_bar div, then sleep
document.getElementById("side_bar").innerHTML = side_bar_html;
setTimeout('getMarkers()', 5000);
}
For context purposes, here is the code that does clear the old markers, but many (not all) or the markers blink when refreshed, even if they don't in fact move loaction.
function getMarkers() {
// create a new connection to get our xml data
var Connect = new XMLHttpRequest();
// send the get request
Connect.open("GET", xml_file, false);
Connect.setRequestHeader("Content-Type", "text/xml");
Connect.send(null);
// Place the response in an XML document.
var xmlDoc = Connect.responseXML;
// obtain the array of markers and loop through it
var marker_data = xmlDoc.documentElement.getElementsByTagName("marker");
// hide the info window, otherwise it still stays open where the removed marker used to be
infowindow.close();
// now remove the old markers
for (var i = 0; i < oldMarkers.length; i++) {
oldMarkers[i].setMap(null);
}
oldMarkers.length = 0;
// reset the side_bar and clear the arrays
side_bar_html = "";
markerInfo = [];
newMarkers = [];
// obtain the attributes of each marker
for (var i = 0; i < marker_data.length; i++) {
var latData = marker_data[i].getAttribute("lat");
var lngData = marker_data[i].getAttribute("lng");
var minfo = marker_data[i].getAttribute("html");
var name = marker_data[i].getAttribute("label");
var icontype = marker_data[i].getAttribute("icontype");
var unitNum = marker_data[i].getAttribute("unitNum");
zIndexNum = zIndexNum + 1;
// create the new marker data needed
var myLatLng = new google.maps.LatLng(parseFloat(latData), parseFloat(lngData));
var marker = new google.maps.Marker({
position: myLatLng,
icon: gicons[icontype],
title: "",
unitIcon: unitNum,
zIndex: zIndexNum
});
// add a line to the side_bar html
side_bar_html += '<a href="javascript:myclick(' + i + ')">' + name + '<\/a><br />';
// add an event listeners on the marker
addInfoWindow(marker, minfo);
// save the current data for later comparison
markerInfo.push(minfo);
newMarkers.push(marker);
oldMarkers.push(marker);
}
// now add the new markers
for (var i = 0; i < newMarkers.length; i++) {
newMarkers[i].setMap(map);
}
// put the assembled side_bar_html contents into the side_bar div, then sleep
document.getElementById("side_bar").innerHTML = side_bar_html;
setTimeout('getMarkers()', 5000);
}
Finally figured out the solution. The process was reading in new xml data which was compared to the saved xml data, to determine if a marker needed to be moved or displayed in a different color on the map.
When I created a new marker object, I did not set the map: property, because I needed to compare the lat/lon/color of the new object to the old before I determined whether a marker needed to be moved. The problem was the map: property not being set. I save the marker data without the map: property set into the new marker array, then copied the new marker array into old marker array to do the next comparison. I should have copied the old marker object into the new marker array! The old marker object HAD the map: property set, and that allowed the Google mapping code to know which marker I wanted to remove.
Sorry for the stupid mistake, but I'm pretty new to Javascript.
Rich