views:

782

answers:

3

I'm writing a basic recipe organization application and I would like to be able to dynamically add additional items to the list of ingredients using Ajax.

This is what one ingredient <fieldset> looks like:

<fieldset id="ingredient_item_0">
 Ingredient <input id="ingredient_0" type="text" size="20" />
 <div id="ingredient_list_0" style="" class="autocomplete"></div>

 Amount <input id="amount_0" type="text" size="5" />

 Unit <input id="unit_0" type="text" size="20" />
 <div id="unit_list_0" class="autocomplete"></div>

 Notes <input id="notes_0" type="text" size="20" />

 <script type="text/javascript">
  new Ajax.Autocompleter('ingredient_0','ingredient_list_0','ingredients.php', {'method':'get', 'paramName': 't'});
  new Ajax.Autocompleter('unit_0','unit_list_0','units.php', {'method':'get', 'paramName': 't'});
 </script>
</fieldset>

What is the best way (using prototype and scriptaculous) to add additional copies of this <fieldset> with the accompanying JavaScript to the page making sure each one has a unique ID?

+2  A: 

If you already have a nice html template, the easiest thing to do is to use a regexp to convert the template ids to unique ids, inject the template html it into the right place in the doc, and eval the scripts. Prototype's Element.insert function does all the work of injecting the html and evaluating the scripts for you.

So say you have the template in a hidden div called ingredient_template, and you mark all the places you need a unique id with XXX:

<div id="ingredient_template" style="display:none;">
    <fieldset id="ingredient_item_XXX">
        Ingredient <input id="ingredient_XXX" type="text" size="20" />
        <div id="ingredient_list_XXX" style="" class="autocomplete"></div>
        ...
    </fieldset>
</div>

And say you want to add it to an ingredients_list element:

<div id="ingredients_list"></div>
<button type="button" onclick="addIngredient()">Add Ingredient</button>

You could use this javascript function to lookup the template, replace the XXXs with the next ingredient number, and insert it into the ingredients_list:

var ingredientCount = 0;
function addIngredient() {
    var html = $("ingredient_template").innerHTML.replace(/XXX/g, ingredientCount++);
    $("ingredients_list").insert(html);
}
Justin Ludwig
+1  A: 

FYI the best way with prototype to assign a unique ID to an element without an ID is to use:

$('element').identify();

In the context of what you're doing, personally i would make use of Prototype's Template functionality which would convert the code to something like this:

var myTemplate = new Template('<div id="ingredient_template" style="display:none;">'+
                              '<fieldset id="ingredient_item_#{num}">'+
                              'Ingredient <input id="ingredient_#{num}" type="text" size="20" />'+
                              '<div id="ingredient_list_#{num}" style="" class="autocomplete"></div>'+
                              '</fieldset>'+
                              '</div>');


function addIngredient(){
  ingredientCount ++;
  var vals = {num: ingredientCount};
  var htmlstr = myTemplate.evaluate(vals);
  $('ingredients_list').insert(htmlstr)
}

Nothing at all wrong with Justin's code, just to show that theres always many ways to achieve the same thing. In your case there is only one variable to manipulate but because templates allow for multiple replacements they can be a much more elegant solution that multiple regexp replacements.

seengee
A: 

how to do the same using jquery ?

pradeep