XMLHttpRequest() won't open in Safari

T

TLaufenberg

I'm new to Javascript programming and I've run into a bit of a snag
with making an XMLHttpRequest in the Safari browser. Actually, the
request doesn't work in Firefox either but only when I use a Mac
computer. IE and FireFox on a Windows based system works just fine. The
problem I am having is that the XMLHttpRequest doesn't open the site
that I've programmed into it. When I check the readyState it only
returns 0 and never goes through the others. My code is as follows:

var xml_request = null;

//Mozilla
if(window.XMLHttpRequest)
{
xml_request = new XMLHttpRequest();

/* try {

netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
} catch (e) {
}*/

xml_request.open("GET", feed, false);
xml_request.onreadystatechange = alert(xml_request.readyState);
xml_request.setRequestHeader("Cache-Control", "no-cache");
xml_request.send(null);
}
else if(window.ActiveXObject)
{
//IE
xml_request = new ActiveXObject("Microsoft.XMLHTTP");

xml_request.open("GET", feed, false);
xml_request.setRequestHeader("Cache-Control", "no-cache");
xml_request.send(null);
}

Again, it works on Windows based computer just fine. But the Firefox
and Safari browser on a Mac are where I'm having trouble.
 
T

Touffy

var xml_request = null;

//Mozilla
if(window.XMLHttpRequest)
{
xml_request = new XMLHttpRequest();

xml_request.open("GET", feed, false);
xml_request.onreadystatechange = alert(xml_request.readyState);

This should cause an error in every browser.
An event handler must be a function. The alert method returns nothing.

instead you should write:
xml_request.onreadystatechange = function(){alert(xml_request.readyState)}
xml_request.setRequestHeader("Cache-Control", "no-cache");
xml_request.send(null);
}
Again, it works on Windows based computer just fine. But the Firefox
and Safari browser on a Mac are where I'm having trouble.

Try it with the working handler function. If it still doesn't work,
tell us what errors you get in both browsers.
 
M

Michael Winter

And IE7, and Opera, and others.

Why include the request here? Obtain a reference to a XMLHttpRequest
object and, if successful, execute the request.

var httpRequest = getRequestObject();

if (httpRequest) {
/* ... */
}
This should cause an error in every browser.

Not necessarily: it depends how they handle access of the readyState
property before the send method is called.

There shouldn't really be a problem in this regard. The property is
described as returning 0 (uninitialised) before the open method is
called, and 1 (loading) before the send method is called.
An event handler must be a function.

The null and undefined values should be understood as "no listener".
The alert method returns nothing.

It returns undefined, which isn't quite the same thing. :)

Mike


If the types (object versus function) of both XMLHttpRequest and
createRequest are consistent, the conditions below can be simplified. I
know that for the former, it is most likely to be 'function', but MSIE
has a habit of using 'object' for some host functions which might extend
to IE 7. I've never used IceBrowser (which uses createRequest).

function getRequestObject() {
var object = null;

if ((typeof XMLHttpRequest == 'object')
|| (typeof XMLHttpRequest == 'function'))
object = new XMLHttpRequest();
else if ((typeof createRequest == 'object')
|| (typeof createRequest == 'function'))
object = createRequest();
else if (typeof ActiveXObject == 'function') {
/*@cc_on @*/
/*@if(@_jscript_version >= 5)
try {
object = new ActiveXObject('Msxml2.XMLHTTP');
} catch(e) {
try {
object = new ActiveXObject('Microsoft.XMLHTTP');
} catch(e) {
object = null;
}
}
@end @*/
}
return object;
}

An alternate implementation could perform the tests once, replacing the
getRequestObject function with a simpler one.
 
T

Touffy

Michael Winter said:
The null and undefined values should be understood as "no listener".

no error indeed, of course. Time for me to have some sleep I guess.
It returns undefined, which isn't quite the same thing. :)

Yeah, true. undefined is not nothing, it is both the type and the value
of everything that is no more, has yet to be, or will never be. And
some things that are. It is the past, the future, and all the
never-to-happen potential of JavaScript. So I guess it's bigger than
the sum of all the defined JavaScript values ever referenced. That's
quite something :)
 
T

TLaufenberg

This should cause an error in every browser.
An event handler must be a function. The alert method returns nothing.

instead you should write:
xml_request.onreadystatechange = function(){alert(xml_request.readyState)}

Touffy,

The suggestion you made is exactly what I have only I didn't create a
function out of it. No need in writing more code then I really have to.
Like I said, my entire program works just fine on a Windows based
system. I even got the program to work in FireFox on the Mac, I forgot
to set the browser property 'signed.applets.codebase_principal_support'
to true but I still can't get it to work in Safari. I'm beginning to
think that Safari has a similar safeguard in place that I need to turn
off somehow in order to allow my program to make a call to the method
XMLHttpRequest.open b/c I believe that the method is being blocked
instead of having an error in my code.
 
T

Touffy

(e-mail address removed) said:
Touffy,

The suggestion you made is exactly what I have only I didn't create a
function out of it. No need in writing more code then I really have to.

When you write:

it does this:

alert(xml_request.readyState);
xml_request_onreadystatechange=undefined;

is it what you want to do ?
I'm beginning to
think that Safari has a similar safeguard in place that I need to turn
off somehow in order to allow my program to make a call to the method
XMLHttpRequest.open b/c I believe that the method is being blocked
instead of having an error in my code

I'm currently writing a web application using XMLHttpRequest. I'm
working on a Mac, so I'm testing on Safari and FF (IE's turn will come
when everything works in "real" browsers ;-) ), and both browsers
behave exactly as I expected. The code I wrote doesn't have any tricky
privilege setting. I tested first with synchronous, then asynchronous
mode, made the code progressively more complex, and it always worked on
the first try (it was my first time using XMLHttpRequest).
XMLHttpRequest is supposed to need special privileges only if your page
requests a URL outside its domain (so if you don't write "http://" in
the request URL, it should work fine without any privilege setting).

So, when you test on Safari, does it throw an error (you have Safari's
JavaScript console open, don't you ?) ? Does FF throw an error when you
test without being privileged ?
If they do, please tell us. I can't see it in the code you posted, it
may be somewhere else.
 
T

TLaufenberg

Touffy,

I should have said it before but I'm trying to perform a cross-domain
XMLHttpRequest and that is where my problem is rooted. We're trying to
add RSS feeds to our Intranet.

xml_request.onreadystatechange = alert(xml_request.readyState);

The above line of code works exactly the same way as your line of code:

xml_request.onreadystatechange =
function(){alert(xml_request.readyState)}

All that is being done here is when the readyState changes, to do
something. So if it is set equal to a function or just the alert itself
doesn't matter. I've realized what the problem is and it is that
cross-domain XMLHttpRequests are not friendly. I found the workaround
for FireFox which is:

try {
user_pref("signed.applets.codebase_principal_support", true);

netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
} catch (e) {
}

But I'm unsure of how to do this in Safari and Internet Explorer. If I
wasn't dealing with the cross-domain non of this would be an issue. If
you have any suggestions on how I get Safari and Internet Explorer to
allow this request that would be greatly appreciated.


-Tracy
 
T

TLaufenberg

Slight correction in the previous posting:

try {

netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
user_pref("signed.applets.codebase_principal_support", true);
} catch (e) {
}

I had the netscape and user_pref backwards in the other posting.


-Tracy
 
T

Touffy

(e-mail address removed) said:
I should have said it before but I'm trying to perform a cross-domain
XMLHttpRequest and that is where my problem is rooted. We're trying to
add RSS feeds to our Intranet.

I see. Maybe you could use some server-side script (or just a cron'd
wget or curl or some Windows equivalent) to retrieve the RSS file and
store it locally so it can be accessed by your script without the
privilege problem ?
xml_request.onreadystatechange = alert(xml_request.readyState);

The above line of code works exactly the same way as your line of code:

xml_request.onreadystatechange =
function(){alert(xml_request.readyState)}

did you test that ?
All that is being done here is when the readyState changes, to do
something.

actually your line ensures nothing is done by setting the
onreadystatechange handler to undefined, which is the return value of
the window.alert method.
I've realized what the problem is and it is that
cross-domain XMLHttpRequests are not friendly. I found the workaround
for FireFox which is:

try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
} catch (e) {
}

But I'm unsure of how to do this in Safari and Internet Explorer.

I know IE uses a different scheme for script privileges. There are
several sets of websites defined in IE's preferences, with privileges
associated with each set.

On Safari, I'm not sure this can even be done.
If I wasn't dealing with the cross-domain non of this would be an issue.

(see the top of this post)
 
T

TLaufenberg

Touffy,

This line of code doesn't return nothing or even undefined. It returns
a value of 0 and never progresses beyond that. I don't know how to do
it but I have to set Safari to allow access to data sources across
domains.
 
T

Touffy

I don't know how to do it but I have to set Safari to allow access to
data sources across domains.

My guess is that it just can't be done with XMLHttpRequest. I've never
heard of the WebKit having any user/script interface to change the
privileges.

Dashboard widgets use the WebKit too, and they can retrieve data from
wherever they want with XMLHttpRequest or some other method, but the
WebKit has a "browser" mode and a "widget" mode and it seems that, when
an instance of the WebKit is running, it can't switch between the two.
If it could, surely Safari's Debug menu would allow it since it allows
you to make the window transparent to test widgets (and Apple
explicitly says that widgets in Safari can never have access to their
full functionnality (though they may refer to other, non-Web features
only)).

Now, that doesn't mean you can't do it, only that you can't do it this
way. I'd love to say there are several workarounds, but it appears only
what I suggested (mirror the RSS feed on your own domain's server) will
work.
Using another method for retrieving the feed would have been a logical
alternative, but:
loading it into a <script> would not work for pure XML,
loading it into a frame would not let you access its contents,
SOAP isn't really compatible with pure RSS either and it's not yet
fully implemented.

It's not so bad, even though it's not what you were trying to do.
Setting up your server to download the RSS regularly should not be a
problem, and that lets you remove all that browser-specific privilege
code from the client-side script.
 
L

Laurent Bugnion

Hi,

Touffy,


This line of code doesn't return nothing or even undefined. It returns
a value of 0 and never progresses beyond that. I don't know how to do
it but I have to set Safari to allow access to data sources across
domains.

That's not possible, in any environment. This is a current limitation of
XmlHttpRequest. The only current way to make cross-domains calls is to
use a server as proxy, i.e. call your own server using XmlHttpRequest,
and use the server to call the other server, for example in ASP.NET
using HttpWebRequest. That's annoying.

Check this for more info:
http://json.org/JSONRequest.html

HTH,
Laurent
 
T

TLaufenberg

That's not possible, in any environment. This is a current limitation of
XmlHttpRequest. The only current way to make cross-domains calls is to
use a server as proxy, i.e. call your own server using XmlHttpRequest,
and use the server to call the other server, for example in ASP.NET
using HttpWebRequest. That's annoying.


Well that isn't very nice of Safari. All the other browsers I've done
this through allow me to set preferences which allow cross-domain
XMLHttpRequest without having to worry about proxies. I guess they
don't want people to tweak Safari to each own's purpose.
 
L

Laurent Bugnion

Hi,

Well that isn't very nice of Safari. All the other browsers I've done
this through allow me to set preferences which allow cross-domain
XMLHttpRequest without having to worry about proxies. I guess they
don't want people to tweak Safari to each own's purpose.

I don't know if Safari allows this. I was talking about default settings.

Greetings,
Laurent
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top