views:

270

answers:

4

This seems like it should be easy. I have a html snippet that I wish to locate and modify in place via javascript. But not just the innerHTML; I want to replace the entire element. Example:

  <div class="content">
    <div class="item">
      <img src="images/pic1.jpg" />
      <a class="clicker" onclick="javascript:doSomethingUseful(##);">Do ##!</a>
      <h3>title</h3>
      <p>description</p>
    </div>
  </div>

After page load, I want to grab the <a class="clicker" ...>Now!</a> and replace it with three instances like:

  <div class="content">
    <div class="item">
      <img src="images/pic1.jpg" />
      <a class="clicker" onclick="javascript:doSomethingUseful(1);">Do 1!</a>
      <a class="clicker" onclick="javascript:doSomethingUseful(2);">Do 2!</a>
      <a class="clicker" onclick="javascript:doSomethingUseful(3);">Do 3!</a>
      <h3>title</h3>
      <p>description</p>
    </div>
  </div>

Using prototype.js, I can easily do $$('.clicker') and get an array with the element. I can use .innerHTML and get the 'Do ##!' and change it. But I want, nay, need the entire element to insert it in place. I can go through weird machinations of siblings and parent, and walk back around the nodes to eventually get what I need, and I will do that. It just seems that I am missing something here that would make this easy.

A: 

In IE you can set outerHTML. In FF, you can use this:

http://snipplr.com/view/5460/outerhtml-in-firefox/

AJ
A: 

So the way I would do this is:

  1. Iterate over all the anchors with class clicker that are inside a div with class item which are inside class content
  2. To each one, add a function which will hide that anchor, and then append the 3 anchors you want

So here's what my html chunk looks like:

<div class="content">
  <div class="item">
    <img src="images/pic1.jpg" />
    <a class="clicker" href='#'>Do ##!</a>
    <h3>title</h3>
    <p>description</p>
  </div>
</div>

And I need to include Prototype:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js"&gt;&lt;/script&gt;

And a variable to hold your replacement html, and a dummy function so what we insert works:

var myReplacementHtml = '<a class="clicker" onclick="doSomethingUseful(1);" href="#">Do 1!</a>';
myReplacementHtml += ' <a class="clicker" onclick="doSomethingUseful(2);" href="#">Do 2!</a>';
myReplacementHtml += ' <a class="clicker" onclick="doSomethingUseful(3);" href="#">Do 3!</a>';

function doSomethingUseful(n) {
    alert(n);
    return false;
}

Then here's my code, you may find it useful to get the backstory on how these work: $$, Element.observe, Element.hide, Element.insert, Event.stop:

<script type="text/javascript">
Event.observe(window, 'load', function(){
    $$('.content .item a.clicker').each(function(item){
        item.observe('click', function(evt){
            item.hide();
            Element.insert(item, {after: myReplacementHtml});
        });
        Event.stop(evt);
    });
});
</script>
artlung
A: 

You can add and append elements.

function doSomethingUseful(val) {

  var ele = document.getElementById('myDiv');
  var newdiv = document.createElement('div');
  var divIdName = 'my'+num+'Div';
  newdiv.setAttribute('id',divIdName);
  ni.appendChild(newdiv);
}
Joel Etherton
A: 

If it is not the only HTML generation you want to run in your page, you may consider a javascript templating engine.
There are several advantages, the main one being a clear cut between the HTML view and the JS logic.

There are plenty of these engines available for every taste.

Here is how it would look with prototype.js and the PURE template engine:

$$('div.content')[0].render([1,2,3], {
    'a.clicker':{
        'id <-':{
            '.':'Do #{id}!',
            '@onclick':'javascript:doSomethingUseful(#{id});'
        }
    }
});
Mic
This is what I want! I wasn't sure if I was just missing an obvious solution already part of prototype or scriptaculous. I was building out a poor man's template engine, one method at a time. And I was now getting into the big leagues, without recognizing it. Yes, there is lots more HTML that I'm generating and was unwilling to have any HTML buried inside my javascript. Pure looks like it might be what I want (I have already put it to the test for five other templates in the same project). Thanks....
Tim