views:

38

answers:

1

We have a tool that allows people to add code to a dynamic page.

A bit of code (a widget) needs to be injected into the DOM, not hard coded into the html. I use jquery to do it. The problem is that it ends up redirecting the page...

I need to solve this.

Here is an example. Create a page with the following:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"&gt;&lt;/script&gt; 
<script type="text/javascript">
    $(function(){

       $('#doInsertW').click(function(){
          var wCode = $('#inputWidget').val();
          $('#putWidget').html(wCode);
       });

    });
</script>
<input id="inputWidget" /><button id="doInsertW" type="button">Insert</button>
<div id="putWidget"></div>

Then paste this into the input and you'll see what I mean:

<script src="http://widgets.twimg.com/j/2/widget.js"&gt;&lt;/script&gt;
<script>
new TWTR.Widget({
  version: 2,
  type: 'profile',
  rpp: 4,
  interval: 6000,
  width: 250,
  height: 300,
  theme: {
    shell: {
      background: '#333333',
      color: '#ffffff'
    },
    tweets: {
      background: '#000000',
      color: '#ffffff',
      links: '#4aed05'
    }
  },
  features: {
    scrollbar: false,
    loop: false,
    live: false,
    hashtags: true,
    timestamp: true,
    avatars: false,
    behavior: 'all'
  }
}).render().setUser('twitter').start();
</script>
+1  A: 

The problem is that the widget.js script uses document.write to place the HTML for the widget on the page. If document.write is called while the page is still loading, it works fine. However, calling document.write after the page has finished loading will rewrite the entire page.

Here is a quick and dirty hack that will force it to work (tested in FireFox):

$(function(){
    document.write = function(c) { $('#putWidget').append(c) };

   $('#doInsertW').click(function(){
      var wCode = $('#inputWidget').val();
      $('#putWidget').html(wCode);
   });

});

Notice, I'm simply overriding the document.write function after the page is done loading.

Mark Eirich
I see. That is pretty lame. I am not aware of any solutions to this because it is their code. Know of any work-arounds?
Dale
@Dale: I just edited my answer to include a workaround.
Mark Eirich
Wait, I think it would work to do something like this. Create a page where you pass the code to it in the url. Then grab the code from the url and execute it on that page. Passing the code to the page via ajax should return the code after it has rendered, after document.write wrote to the other page.
Dale
@Mark Eirish: That seems to work. Since I never use document.write myself I think this should be safe enough. Thanks
Dale
Do you have control over what code is dynamically inserted, or does the user paste it from somewhere off-site? I ask because in Chrome I have to click Insert twice to get it to work. I think the solution may involve modifying the pasted code.
Mark Eirich
Yeah, we allow them to insert code/widgets from anywhere they may find it on the web. Flash and html widgets work great of course. Its just some of these js ones where they use document.write.
Dale
Thanks for accepting my solution. However, you should probably do some thorough cross-browser testing. Chrome and Safari require me to click Insert twice before it will work. My suspicion is that it's running `new TWTR.Widget` before it finishes loading widget.js. This may have to do with the way that jQuery executes scripts, or it may be a problem with Webkit. Unfortunately, I don't have the time to fully diagnose (not for free, anyway!).
Mark Eirich
Also, keep in mind that what you are doing is very unsafe, in that it invites cross-domain scripting hacks. A third-party site could **very easily** offer widget code that steals your user's cookies.
Mark Eirich
I see, thanks. I will look into all your suggestions. Especially the cookie problem.
Dale