views:

583

answers:

7

I'm having some issues with a jQuery AJAX call. My code works fine when I request a page with no javascript in it, but when I have script tags in my code, things start to get weird.

It seems that any script tags referencing external URLs cause the browser to redirect. In firefox, the page goes blank. In safari, the page clears and loads with the content of the AJAX response. In both browsers, the URL doesn't change.

To be specific about my problem; I have a tab control in which I'm trying to embed the walkscore widget. Since it's pretty heavy on the client side, I only want to actually load it once the user clicks the tab it's in. The walkscore AJAX page looks like this:

<script type="text/javascript">
  var ws_address = "1 Market St, San Francisco";
  var ws_width = "500";
</script>
<script type="text/javascript" src="http://www.walkscore.com/tile/show-tile.php?wsid=MY_WSID"&gt;
</script>

Is there some restriction on script tags referencing external sites on AJAX calls? Is there any nice way around this?

-- Edit --

OK I've been playing with it for a bit and have narrowed down the problem a little. Let me try give a better explanation at the same time:

I have two files, index.html and walkscore.html

index.html

function widget() {
  var widget = $('#walkscore');
  $.get('/walkscore.html', function(data) {
    $('#loading').slideUp(function() {
      widget.html(data);
      loaded[name] = true;
      widget.slideDown();
    });
  });
}

walkscore.html - as shown in the top code block

In index.html, I have a link that calls the widget function. Whenever I click this link, the whole page is replaced by the output of the js file. It happens regardless of the domain the js file is from. It only seems to happen with js files that have document.write in them. It behaves in exactly the same way when I use the $.getScript function, even when it's in index.html

-- Edit --

It seems it has everything to do with the document.write. I made a copy of the walkscore javascript and replaced all occurrences of document.write with jquery.html, and it seems to work properly. I'm (obviously) a js noob. Is this the expected behavior of document.write? How come it doesn't do it when I include the script on a page load?

A: 

I would first check the response of that script source, maybe something in that causes the unwanted behavior.

Gidon
The script works - when I view the ajax page directly everything appears as it should.
zaius
+1  A: 

Load script separately from html content, you can use $.getScript( ).

Artem Barger
I tried using getScript in both the script tag on the AJAX page, and on the page doing the AJAX call. Both have the same redirect problem. This makes me think that it is something inherent in requesting an external script.
zaius
To be honest I have read your question once again and I'm not sure I understand it correctly at first time. Please could you please explain in more details what are you trying to do? How? And what is going wrong?
Artem Barger
A: 

Hello zaius,

I have exactly the same problem as you do.

On my page I have Jquery Tabs. I need to load walkscore script in the middle of content of the "Third TAB" only in case if user will click to see this TAB.

Did you find the solution?

Does anyone know how to do it?

Yes! I did - check the last edit I made to the question. I just load the walkscore iframe directly now instead of through their script. It might be fragile because it's not using their official way of doing things, but it works perfectly. Send me an email if you want to see my code - david at kelso dot id dot au
zaius
+1  A: 

It has to do with the document.write in the response.. I was able to fix this in Firefox by doing this:

<script type="text/javascript">

  // save default document.write function so we can set it back
  var write_func_holder = document.write;

  // redefine document.write to output text target div
  document.write = function(text) {
    $('#ad_container').html($('#ad_container').html() + text);
  }
</script>

<script language="JavaScript" type="text/javascript" src="javascriptfile">
</script>

<script type="text/javascript">
  // reset document.write function
 document.write = write_func_holder;
</script>

I'm still getting an issue in Safari where the browser refreshes to a blank page with just the content of the document.write and IE6, IE7 doesn't do anything at all. Firefox works though.

I hope this helps someone figure out what wrong and they in turn can fix the IE6/7 and Safari issues

+1  A: 

It happens because of the document.write call. Here's some info on what's going on:

Writing After A Page Has Been Loaded

If document.write() is invoked after a page has finished loading, the entire static (non-script generated) content of a page will be replaced with the write method's parameter. This scenario is most often played out when the write method is invoked from an event handler - whether the method is in a function called by the event handler or alone inside the handler - because event handlers are triggered after a page has finished loading. This is important to know because static content replacement is not always the desired result. Another common scenario for content overwite has to do with writing content to a new window. In this case, the overwrite of blank page is the goal. (source)

The solution I went with was to eliminate the document.write commands, and replace the content of a div instead. If you're loading an external script, and have no control over it, you can replace the document.write function with your own. It's discussed here:

http://www.webxpertz.net/forums/showthread.php?threadid=11658

Hope that helps someone out there!

zaius
+1  A: 

Replacing document.write is the way to go. This is shameless self promotion, but if you have a non-trivial case, writeCapture.js handles all the edge cases.

noah
Hi, using your script, what would be the nice and simple way to get the following code to work that is returned in an ajax response:<script type="text/javascript" src="http://www.retweet.com/static/retweets.js"></script>The external js file has the dreaded document.write inside it.
jmoz
@jmoz Using the plugin: `$('#wherever you want the content').writeCapture().html(responseHtml);` Or if you just need that script: `$('#whatever').writeCapture().html('<script type="text/javascript" src="http://retweet.com/static/retweets.js"> </script>');`
noah
A: 

I am experiencing the EXACT same behaviour and spent some frustrating hours last night trying to figure out what the problem was and searching for answers to no avail. I'm surprised this is mentioned anywhere in the jquery docs as it seems like a plausible problem not some crazy never-to-be-encountered bug.

Anyway, here's my story in case anyone searches for something related.

I have a jquery enabled page that loads some content into a div using $.ajax(), it all works perfectly. What I needed to do was include one of those twitter retweet buttons that shows a count and enables you to tweet about the content on the page. To do this a simple piece of javascript from them should be included on the page.

<script type="text/javascript" src="http://www.retweet.com/static/retweets.js"&gt;&lt;/script&gt;

So in theory, that script tag should be returned in the ajax call and jquery should execute it and include the result of it, as I specified the data type as html in the $.ajax() call.

The external script on closer inspection does:

if(!url)
{
 var url=window.location.href;
}
if(!size)
var size="big";
var height="75";
var width="54"
if(size=="small")
{
  height="22";
  width="120";
}
if(!username)  
  var username="none";
url=url.replace("?", "*");
var src="http://www.retweet.com/widget/button/"+size+"/"+username+"/"+url;
document.write('<iframe src="'+src+'" height="'+height+'" width="'+width+'" frameborder="0" scrolling="no"></iframe>');

Which obviously bombs out on the document.write.

Tonight i'll try the methods in this post and see if they work, thanks for the info.

jmoz
Hey jmoz. Because the script is small, you can just put the content of it inline in your page, and replace the document.write with a jquery call. Like this: http://pastie.org/897809The only downside of this is that if the script changes, you have to manually update it on your page.
zaius
Yeh, I looked at that but decided re-assigning the document.write function similiar to how John La did it was the best option as the script may change and I also may include other scripts. I've not tested IE or safari though so i'll have to hope for the best..
jmoz