PDA

View Full Version : Getting a value from a text file



cmatkin
12-13-2005, 09:00 PM
Hi
I have a text file (values.txt) that contains information in the form of

A1=99
A2=3
A3=255

A454=23

I was wondering if there was a script that I can have on my html page that returns the value of the variable pointed to.

Eg:
A1 = getvalue(A1)

Regards
Craig

jscheuer1
12-14-2005, 06:21 AM
Here is a little demo you might find interesting. There may be more efficient methods and I am not sure how this will react with large data files, hopefully someone with a clue on that will contribute to this thread. Also, since you say you already have this big file with the values in it, you could test it out on that and see how much lag time there is with a large file being parsed for individual values. For the purposes of this demo, I created data.txt and get_data.htm -

data.txt
------------------------

A1=99
A2=3
A3=255

------------------------

get_data.htm
------------------------

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<title>Get Data - Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function getFile(filename)
{ oxmlhttp = null;
try
{ oxmlhttp = new XMLHttpRequest();
oxmlhttp.overrideMimeType("text/xml");
}
catch(e)
{ try
{ oxmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e)
{ return null;
}
}
if(!oxmlhttp) return null;
try
{ oxmlhttp.open("GET",filename,false);
oxmlhttp.send(null);
}
catch(e)
{ return null;
}
return oxmlhttp.responseText;
}

function getData(file, param){
return getFile(file).split(param+'=', 2)[1].split('\n', 1)[0]
}

</script>
</head>
<body>
<input type="button" onclick="alert(getData('data.txt', 'A1'))" value="A1"><br>
<input type="button" onclick="alert(getData('data.txt', 'A2'))" value="A2"><br>
<input type="button" onclick="alert(getData('data.txt', 'A3'))" value="A3"><br>
</body>
</html>

jscheuer1
12-14-2005, 07:30 AM
The function getData(file, param) might be more efficient (I'm thinking about 'on a large data file', again) like so:


function getData(file, param){
var re = new RegExp('\n|.*'+param+'=(.*)$|.*', 'gm')
return getFile(file).replace(re, '$1')
}

Twey
12-14-2005, 02:26 PM
catch(e)
{ return null;
}
}
if(!oxmlhttp) return null;You're repeating yourself :-\
That second "return null" will never be reached; if the object can't be created, you've already returned null in the catch block above.

jscheuer1
12-14-2005, 05:12 PM
That second "return null" will never be reached; if the object can't be created, you've already returned null in the catch block above.

If true, it will harm nothing. I didn't write the function that part of the code belongs to and I do not fully understand it. As a result, I cannot be certain if that bit may or may not be needed. Perhaps it is a fallback for things like a 404 or 403 response.

Twey
12-14-2005, 05:22 PM
Ah, I see. It would be necessary were it in a seperate function.

function getFile(filename) {
oxmlhttp = null;
try {
oxmlhttp = new XMLHttpRequest();
oxmlhttp.overrideMimeType("text/xml");
} catch(e) {
try {
oxmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) { return null; }
}
try {
oxmlhttp.open("GET",filename,false);
oxmlhttp.send(null);
} catch(e) { return null; }
return oxmlhttp.responseText;
}

jscheuer1
12-14-2005, 05:46 PM
I was just testing out the getFile function and, as I believe Mike pointed out in an earlier thread, it doesn't handle a 404 too well. Also I couldn't get it to reach that part in the code that you (Twey) say is redundant. Nevertheless, it is serviceable for the purpose I used it for.

Twey
12-14-2005, 07:22 PM
function getFile(filename) {
oxmlhttp = null;
try {
oxmlhttp = new XMLHttpRequest();
oxmlhttp.overrideMimeType("text/xml");
} catch(e) {
try {
oxmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) { return null; }
}
try {
oxmlhttp.open("GET",filename,false);
if(oxmlhttp.status == 404) {
window.alert("URL doesn't exist! Please contact the webmaster.");
return null;
} else if((oxmlhttp.status != 200 /*Request OK*/) && (oxmlhttp.status != 304 /*Not modified, don't know if this will be needed, but better safe than sorry*/)) {
window.alert("An error " + oxmlhttp.status + " has occurred! Please alert the webmaster.");
return null;
}
oxmlhttp.send(null);
} catch(e) { return null; }
return oxmlhttp.responseText;
}

it doesn't handle a 404 too well.Now she does :)

cmatkin
12-14-2005, 11:35 PM
I would like to thank all of you that help with the code here.
Your code works like a treat.

Thanks again.
Regards
CA

jscheuer1
12-15-2005, 05:58 AM
I decided that I didn't like this whole:

XMLHttpRequest()/ActiveXObject("Msxml2.XMLHTTP")

method because Opera didn't seem to like it. I went ahead and created an entirely different approach, using an iframe. I will test out Twey's neat looking code soon but, I am not too optimistic about its working in Opera. Here is my latest:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<title>Get Data Iframe- Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">

/*Get Data Iframe script- John Davenport Scheuer
as first seen in Dynamic Drive Forums
http://www.dynamicdrive.com/forums
user name: jscheuer1
*/

//set source for data file. Use a plain text file with one name=value pair per line.
var datasrc='data.txt'

///////////////No Need to Edit Below/////////////////
if(document.getElementById)
document.write('<iframe name="source" id="data" src="'+datasrc+'" style="position:absolute;top:-1000px;left:-1000px;visibility:hidden;"></iframe>')

function getData(param){
if(!document.getElementById)
return;
var frameObj=document.getElementById('data');
// Local Error Check (IE and Mozilla):
if (typeof source.location.href!=='string'||source.location.href.indexOf(datasrc)==-1){
alert('file: "'+datasrc+'" Unavailable')
return false;
}
var dataSet=frameObj.contentDocument? frameObj.contentDocument.body : frameObj.Document.body
dataSet=dataSet.innerHTML
var re = new RegExp(param+' *=', 'gm')
// Remote Error Check (IE, Mozilla and Opera) (Opera Local Error Check, as well)
if (!re.test(dataSet)){
alert('file: "'+datasrc+'" Unavailable\nor\nvariable: "'+param+'" Undefined')
return false;
}
re=new RegExp('\r|\n|.*'+param+' *=(.*)$|.*', 'gm')
return dataSet.replace(re,'$1').replace(/\r|<\/[XMPpRrEe]*>/, '');
}

</script>
</head>
<body>
<input type="button" onclick="alert(getData('A1'))" value="A1"><br>
<input type="button" onclick="alert(getData('A2'))" value="A2"><br>
<input type="button" onclick="alert(getData('A3'))" value="A3"><br>
</body>
</html>

Twey
12-15-2005, 06:48 AM
I decided that I didn't like this whole:

XMLHttpRequest()/ActiveXObject("Msxml2.XMLHTTP")

method because Opera didn't seem to like it.
Eh? Opera uses the XMLHttpRequest object like everything else. The AJAX Includes script uses the XMLHttpRequest object, and Opera runs it fine.
"I've been using dynamically created iFrames which push their content out to the parent page by the simple expedient of (pseudocode sequence) iFrame.var=iFrame.element.innerHTML > parent.var=iFrame.var > parent.element.innerHTML=parent.var

This works well in most modern browsers and is testable. However, if the first thing in iFrame.element.innerHTML is a script, this apparently will fail in the latest Safari and Opera. I don't really care about Opera, but the Safari issue is kind of a dealbreaker. The problem is, I can't absolutely guarantee that a script won't be the first element in the innerHTML."

http://www.quirksmode.org/blog/archives/2005/03/ajax_promise_or.htmlI have, however, added another safety net to my code - for earlier versions of IE, I think.

jscheuer1
12-15-2005, 07:08 AM
Opera chokes on:


oxmlhttp.overrideMimeType("text/xml");

at least locally. For which there is the easy fix:


if (!window.opera)
oxmlhttp.overrideMimeType("text/xml");

But, I'd like to see an object test (thinking of other browsers that may not like this either) for this instead and haven't as yet been able to devise one. 'typeof oxmlhttp.overrideMimeType("text/xml")' and 'typeof overrideMimeType("text/xml")' proved useless.

Rob's concerns are interesting but not a concern for my script. However, he could probably overcome the problem by using the dom createElement and insertBefore to place a non script element at the beginning of the iframe's innerHTML from the parent. I avoid all this mess by using a specific kind of data file for the iframe's src.

Another note on these various versions - the try/catch thing really needs to be shielded for older browsers. My latest version avoids this problem by avoiding the use of try/catch. Shielding older browsers is fairly easy though as explained here:

http://www.faqts.com/knowledge_base/view.phtml/aid/10601

jscheuer1
12-15-2005, 07:32 AM
As regards your (Twey's) getFile() function, aside from the (local on XP at least) Opera problem I mentioned, it has a couple of other local problems with both IE and FF on XP at least, neither of those browsers like the tests for:

oxmlhttp.status

This is considered 'unknown' to IE locally and as 0 to FF. I've devised a means around that (relevant section of code only, additions red):


try {
oxmlhttp.open("GET",filename,false);
var flag=0
if (typeof oxmlhttp.status=='unknown'||oxmlhttp.status==0)
flag=1
if(!flag&&oxmlhttp.status == 404) {
window.alert("URL doesn't exist! Please contact the webmaster.");
return null;
} else if(!flag&&(oxmlhttp.status != 200 /*Request OK*/) && (oxmlhttp.status != 304 /*Not modified, don't know if this will be needed, but better safe than sorry*/ )) {
window.alert("An error " + oxmlhttp.status + " has occurred! Please alert the webmaster.");
return null;
}
oxmlhttp.send(null);
}

Not sure how these modifications will play out live though.

Twey
12-15-2005, 01:55 PM
it has a couple of other local problems with both IE and FF on XPHow exactly did you test a page that makes an HTTP request locally?! :confused: It needs an HTTP server to make an HTTP request to, surprisingly. I'm not too astonished that it barfed when asked for the status.
But, I'd like to see an object test (thinking of other browsers that may not like this either) for this instead and haven't as yet been able to devise one.In Javascript, functions are treated as objects. However, you must omit the parentheses at the end to avoid calling them and testing their return value. Behold:
if(oxmlhttp.overrideMimeType) oxmlhttp.overrideMimeType("text/xml");I found one actual error in my function, which was that I was checking the status before calling XMLHttpRequest.send(). So, the final code - extensively tested with FF, IE, Opera, and Konqueror:
function getFile(filename) {
var oxmlhttp = null;
try {
oxmlhttp = new XMLHttpRequest();
if(oxmlhttp.overrideMimeType) oxmlhttp.overrideMimeType("text/xml");
} catch(e) {
try {
oxmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
oxmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) { return false; }
}
}
try {
oxmlhttp.open("GET",filename,false);
oxmlhttp.send(null);
if(oxmlhttp.status == 404) {
window.alert("URL doesn't exist! Please contact the webmaster.");
return false;
} else if((oxmlhttp.status != 200 /*Request OK*/) && (oxmlhttp.status != 304 /*Not modified, don't know if this will be needed, but better safe than sorry*/)) {
window.alert("An error " + oxmlhttp.status + " has occurred! Please alert the webmaster.");
return false;
}
} catch(e) { return "An error has occurred. Error: " + e.toString(); }
return oxmlhttp.responseText;
}There is a live demo here (http://www.crystalinity.net/files/ajax.html). As for shielding, I couldn't find a W3C-compilant method that would work with an acceptable portion of browsers; however, this doesn't really matter in this case, as, from the sound of it, the OP's code is pretty much totally reliant on this bit of code anyway, so will die in older browsers no matter what we do.

jscheuer1
12-15-2005, 08:04 PM
How exactly did you test a page that makes an HTTP request locally?! :confused:

I just ran the darn thing. At least on XP the HTTP request is treated as if it were a server. The only difference being that 'oxmlhttp.status' is always 0 (if executed at the proper point in the code, as you note - thanks for that)


(about typeof tests of function objects) . . . However, you must omit the parentheses at the end to avoid calling them and testing their return value.

Thanks for that gem too, clears up a lot for me.


As for shielding, I couldn't find a W3C-compilant method that would work with an acceptable portion of browsers; however, this doesn't really matter in this case, as, from the sound of it, the OP's code is pretty much totally reliant on this bit of code anyway, so will die in older browsers no matter what we do.

This very issue (shielding), although personally I'm not too concerned with compliance in a case like this, is what makes me very annoyed about the whole try/catch thing. I understand your thinking, I think. I think you are saying that if a browser can't run the code to begin with, who cares if it barfs on it? That is a very tempting stance, it certainly makes life easier and ordinarily I subscribe. However, it is always a nice touch to allow the older and non-supporting browser alike, to degrade gracefully. To that end I've rewritten your function in a way that, in addition to running locally (for testing purposes) also degrades well in non-supporting browsers. It may not work in Konq or Safari, I will rely on you to test that and any other paces you want to put it through (good or at least gracefully degrading in NS4+, FF1.0.7, IE4+, Opera8):


<script type="text/javascript">
function getFile(filename) {

oxmlhttp = null;
if (typeof XMLHttpRequest!=='undefined'&&typeof XMLHttpRequest!=='unknown'){
oxmlhttp = new XMLHttpRequest();
if (oxmlhttp.overrideMimeType)
oxmlhttp.overrideMimeType("text/xml");
}
else if (typeof ActiveXObject!=='undefined'&&typeof ActiveXObject!=='unknown') {
oxmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
else { return null; }
if (typeof document.documentElement=='object'&&(typeof oxmlhttp.open=='function'||typeof oxmlhttp.open=='unknown')){
oxmlhttp.open("GET",filename,false);
oxmlhttp.send(null);
if(oxmlhttp.status == 404) {
window.alert("URL doesn't exist! Please contact the webmaster.");
return false;
} else if(oxmlhttp.status != 0&&(oxmlhttp.status != 200 /*Request OK*/) && (oxmlhttp.status != 304 /*Not modified, don't know if this will be needed, but better safe than sorry*/)) {
window.alert("An error " + oxmlhttp.status + " has occurred! Please alert the webmaster.");
return false;
}
}else { return null; }
return oxmlhttp.responseText;
}

As a result of my testing, I have also upgraded my little function for parsing out the values if this is used for the OP's original purpose:


function getData(file, param){
var test=getFile(file)
if (test==null){
alert('Error Retrieving Data!')
return false;
}
var re=new RegExp('\r|\n|.*'+param+' *=(.*)|.*', 'g')
return test.replace(re,'$1').replace(/\r/, '')
}

Twey
12-15-2005, 08:30 PM
Thanks for that gem too, clears up a lot for me.Yeah, that was a little patronizing. Sorry. Couldn't resist :)

At least on XP the HTTP request is treated as if it were a server.Oo-er... I don't like the sound of that. Isn't that a tad insecure? It's treating every file on the hard drive as if it were publicly available.
I think you are saying that if a browser can't run the code to begin with, who cares if it barfs on it?That's exactly what I'm saying. Obviously I wouldn't do this if there were some safety-net available to help the more geriatric browsers to wheeze on down to the next level of feature-richness, but in this case, it seems a little pointless to me. I don't know about "degrading gracefully," either; the reason I'm not bothered about that is that the script relies on this output heavily, and so it'll die (probably with lots of error messages) in older browsers without XMLHttpRequest anyway, never mind the try/catch.
A couple of points about your code:
1) What's all this typeof stuff for? Is (!XMLHttpRequest) not reliable?
2) Your regex. Does | have a different meaning in Javascript regex than the Perl regex I'm used to? It looks like what you're saying there is:
One of:
\r
\n
anything followed by the parameter followed by = followed by anything
anything
Obviously, having "anything" (.*) as a choice from a set of possibilities is pointless.
3)
if (typeof document.documentElement=='object'&&(typeof oxmlhttp.open=='function'||typeof oxmlhttp.open=='unknown')){Eh? Why test for XMLHttpRequest.open()? We've already established that an object exists; all XMLHttpRequest objects (and Microsoft alternatives) have an open() function. It's quite possibly the most important part of behaviour.

Your code does work in Konqueror; I don't know about Safari.

jscheuer1
12-15-2005, 09:43 PM
I don't like the sound of that. Isn't that a tad insecure? It's treating every file on the hard drive as if it were publicly available.

I don't write the OS. It is convenient for testing purposes.


I don't know about "degrading gracefully," either; the reason I'm not bothered about that is that the script relies on this output heavily, and so it'll die (probably with lots of error messages) in older browsers without XMLHttpRequest anyway

Well, that much is so, however, this (getFile function) could be used anywhere, it would be nice if it were just a drop in bit of code that the person using it could rely upon to be innocuous if they have other means for other browsers. As an example, you could use this to get up to date data for a page but, have a fall back that you update manually every week. Whichever page the user gets will be marked as to how current it is.

[dispensing with quotes here]

1) What's all this typeof stuff for? Is (!XMLHttpRequest) not reliable?

I found that a simple test like that just didn't cover all the possibilities for the browsers I was working with.


2) Your regex. Does | have a different meaning in Javascript regex than the Perl regex I'm used to? It looks like what you're saying there is:
One of:
\r
\n
anything followed by the parameter followed by = followed by anything
anything
Obviously, having "anything" (.*) as a choice from a set of possibilities is pointless.

The | means 'or' as it probably does in most systems. I'm no expert on regex's, this worked in testing. I think it means that if anything other than the pattern I am looking for is also found, it gets swept up along with the pattern and replaced by the single match of the saved buffer, which in this case is the value sought after. The \r and \n are a work around for browsers that won't accept the m flag and the .* takes care of the rest of the content of those lines, I think. We may need Mike for a definitive answer here. I'll play with it some more to see if it can be pared down.


3)
if (typeof document.documentElement=='object'&&(typeof oxmlhttp.open=='function'||typeof oxmlhttp.open=='unknown')){Eh? Why test for XMLHttpRequest.open()? We've already established that an object exists; all XMLHttpRequest objects (and Microsoft alternatives) have an open() function. It's quite possibly the most important part of behaviour.

IE4 liked the ActiveXObject but wouldn't open it.


Your code does work in Konqueror; I don't know about Safari.

Cool. Let's call it our version of the code. I originally found this bit over on Coding Forums. It was in a special FAQ area, dealing with how to access files using javascript and a host of other topics. I think that through both of our efforts it is now much more robust and x-browser friendly.

Twey
12-15-2005, 09:58 PM
IE4 liked the ActiveXObject but wouldn't open it.How peculiar. I wonder why?
Well, that much is so, however, this (getFile function) could be used anywhere, it would be nice if it were just a drop in bit of code that the person using it could rely upon to be innocuous if they have other means for other browsers.Always good to keep modular, I suppose. Once I have a moment, I'll write a decent OO version of this. I'm sure there are plenty out there, but one more can't hurt ;)

Regex stuff: Ah, I think I see. Due to the brackets, it'll match just about anything, but will replace it with "". The $1 will only be used when the portion with the brackets in matches.
Have you tried KRegExpEditor (http://docs.kde.org/stable/en/kdeutils/KRegExpEditor/)? You mentioned you have a copy of Cygwin/KDE floating around somewhere. It's a nice little program; it just lays everything out nicely to make it easy to read.
I think that through both of our efforts it is now much more robust and x-browser friendly.We can hope so :)

Anyone got a copy of Safari for testing?

mwinter
12-17-2005, 05:56 PM
Opera chokes on:



oxmlhttp.overrideMimeType("text/xml");
That's not really a problem though. Not in this instance, anyway: the content type of the data being returned is text/plain, so trying to convince Mozilla otherwise is not a good idea.

I don't think this method should ever really be necessary. With the security model as it is, one may only connect to the originating server, so there should be no trouble ensuring that the server sends the right content type within any data requested. If the method is used, use feature detection as Twey later suggested.


Shielding older browsers [from try/catch] is fairly easy though as explained here:

http://www.faqts.com/knowledge_base/view.phtml/aid/10601That is bad advice. Feature detection renders it unnecessary, leaving the subject of 'shielding' pointless. The exception handling used to create an XMLHttpRequest object is a rare exception, and IE-specific anyway.

For this IE case, the use of JScript's condition compilation is the best approach, as it is the JScript version that determines whether exception handling is possible, and JScript can be updated independently from the browser version. Indeed, this is what the code I posted previously does, and I recommend that as the most reliable way of creating an XMLHttpRequest object. However, the try/catch mechanism may need to be expanded in the near future to cope with MSXML 4.0 that, unlike previous versions, does not allow the version-independent ProgID, 'Msxml2.XMLHTTP', and requires 'Msxml2.XMLHTTP.4.0' instead.


I think you are saying that if a browser can't run the code to begin with, who cares if it barfs on it?I find that, as an end-user, it's a poor reflection on a site to encounter fatal script errors. It either demonstrates a lack of testing, effort or skill. Whether that's the case or not, that's the message it sends, and clearly one that should be avoided.


[...] in addition to running locally (for testing purposes) [...]It would be better to use a testing server for testing code. Installing Apache, whether on Linux or Windows, is very simple and combines the simplicity of not uploading files with the ability to determine how code will behave when served remotely.



Obviously I wouldn't do this [allow uncontrolled failure] if there were some safety-net available to help the more geriatric browsers to wheeze on down to the next level of feature-richness, but in this case, it seems a little pointless to me.There is a safety net: the server. The XMLHttpRequest object is, for the most part, just a way to obtain data to alter the content of a document without regenerating it, so the degraded path is to fall back to the server and allow it to serve another document.

You might think that's a lot of work. Perhaps, but using XMLHttpRequest in this way can produce a nicer, more intuitive interface, so it's worth it in that sense. But, at the same time, it has the least support over a wide range of browsers than most other features, with slightly older versions of current browsers (for example, Opera 7.x) and other older browsers lacking it entirely. Therefore, one cannot aim for 'cross-browser compatibility' unless this is recognised and handled appropriately.


[...] the reason I'm not bothered about that is that the script relies on this output heavily [...]Then that would be a problem with the overall design.


1) What's all this typeof stuff for? Is (!XMLHttpRequest) not reliable?Taking that literally, no. If it is not available, there will be no XMLHttpRequest identifier, resulting in an error. The use of the typeof operator avoids that error. However, the correct way to feature test is look for matching values, not a small, incomplete subset of types that one doesn't want:



if(('function' == typeof XMLHttpRequest) || ('object' == typeof XMLHttpRequest)) {
/* ... */
}

Does | have a different meaning in Javascript regex than the Perl regex I'm used to?No. ECMAScript regular expressions are Perl-compatible, and a pipe (|) denotes alternatives. Your analysis is correct.

A simpler extraction process (or less intensive, at least) might be:



function getValue(key, url) {
var request = getRequestObject(),
pattern = new RegExp('(^|\\n)' + key + '\\s*=([^\\n]*)'),
match;

if(request) {
request.open('GET', url, false);
request.send(null);

if(((200 == request.status) || (304 == request.status))
&& (match = pattern.exec(request.responseText)))
{
return match[2];
}
}
}
which returns a (possibly empty) string on success, or undefined on failure. The line terminator used in the regular expression may need to altered, depending on how the text file is created.



IE4 liked the ActiveXObject but wouldn't open it.The XMLHttpRequest object doesn't depend on the browser version with IE so much as the libraries on the machine (specifically, Microsoft XML Components - MSXML). That said, IE4 keeps complaining about MIME types for some reason whereas later versions do not (I don't know if that's what you're experiencing). However, as IE4 is likely to be excluded when creating the request object anyway, I wouldn't worry that much.

Mike

Twey
12-17-2005, 06:14 PM
[...] the reason I'm not bothered about that is that the script relies on this output heavily [...]
Then that would be a problem with the overall design.Certainly, but that wasn't what the OP asked :)
Installing Apachehttp://httpd.apache.org/ for the searchers.

jscheuer1
12-18-2005, 05:45 AM
When Mike makes sense and his code works and even I can understand it, that's a very good thing. Tested out in almost all the browser versions I had used on my code (I skipped NS7.2). I did add to the RegExp:


new RegExp('(^|\\n)' + key + '\\s*=([^\\n\\r]*)')

To remove hex 0d from the end of the response, just in case it could possibly present any problem, which is highly unlikely.

I was particularly impressed with the advanced, in-script Jscript filter, which appeared to work flawlessly. I added:


if(((200 == request.status) || (304 == request.status) || (0 == request.status))
&& (match = pattern.exec(request.responseText)))

To allow for local testing under XP.

Twey
12-18-2005, 01:07 PM
You might want to add 301 (moved permanently) to the list of allowed status values.

jscheuer1
12-18-2005, 03:29 PM
You might want to add 301 (moved permanently) to the list of allowed status values.

Is there one for 'down the shore for the weekend'? ;) Seriously, would adding 301 help? Wouldn't the file still be unavailable? While we are on this subject, is zero ever a possible request.status with a live page?

Twey
12-18-2005, 04:26 PM
Heh :)
No; if 301 or 304 are given out by the server, it would also include a Location: header that would (I think) cause the request to be redirected. Note that I'm not sure if the XMLHttpRequest object would handle this; it might be necessary to build this into the script yourself. You should read section 10.3 of section 10 of RFC 2616 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html), detailing redirect HTTP status codes.
While we don't have "down the shore for the weekend," one that did give me pause for thought was client error 402: "Payment Required," not implemented yet. Oo-er.

/EDIT: After testing, most browsers (Firefox, Mozilla, Netscape, Konqueror, Opera) do handle the redirect. However, for some (Konqueror and Opera), the redirect response header overrides the final 200 header. IE just died with an error, the toString() representation of which was "[object Error]". Ah, Microsoft, you're so good to us web developers. So yes, I was correct, and 304 and 307 should be added to the allowed status codes.

mwinter
12-18-2005, 05:03 PM
You might want to add 301 (moved permanently) to the list of allowed status values.This suggestion made me rethink the inclusion of 304 (Not Modified).

Assuming I'm right (and I might not be), requests sent through a XMLHttpRequest object are more-or-less done so unchanged. A few headers are added, such as Host, User-Agent, and Accept, but not a lot else.

A browser may cache a server response (response headers permitting), but subsequent requests are unconditional. That is, no If-Modified-Since or If-Match headers are sent. As a result, a 304 (Not Modified) will never be returned. There's no reason why code cannot perform its own caching by keeping old responses and creating its own conditional requests, but it's not going to happen by itself.

As for redirection status codes, expecting one would necessitate the creation of code to follow that redirect. To be robust, that code should also check for redirection loops. Furthermore, if it accepts one 3xx code, why not the others? Of course, the simpler course of action is never have the server return anything other than 200 or 4xx. :)



Is there one for 'down the shore for the weekend'?Sort of. :p There's 410 (Gone), which signals that a resource was purposefully removed with no forwarding address. A server won't send it automatically because filesystems don't record that a file was deleted (as such), just that a region is available for allocation. However, one could add directives for it to send 410 for certain requests, rather than the usual 404 (Not Found).


Seriously, would adding 301 help? Wouldn't the file still be unavailable?Yes. If server-side redirects are not transparently followed, the only response should be a 3xx response and a Location header that indicates where a second response should be directed. I haven't tested this.


While we are on this subject, is zero ever a possible request.status with a live page?No. Never.



No; if 301 or 304 are given out by the server, it would also include a Location: header [...]A 304 response doesn't include a Location header. See 10.3.5 of RFC 2616.

[Edit:]
So yes, I was correct, and 304 and 307 should be added to the allowed status codes.Many of the various redirection response codes (301, 302, 303, and 307) could be included, but as I explained above, 304 is not one of them. Based on what you said with regard to behaviour, I'd again reiterate avoiding the issue entirely by never redirecting resources that might be requested through a XMLHttpRequest object.

Mike

Twey
12-18-2005, 05:59 PM
No; if 301 or 304 are given out by the server, it would also include a Location: header [...]
A 304 response doesn't include a Location header. See 10.3.5 of RFC 2616.I beg your pardon. I did, of course, mean 307 :)

So yes, I was correct, and 304 and 307 should be added to the allowed status codes.Many of the various redirection response codes (301, 302, 303, and 307) could be included, but as I explained above, 304 is not one of them. Based on what you said with regard to behaviour, I'd again reiterate avoiding the issue entirely by never redirecting resources that might be requested through a XMLHttpRequest object.Again, I meant 301. John was earlier talking about making this piece of code easily reimplementable, and if we're working towards this goal, we can't possibly depend upon the server to meet such demands.

cmatkin
12-31-2005, 03:31 AM
I have just been testing the above code from jscheuer1 on the first page.
While all looks good running from a local win pc. All does not work so well when on the server.

On the server I have an other program updating the variables.
When I use the sample code from jscheuer1 it grabs the right value first time.
When the file gets updated, the code only returns the origional value.

I have checked that the data file is been updated by watching it in IE, and have downloaded it via FTP.

If I close the browser down and load up the page to get the values again,I get the new ones until they change again.

Lastly, when the page is loaded in IE, if I remove the server from the network, I still get the values. (not the updated ones.)

I think that IE is caching the data file. Is there any way in forcing no cache of forcing an updated call??

Regards
Craig

mwinter
01-01-2006, 03:04 PM
Is there any way in forcing no cache of forcing an updated call??Stopping all caching is not a good solution. You should ensure that the caching occurs correctly. Don't send an Expires header or Cache-Control: max-age directive that is too far into the future and will inappropriately prevent end-to-end validation of the resource. Ensure that an accurate validator (ETag or Last-Modified header) is generated each time the resource is updated.

Mike

cmatkin
01-02-2006, 07:39 AM
I have done some more tests and it is caching problem.
If I open up a second browser window with the data file and continue refresh it then the get function grabs the new value.

The data file is on an embeded server that has no server side scripting. I can change the format if the data file to any type of text file, I were to change it to a XML file, would this make a script function easier?

Regards
CA

Twey
01-02-2006, 10:33 AM
I can change the format if the data file to any type of text file, I were to change it to a XML file, would this make a script function easier?No. However, you might want to use something like Pragma: No-Cache. No doubt Mike will correct me here. :p

mwinter
01-03-2006, 12:29 AM
I have done some more tests and it is caching problem.That wasn't in any doubt, however it doesn't automatically mean that caching should be disabled. That is an extreme response and rarely appropriate. Unless a resource will change upon every request (or after only a few minutes) then it should be cached.


The data file is on an embeded server that has no server side scripting.A programming language isn't necessary, just an reasonable server.

If you can add headers to a response through the server configuration, then you can add the Cache-Control: no-cache directive. This has a rather misleading name: the resource will be cached, but an end-to-end revalidation will occur with every request (unlike the must-revalidate directive, which will only do so if the resource is stale).

If sending headers is not an option, then a second approach is to generate a unique URL each time the file is requested. As this is driven by a client-side script, you can append the current time (as a number) to the query string, making the browser (and any intervening caches) think that it's a completely different file.



var url = 'http://www.example.com/path/to/resource?time=' + (+new Date());




[Y]ou might want to use something like Pragma: No-Cache.Something like it, but not a Pragma header (http://www.mnot.net/cache_docs/#PRAGMA).

Mike

Twey
01-03-2006, 04:27 PM
No doubt Mike will correct me here. :pKnew it. :p