...

View Full Version : ajax modification



jmrker
09-24-2011, 03:55 AM
I have been successfully using the following "myAjax" function to load text file information from the server.


// ajax.js
// From: http://www.webdeveloper.com/forum/showthread.php?t=245681
// and: http://www.webdeveloper.com/forum/showthread.php?t=245694

// From: http://codingforums.com/showthread.php?t=143412&highlight=file
var myAjax = {
TextInformation : '',
myAjaxIO : function (U, V) { //LA MOD String Version. A tiny ajax library. by, DanDavis
var X = !window.XMLHttpRequest
? new ActiveXObject('Microsoft.XMLHTTP')
: new XMLHttpRequest();
X.open(V ? 'PUT' : 'GET', U, false );
X.setRequestHeader('Content-Type', 'text/html');
X.send(V ? V : '');
return X.responseText;
},
doLoad : function (filename) { this.TextInformation = this.myAjaxIO(filename); },
getTextInfo : function () { // alert(this.TextInformation); // for testing purposes
return this.TextInformation }
}
/* example
function Load_and_Show(filename) {
myAjax.doLoad(filename);
document.getElementById('TArea').value=myAjax.getTextInfo();
}
*/

After I load the text file, I store the text "records" into an array by doing something like this:


var Recs = myAjax.getTextInfo().split('}');

Where the '}' character is my record delimiter. It could just as easily be '\n' or '\r' or the like.
Again, I am not having any problems doing it this way as it suits my current needs.

Now the question(s)
1. Does the call to read the text data from the external file
always read in the entire contents or can I read one line or delimited record
at a time and store it to the array directly without the text storage?

2. If the text is always read completely (my suspicion), can I safely delete
the "TextInformation" after I convert to the array format? Is there any memory
penalty for doing it this way as the text information can be somewhat lengthly
and I don't like the idea of having doubled memory usage when I only need the information in array format anyway?

This is the idea I am considering, but I don't know if there are drawback to this method of if there is a better way to accomplish the task.


// ajax.js
// From: http://www.webdeveloper.com/forum/showthread.php?t=245681
// and: http://www.webdeveloper.com/forum/showthread.php?t=245694

// From: http://codingforums.com/showthread.php?t=143412&highlight=file
var myAjax = {
TextInformation : '',
TextArrayInfo : [],

myAjaxIO : function (U, V) { //LA MOD String Version. A tiny ajax library. by, DanDavis
var X = !window.XMLHttpRequest
? new ActiveXObject('Microsoft.XMLHTTP')
: new XMLHttpRequest();
X.open(V ? 'PUT' : 'GET', U, false );
X.setRequestHeader('Content-Type', 'text/html');
X.send(V ? V : '');
return X.responseText;
},
doLoad : function (filename) { this.TextInformation = this.myAjaxIO(filename); },
getTextInfo : function () { // alert(this.TextInformation); // for testing purposes
return this.TextInformation },

doArrayConvert : function() {
TextArrayInfo = this.TextInformation.split('}'); // assumes '}' is separator character
this.TextInformation = '';
},
getTextArrayLength : function() {
return this.TextArrayInfo.length;
},
getTextArrayAt : function(ptr) {
return this.TextArrayInfo[ptr];
}

}
/* example
function Load_and_Show(filename) {
myAjax.doLoad(filename);
document.getElementById('TArea').value=myAjax.getTextInfo();
}
function Convert_to_Array() {
myAjax.doArrayConvert();
}
var rec = myAjax.getTextArrayAt(0); // gets record element '0'
// or
rec = myAjax.getTextArrayAt(myAjax.getTextArrayLength()-1); // get last element
*/

jmrker
09-26-2011, 05:42 AM
No comments or suggestions for improvements about the code? :confused:

Basically, can ajax methods read one line at a time or does it always read in the entire text?

And, any memory concerns about removing the text after converting text an array of lines?

Old Pedant
09-26-2011, 06:40 AM
It always reads the entire text.

But why do you need your getTextInfo function, at all?

If you are only interested in the array, just get the data *as* an array.

And, by the by, you are *NOT* using AJAX. You are using SJAX. That is, because of your false as the last argument to open( ), you are asking for *synchronous* I/O, so the "A" for "Asynchronous" becomes "S" for "Synchronous."

Not that it's a huge deal.

But under the circumstances, why have all the extra froo-froos that AJAX needs and SJAX doesn't?



function getRecords(url)
{
// 97% of the time, this line will work
var X = window.XMLHttpRequest;
// so then this if test will be false and so this will be quickest code
if ( X == null ) X = new ActiveXObject('Microsoft.XMLHTTP');
X.open('GET', url, false );
X.setRequestHeader('Content-Type', 'text/html'); /* you almost surely don't need this */
X.send();
return X.responseText.split('}');
};

I mean, I'm all in favor of having libraries that do various things, but for this particular case, what you actually want is so simple that I can't see the reason to hang all that other stuff onto it.

And by returning the text already split into records, you *HAVE* caused the responseText to be made eligible for garbage collection. (That is, there won't be any references to it, so it will be unused heap space and will be collected by JS when needed.)

Why complicate things?

blaze4218
09-26-2011, 06:59 AM
You might have gotten a quicker response posting this in the ajax forum, but IDK...
As far as your questions, I think you are going about this the wrong way entirely...

To answer your first question not by design.
AJAX (I believe) was designed to call out to another file that can do some logic processing, preferably on the server, and return the result of the processing.
Now to that end, I think you would be better off using a server-side script to read a file (line by line is easily accomplished) and return the result of that read to your ajax call for parsing (in your case and mine: into an Array).
I use the following JScript ASP. You might optimize it a little... I've been using it for years, since I first learned those concepts, so it might need it...


<%@LANGUAGE="JavaScript"%>
<%
file = new String(Request("file")); // Make sure to include a RegExp to "clean" the input,
db = new String(Request("db")); // something like Request('file').replace(/[^\/\.a-zA-Z0-9]/g,'');

fso = Server.CreateObject("Scripting.FileSystemObject");

function WRITE_FILE_TO_ARRAY(file , db) // db=true if you need to split the file at the "," to make multi tiered array
{
Arr = []
if(!fso.FileExists(file))return;
myFile = fso.OpenTextFile( file, 1);
i=0;
while(!myFile.AtEndOfStream)
{
Arrtmp=myFile.ReadLine();
if(db)Arr[i] = Arrtmp.split(",");
else Arr[i] = Arrtmp;
i++;
}
myfile.Close();
// Arr = Arr.sort(); // I use this alot, but totally optional...
return Arr;
}
%>

You can substitute the loop to prevent the entire file from being read. But you would have to direct your AJAX to the processing file instead, and include the text file as url parameters ?file=data.txt&db=false

jmrker
09-26-2011, 07:23 PM
Thank you 'Old Pedant' and 'blaze4218',

It is because of my ignorance that I ask the questions. :o :eek: :D

I appreciate the feedback! :thumbsup:

jmrker
09-26-2011, 07:43 PM
function getRecords(url)
{
// 97% of the time, this line will work
var X = new window.XMLHttpRequest;
// so then this if test will be false and so this will be quickest code
if ( X == null ) X = new ActiveXObject('Microsoft.XMLHTTP');
X.open('GET', url, false );
X.setRequestHeader('Content-Type', 'text/html'); /* you almost surely don't need this */
X.send();
return X.responseText.split('}');
};


After evaluating your suggested change, I found it would not read the file
until I made the change in RED above for the initial request.

Only bring it to attention in case others would like to use the code ;)

blaze4218
09-26-2011, 08:03 PM
It is because of my ignorance that I ask the questions. :o :eek: :D

No one who seeks answers is ignorant, rather, they are not-yet-knowing.

Old Pedant
09-26-2011, 09:31 PM
My bad. Too much editing on my part.

Yes, of course you need the new. Sorry.

Old Pedant
09-26-2011, 09:33 PM
Blaze: I don't see how you can use that ASP code to service an AJAX request.

As yoo correctly note, the function returns an array.

But you can't return an array to an AJAX request. You can *ONLY* return text.

So you'd have to re-join all those array elements before doing the Response.Write to send the data back to the AJAX requestor. Granted, JS (JavaScript or JScript) will automatically convert an array to a string, for you, but then why create the array in the first place???

blaze4218
09-26-2011, 10:04 PM
oh, that...
Like I said, I have been using that since long before I learned how to implement AJAX (3weeks ago) and it always worked for asp. For AJAX I came up with


function WRITE_FILE_TO_ARRAY()
{
Arr = [];
fso = Server.CreateObject("Scripting.FileSystemObject");
myPath=Server.MapPath("timecards/" + file);
if(!fso.FileExists(myPath))return;
myfile = fso.OpenTextFile( myPath, read);
while(!myfile.AtEndOfStream)
{
Arrtmp=myfile.ReadLine();
Arr.push(Arrtmp.replace(/,/g,'.'));
}
myfile.Close();
Arr = Arr.sort();
Response.Write(Arr);
}


And yes the AJAX will return the entire array into a string, if it didn't I would have just used .join()
And as for the why... I need to break my file reads like so:


//file.txt
red,green,blue
blue,red,green

//New array after retrieved by ajax and parsed from response.Text()
Colors === [[red,green,blue],[blue,red,green]]

The asp page replaces the ',' delimiter with '.' because the Response.Write() will automatically separate each line with ',' making the parsing as simple as


Colors = fromServer.split(',');
for (i in Colors){
Colors[i] = Colors[i].split('.');
}

Sure I could have replaced the ',' with '.' and added the value of each line to a string and sent the string, but JScript was going to re-cast the type anyway...
I guess for me, it is easier to keep track of information that starts as an array and ends as an array if I don't convert it more than I have to...

Also, I did mistakenly post the wrong version of WRITE_FILE_TO_ARRAY(), my bad :o

blaze4218
09-26-2011, 10:16 PM
As yoo correctly note, the function returns an array.

No I didn't, and no it doesn't.
I said that for both of our needs we would want to parse it "into an array"
The function as is doesn't "return" anything per-say, it writes to the document, and the AJAX call on the preceding page will take what is written to that document and pass it along as a string. As your skills far surpass mine, you might have something to say about a write to the document being considered a return, or something else clever like that, IDK... The "how it works" is all way over my head, I just know that it works :cool:

Old Pedant
09-26-2011, 10:17 PM
the Response.Write() will automatically separate each line with ','

Well, no. Actually, that's ECMAScript (JavaScript, JScript) standard.

Response.Write automatically invokes the toString() method on whatever it is asked to write.

And the spec for Array.toString() says to convert the array to a string by doing (what else?) arrayName.join(",")

Unfortunately, there's no way to modify that behavior (well...not true...you could create your own toString method for Array) and it doesn't work well for multidimensional arrays. Demo:


<script>
var a1 = [ "a", "simple", "test"];
document.write(a1);
document.write("<hr>")
var a2 = [ [ "this","shows","an" ], [ "array", "of", "arrays" ] ];
document.write(a2);
</script>

So, yes, your hack of converting the commas in the inner array to periods works. But what would you do if the inner array elements *already* contained commas?? Or if they already contain periods?

One answer is to convert to JSON notation. Another would be to convert to XML.

But whatever works, and if periods work for what you are doing...

blaze4218
09-26-2011, 10:34 PM
Not interested in JSON for the time being. Working on trying to understand XML (it's slow going, I don't work in IT and cant afford school, so I just take it 1 day at a time ;) )
I haven't yet come into any complex strings that include ',' or '.' but I also use other delimiters for even deeper multidimensional arrays '<->' ,'(*)' and the like, anything I can identify at a glance. You make an interesting point though I probably should have left the ',' in the lineRead from the text file and just used myArr.join('.'), either way, there are many parsing considerations when using this archaic method of mine...

Old Pedant
09-26-2011, 11:02 PM
Quite frankly, I wouldn't bother parsing it server-side.

After all, since you will do the work in ECMAScript either way, why not offload the processing time to the user's browser and take the (admittedly very minor) load off of the server.

But that's me.

JSON notation for this is actually pretty simple.



function WRITE_FILE_AS_JSON(file)
{
fso = Server.CreateObject("Scripting.FileSystemObject");
myPath=Server.MapPath("timecards/" + file);
if(!fso.FileExists(myPath))return;
myfile = fso.OpenTextFile( myPath, read);
var lines = myfile.readAll().split("\n");
Response.Write("[\n");
for ( var i = 0; i < lines.length; ++i )
{
Response.Write(' ' + (i >0 ? ',' : '' ) + '["' + lines(i).replace(/\,/g,'","') + '"]\n');
}
Response.Write("]\n");
myfile.Close();
Response.End();
}

You see it?

If your text file contains


red,green,blue
blue,red,green

then that will end up outputting

[
["red","green","blue"]
,["blue","red","green"]
]

And then you can eval() that just fine.

blaze4218
09-26-2011, 11:14 PM
Ok, so minor as it is I love the idea of passing the buck to the client in this case because the client needs to parse it anyway... So I'm going to go over your JSON notation when I have time to inspect it at my leisure. But let me get something straight here, are you actually recommending eval()?!? I thought all you hardcore javascripters thought it was "evil".
Thanks for all your notes on the subject, I've learned alot.

Old Pedant
09-26-2011, 11:29 PM
JSON with AJAX relies on eval() or the equivalent.

You have to be able to convert the text form of an object notation (in this case, an array of arrays, so not the most complex object notation, but still object notation) to internal objects.

eval() is the best candidate.

Also, eval() really isn't all that evil if you aren't using it to create code, create variables, etc. Here, you really are using it for the purpose it was intended: converting a string to the *contents* of a variable.

blaze4218
09-26-2011, 11:47 PM
This is probably bad form to keep this thread alive whilst off topic. If so maybe you could pm me, but I was wondering:
Could you show me that eval() example?
And if it's not too much trouble a brief explanation would do me a world of good. I've just had the hardest time understanding what JSON notation is/does by the online tutorials :(
I'm reluctant to admit that I used eval() when I was starting out, as a last resort to extract the data from an object that I couldn't yet understand and insert it into a line of code... In fact, 99% of the time if I tried everything I knew to extract the data to no avail an eval would get it out by writing the code i expected to work in a string and replacing the object with eval('code to evaluate'+object+'rest of statement;');. by the time I fount out it was 'evil' to do that I hadn't done it in over a year, thankfully...

jmrker
09-27-2011, 12:19 AM
While it may be "off-topic" from my initial question,
I too, have found the discussion informative.

As a side note, the initial code (with minor fix) by 'Old Pedant' worked well for my needs.
I do not have access to a server side solution as 'blaze4218' provided as JSP (?)
so I'm just a satisfied observer at this point who was happy to have generated
a two page disussion on a topic I need to know more about! :)

Old Pedant
09-27-2011, 03:12 AM
Okay, using my post #14 as the server side part of this.

Note again that the code shown there (ASP code, by the by) will return the *TEXT*


[
["red","green","blue"]
,["blue","red","green"]
]

right?

Okay, so now let's use JS AJAX code to see what we would do with that.



var X = null;
function getRecordsViaAjax(url)
{
X = new window.XMLHttpRequest;
if ( X == null ) X = new ActiveXObject('Microsoft.XMLHTTP');
X.open('GET', url, false );
X.onreadystatechange = processAjaxResponse;
X.send();
}
function processAjaxResponse( )
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var preferences = eval( X.responseText );
var txt = "";
for ( var p = 0; p < preferences.length; ++p )
{
txt += "Colors for person #" + p + ":<ul>";
var colors = preferences[p];
for ( var c = 0; c < colors.length; ++c )
{
var color = colors[c];
txt += '<li style="color: ' + color + ';">' + color + '</li>';
}
txt += "</ul>";
}
document.getElementById("ShowPreferences").innerHTML = txt;
}
}
</script>
...
<body>
<input type="button" value="Get Preferences" onclick="getRecordsViaAjax('userColors.txt')"/>
...
<div id="ShowPreferences"></div>
...

If I've done that right, the <div> there will end up showing you something like


Colors for person #0
. red
. green
. blue

Colors for person #1
. blue
. red
. green

Demonstrating that the eval( ) of that response text did, indeed, produce the two dimensional array as I described it.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum