Google Map API V3: Parsing an XML document - javascript

I'm trying to update my Google Maps API web application that I had running fine under version two. Version three seems not only to have broken everything but also has placed the burden of writing one's own versions of a lot of missing API functions that are no longer there.
Soooo, what was a relatively simple adaptation of their "store locator" example under version two has turned into a gigantic headache.
More specifically, my problem is parsing the XML document that my PHP/mySQL code returns after the user has entered some data into the web page and sent it off to the server. I know that the test data that I've been entering works because, 1. it worked flawlessly under V2, and 2., If I hardcode it into the PHP page and then load that page I get the expectant XML document loaded in my browser (Firefox 3.6.13 running on Snow Leopard).
Update: After very careful tracing with Firebug I've discovered that "downloadUrl" function from here is returning the data correctly.
However, it looks like the function "GXml.parse(data)" ( from here) isn't processing the returned XML. I'm pasting that code below:
function GXml(){}
GXml.value=value;
GXml.parse=parse;
function value(node){
if(!node){
return"";
}
var retStr="";
if(node.nodeType==3||node.nodeType==4||node.nodeType==2){
retStr+=node.nodeValue;
}else if(node.nodeType==1||node.nodeType==9||node.nodeType==11){
for(var i=0;i<node.childNodes.length;++i){
retStr+=arguments.callee(node.childNodes[i]);
}
}
return retStr;
}
function parse(textDoc){
try{
if(typeof ActiveXObject!="undefined"&&typeof GetObject!="undefined"){
var b=new ActiveXObject("Microsoft.XMLDOM");
b.loadXML(textDoc);
return b;
}else if(typeof DOMParser!="undefined"){
return(new DOMParser()).parseFromString(textDoc,"text/xml");
}else{
return Wb(textDoc);
}
}
catch(c){
P.incompatible("xmlparse");
}
try{
return Wb(textDoc);
}
catch(c){
P.incompatible("xmlparse");
return document.createElement("div");
}
}
function P(){}
P.write=function(a,b){}
;P.writeRaw=function(a){}
;P.writeXML=function(a){}
;P.writeURL=function(a){}
;P.dump=function(a){}
;P.incompatible=function(){}
;P.clear=function(){}
;
function Wb(a){
return null;
}

I dont bother parsing XML anymore.. much easier to convert it to JSON and stream it directly into objects.. one example:
Is this the fastest way to parse my XML into JavaScript objects using jQuery?
Duncan.

I'm having the same problems, but I found this after a little bit of search. I haven't followed the tutorial through all the way yet, but I thought I'd go ahead and share it.
http://code.google.com/apis/maps/articles/phpsqlsearch_v3.html
Mia

Related

How to call a fetch request and wait for it's answer inside a onBeforeRequest in a web extension

I'm trying to write a web extension that stops the requests from a url list provided locally, fetches the URL's response, analyzes it in a certain way and based on the analysis results, blocks or doesn't block the request.
Is that even possible?
The browser doesn't matter.
If it's possible, could you provide some examples?
I tried doing it with Chrome extensions, but it seems like it's not possible.
I heard it's possible on mozilla though
I think that this is only possible using the old webRequestBlocking API which Chrome is removing as a part of Manifest v3. Fortunately, Firefox is planning to continue supporting blocking web requests even as they transition to manifest v3 (read more here).
In terms of implementation, I would highly recommend referring to the MDN documentation for webRequest, in particular their section on modifying responses and their documentation for the filterResponseData method.
Mozilla have also provided a great example project that demonstrates how to achieve something very close to what I think you want to do.
Below I've modified their background.js code slightly so it is a little closer to what you want to do:
function listener(details) {
if (mySpecialUrls.indexOf(details.url) === -1) {
// Ignore this url, it's not on our list.
return {};
}
let filter = browser.webRequest.filterResponseData(details.requestId);
let decoder = new TextDecoder("utf-8");
let encoder = new TextEncoder();
filter.ondata = event => {
let str = decoder.decode(event.data, {stream: true});
// Just change any instance of Example in the HTTP response
// to WebExtension Example.
str = str.replace(/Example/g, 'WebExtension Example');
filter.write(encoder.encode(str));
filter.disconnect();
}
// This is a BlockingResponse object, you can set parameters here to e.g. cancel the request if you want to.
// See: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/BlockingResponse#type
return {};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
// 'main_frame' means this will only affect requests for the main frame of the browser (e.g. the HTML for a page rather than the images, CSS, etc. that are loaded afterwards). You might want to look into whether you want to expand this.
{urls: ["*://*/*"], types: ["main_frame"]},
["blocking"]
);
Correction:
The above example only works properly if the response data fits in one chunk. If it is larger (and you still want to inspect the entirety of the response data), you would need to put all of the data into a buffer, and then work on it once all data has been received. See the document here for more information: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/StreamFilter/ondata#webextension_examples (the code section titled "This example combines all buffers into a single buffer" would be of most interest to you I think).
In terms of using this API to block responses, data is only returned from this URL if you call filter.write(), so if you don't like the response, you can simply not call it (just call filter.close()) and an empty response will be returned. You can also only return part of the full response body by filter.write()ing only the bits that you want to return.

JavaScript: Writing an output file within a limited & secure scenario

I would like to add a function in my javascript to write to a text file in the local directory where the javascript file is located. This means I'm not looking for some insecure way of accessing the user's file system in any way. All I care about is extracting the user's input into an html page that is accessed by my javascript then using that input as data externally. I just need a simple text file. This user input isn't actually text by the way, but rather a bunch of actions using my online game's components that the underlying javascript turns into a text string (so this particular string is what I want to save, not really even anything direct from the user).
I don't want to write to a user's file system, but rather, the file where the javascript (and html) code is located (a folder hosted on a server). Is there any simple way to get some file I/O going?
I know Javascript has a FileReader, is there any way to get it to do this in reverse? Like a FileWriter. GoogleClosure looks like it has a FileWriter, but it doesn't seem to quite work and I can't find any decent examples of how to get it to do this.
If this requires a different language, is there any way I can just get the relevant snippet and insert this into my Javascript file?
(the folder is hosted on a Linux system if that helps)
ADDENDUM: Elias Van Ootegem's solution below is excellent and I would highly recommend looking into it as it's a great example of client-server interaction and getting your system to provide you the data you're looking to extract. Workers are pretty interesting.
But for those of you looking at this post with that similar question that I initially had about JavaScript I/O, I found one other work-a-round depending on your case. My team's project site made use of a database site, MongoDB, that stored some of the user's interaction data if the user had hit a "Save" button. MongoDB, and other online database systems, provide a "dumping" function/script that you can call from your local machine/server and put that data into an output file (I was able to put the JSON data into a text file). From that output, you can write a parser to extract and format the data you desire from that output since databases like MongoDB can be pretty clear as to what format the text will be in (very structured, organized). I wrote a parser in C (with a few libraries I had written to extend the language) to do what I needed, but the idea is pretty generalizable to other programming/scripting languages.
I did look at leaving cookies as option as well, and made use of a test program to try it out (it works too!). However, one tradeoff for leaving cookies on a user's local system is that those cookies generally are meant to hold small amounts of data (usually things like username, date created, & expiration date of the cookie) and are dependent upon the user's local machine. Further, while you can extract the data in those cookies from JavaScript, you are back to the initial problem: the data still exists on the web, not on an output file on your server's file system. In the case you need to extract data and want some guarantee this data will exist on your machine, use Elias Van Ootegem's solution.
JavaScript code that is running client-side cannot access the server's filesystem at the same time, let alone write a file. People often say that, if JS were to have IO capabilities, that would be rather insecure... just imagine how dangerous that would be.
What you could do, is simply build your string, using a Worker that, on closing, returns the full data-string, which is then sent to the server (AJAX call).
The server-side script (Perl, PHP, .NET, Ruby...) can receive this data, parse it and then write the file to disk as you want it to.
All in all, not very hard, but quite an interesting project anyway. Oh, and when using a worker, seeing as it's an online game and everything, perhaps a setInterval to send (a part of) the data every 5000ms might not be a bad idea, either.
As requested - some basic code snippets.
A simple AJAX-setup function:
function getAjax(url,method, callback)
{
var ret;
method = method || 'POST';
url = url || 'default.php';
callback = callback || success;//assuming you have a default function called "success"
try
{
ret = new XMLHttpRequest();
}
catch (error)
{
try
{
ret= new ActiveXObject('Msxml2.XMLHTTP');
}
catch(error)
{
try
{
ret= new ActiveXObject('Microsoft.XMLHTTP');
}
catch(error)
{
throw new Error('no Ajax support?');
}
}
}
ret.open(method, url, true);
ret.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
ret.setRequestHeader('Content-type', 'application/x-www-form-urlencode');
ret.onreadystatechange = callback;
return ret;
}
var getRequest = getAjax('script.php?some=Get&params=inURL', 'GET');
getRequest.send(null);
var postRequest = getAjax('script.php', 'POST', function()
{//passing anonymous function here, but this could just as well have been a named function reference, obviously...
if (this.readyState === 4 && this.status === 200)
{
console.log('Post request complete, answer was: ' + this.response);
}
});
postRequest.send('foo=bar');//set different headers to pos JSON.stringified data
Here's a good place to read up on whatever you don't get from the code above. This is, pretty much a copy-paste bit of code, but if you find yourself wanting to learn just a bit more, Here's a great place to do just that.
WebWorkers
Now these are pretty new, so using them does mean not being able to support older browsers (you could support them by using the event listeners to send each morsel of data to the server, but a worker allows you to bundle, pre-process and structure the data without blocking the "normal" flow of your script. Workers are often presented as a means to sort-of multi-thread JavaScript code. Here's a good intro to them
Basically, you'll need to add something like this to your script:
var worker = new Worker('preprocess.js');//or whatever you've called the worker
worker.addEventListener('message', function(e)
{
var xhr = getAjax('script.php', 'post');//using default callback
xhr.send('data=' + e.data);
//worker.postMessage(null);//clear state
}, false);
Your worker, then, could start off like so:
var time, txt = '';
//entry point:
onmessage = function(e)
{
if (e.data === null)
{
clearInterval(time);
txt = '';
return;
}
if (txt === '' && !time)
{
time = setInterval(function()
{
postMessage(txt);
}, 5000);//set postMessage to be called every 5 seconds
}
txt += e.data;//add new text to current string...
}
Server-side, things couldn't be easier:
if ($_POST && $_POST['data'])
{
$file = $_SESSION['filename'] ? $_SESSION['filename'] : 'File'.session_id();
$fh = fopen($file, 'a+');
fwrite($fh, $_POST['data']);
fclose($fh);
}
echo 'ok';
Now all of this code is a bit crude, and most if it cannot be used in its current form, but it should be enough to get you started. If you don't know what something is, google it.
But do keep in mind that, when it comes to JS, MDN is easily the best reference out there, and as far as PHP goes, their own site (php.net/{functionName}) is pretty ugly, but does contain a lot of info, too...

WP8 App misbehaving due to StreamWrite in JavaScript

I would like to save the results calculated on html page in a textfile using javascript.
<script type="text/javascript">
window.onload = function () {
var sw : StreamWriter = new StreamWriter("HTML_Results.txt");
sr.Write('xyz");
*** calculations ******
sr.Write (result);
}
</script>
by doing this, my WP8 App is misbehaving and not displaying images as usual. This app is an Image Fader (calculates FPS).
Also tried:
StreamWriter sr;
try {
sr = new StreamWriter("\HTML5\HTMLResults.txt");
sr.Write("xyz");
File.SetAttributes("HTML5\HTMLResults.txt", FileAttributes.Hidden);
} catch(IOException ex) {
console.write ("error writing"); //handling IO
}
The aim is to:
Extract calculated values of several html pages(after getting loaded
one by one) in a single text file.
A Resultant HTML that reads this
text file and displays results in a tabular format.
Is there a better way to this job or the above can be rectified and used? Appreciate help.
Perhaps I've misunderstood your code but it looks like you're trying to write Java within JavaScript scripting tags. You cannot write Java in an HTML document. As far as I know, client-side JavaScript (which given your <script> tags is I guess what you're trying to write) can't perform the kind of file I/O operations you seem to want here.
You need to use Node JS to use JavaScript for something like that and then you're talking server-side. The closest you can get on client-side is using the new localStorage feature in HTML5 (not supported by all browsers).

Javascript XML reading problem

I'm having problems reading an XML local input. The weird thing is that this code works perfectly when the XML is located on a server(This is desktop, by the way, so no SOP problems). I can't figure this out for the life of me, and I've been staring at it, trying different things for a couple of hours.
And another question: does the XML document need a css sheet to be properly read? I would imagine that it doesn't, but I don't know too much about it.
function verify()
{
zipObj = new ActiveXObject("Msxml2.XMLHTTP");
zipObj.open("GET", "KMSY.xml", false);
zipObj.onreadystatechange = function() {
if (zipObj.readyState === 4) {
zipXML = zipObj.responseXML;
read(zipXML);
}
else {
document.getElementById("notice").innerHTML = zipObj.readyState;
}
}
zipObj.send();
}
function read(zipXML)
{
var temp = zipXML.getElementsByTagName("temp_f")[0].childNodes[0].nodeValue;
document.getElementById("notice").innerHTML = temp;
}
Import the XML file to a local server, AJAX obviously needs the XML files to be on web server in order to parse them, or so my humble experience tells me.
You might also want to add the compatibility code for other XML requests into your code.
new XMLHttpRequest() for all browser and IE 8+
new ActiveXObject("Microsoft.XMLHTTP") IE prior to 8

how to receive XML in IE8 with mootools

I'm doing a web where I heavily use AJAX requests to
a XML service. In fact, my web is a front-end with almost
no server whatsoever and uses AJAX to communicate with
the back-end.
Everything was going fine (I developed and tested in Ubuntu 9.04
and Firefox 3.0 as a browser).
One day I decided to see how my web did in IE8...
horror!
Nothing was working as it marvelously did in Firefox.
To be more specific, the Request.HTML's were not working.
As I said, my web relied heavily on that, so nothing worked.
I spent a day trying to get something running but I had no luck..
The only conclusion to which I arrived was that the XML was
incorrectly parsed
(I hope I'm in mistake). Let's get to the code:
var req = new Request.HTML({
url: 'service/Catalog.groovy',
onSuccess: function(responseTree, responseElements) {
var catz = responseElements.filter('category');
catz.each(function(cat){
// cat = $(cat);
var cat_id = cat.get('id');
var subcategory = cat.getElement('subcategory');
alert(cat_id);
alert(cat.get('html'));
alert(subcategory.get('html'));
}
},
onFailure: function(){...}
});
for example, that piece of code.
In firefox, it worked perfectly. It alerted an ID (for example, 7),
then it showed the contents of the category element, for example:
<subcategory id='1'>
<category_id>7</category_id>
<code>ACTIO</code>
<name>Action</name>
</subcategory>
and then it showed the contents of some inner element, in this case:
<category_id>7</category_id>
<code>ACTIO</code>
<name>Action</name>
In IE8, the first alert worked OK (alerted 7)
but the next alert (alert(cat.get('html'));) gave an empty string
and the last threw an Exception... it said something about subcategory
beeing null.
What I concluded with this all is that the elements where parsed
correctly
in Firefox, but in IE8 I only got the tags and the attributes OK,
everything else
was completely wrong (in fact, missing). I mean, the inner content of
all the
elements of the response where gone!
Other fact you could use: this code:
alert(cat.get('tag')); resulted in
Firefox: category
IE8: /category <-----------(?)
hmm what else...
oh yeah... the line you see commented above (cat = $(cat);) was
something
I tried to do to fix this. I read in the mootools Docs that IE needed
to explicitly call
the $ function on elements to get all the Element-magic ... but this
didn't fix anything.
I was so desperate... I even fiddled around with mootools.js code
OK, so...
What I want you, dear mootool-pro's is to help me solve this problem,
for I REALLY need the web to function in IE8, and in fact I chose
mootools to forget about compatibility problems...
ps: if something is not clear, please ASK! I'd appreciate any help :D
I had a similar issue like this sometime ago using jQuery. The problem was that, in IE, the incoming response data needed to be handled by the Microsoft.XMLDOM ActiveX object.
The general steps are to:
Instantiate the ActiveX object.
var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
Pass it the incoming response data and load it.
oXmlDoc.loadXML(sXmlResponseData);
Parse it as needed.
You can check out the full resolution here.

Categories