views:

79

answers:

5

I have an html as follows:

<fieldset id="question1"> <legend class='legend'>...</legend>

...

<input type="text" name="label_no1" id="label_no1" autocomplete="off">

</fieldset>

On the java script, I'm cloning the fieldset, yet I want to access its element to change ids, and some of the text.

I tried this and it did not work:

$('#question1").siblings(".legend").html="any text"; \\ I also tried children

I also want to be able to access all the inputs inside the fieldset, so to change their ids. Any help?

A: 

The jQuery html method has a syntax as follows:

var result = $(selector).html(); // result now contains the html of the first matched element

@(selector).html('some html markup'); // the html of all matched elements are set to 'some html markup'
Tomas Lycken
A: 

I think this could help : http://stackoverflow.com/questions/416081/jquery-clone-duplicate-ids

Kaaviar
+2  A: 

You can change the id of the question using the attr method:

var q2 = $('#question1').clone();
q2.attr('id', 'question2');

To edit specific children in your new element, you want the find method:

var legend = q2.find('.legend').html('....');
Dexter
Thanks Dexter, your method worked. Now if I want to change an id of an input that is inside the fieldset, do you know how to do it? Note that I have many inputs inside it.
zeina
@Dexter: a little typo: `$('#question1").clone();` should be `$('#question1').clone();` you closed a single quoted string with a double quote
jigfox
Thanks @Jens - fixed
Dexter
+1  A: 

To clone the fieldset and add it to the same parent:

var fieldset = $("#question1");    // Get the fieldset
var clone = fieldset.clone();      // Clone it
clone.attr("id", "question2");     // Set its ID to "question2"
clone.appendTo(fieldset.parent()); // Add to the parent

Note we're changing the ID before adding it to the tree, since you can't have two elements with the same ID.

To do things with the elements within it, you can use .children() or .find() on your clone variable with a selector to select the children/descendants you want (once you've added the clone to the parent). For instance, to clean up the ids on the inputs:

clone.find('input').each(function() {
    if (this.id) {
        // It has an ID, which means the original had an ID, which
        // means your DOM tree is temporarily invalid; fix the ID
        this.id = /* ...derive a new, unique ID here... */;
    }
});

Note that within the each callback, this is not a jQuery instance, it's the raw element. (Hence my setting this.id directly.) If you wanted to get a jQuery instance for the element, you'd do var $this = $(this); and then use $this.attr("id", ...) instead. But there's no particular need unless you're doing something other than changing the ID.


Answering your question about renumbering IDs, you'll need to be sure you update whatever's using those IDs as well as the actual IDs on the input elements.

But in terms of doing the update on the input elements, you could do it by reading the number and incrementing it until you get one that isn't used:

clone.find('input').each(function() {
    var id;
    if (this.id) {
        id = this.id;
        do {
            id = id.replace(/[0-9]+$/g, function(num) {
                return String(Number(num) + 1);
            });
        }
        while ($("#" + id).length > 0);
        this.id = id;
    }
});

...which will give you "input_radio2" if the original ID was "input_radio1", but I think I'd probably use a different naming convention instead. For instance, you could prefix your various input IDs with the ID of the question:

<fieldset id='question1'>
    ...
    <input id=-'question1:input_radio1' />
</fieldset>

...and then just replace 'question1' with 'question2' in the cloned IDs. (Colons [:] are perfectly valid in IDs.)

If you can avoid having IDs on all of your inputs, though, that would be the way to go. For instance, unless your markup prevents it for a different reason, you can associate an input with its label via containment rather than using for:

<label>First name: <input type='text' ... /></label>

Lots of options. :-)

T.J. Crowder
but how can i give each input a unique id, if I did not give it a class?On my original fieldset I have something like this:`<input type="radio" value="radio" id="input_type_radio1" name="input_type1">``<input type="radio" value="checkbox" id="input_type_check1" name="input_type1">`and more inputs. What I really want to do is to change the id to input_type_check2 and so on.. So how can I know which input I'm dealing with if I did not give it a class?
zeina
I did this`var id=this.id;``id=id.replace(old_counter,new_counter); \* replacing 2 with 1 and so on*/``this.id = id; `Is this the best way to do it? And will there be a problem when I clone more than 10 fieldset?thanks in advance.
zeina
@zeina: LOL, I was just answering your earlier question when you posted that. My solution is similar, but guards against conflicts. But I think it might be worth taking a step back and refactoring the form a bit (he says, not knowing anything about the requirements!). :-)
T.J. Crowder
Thanks very much. One last question, if I want to remove cloning, how I can do that? Just set it to hidden? I doubt that there is a better way.
zeina
@zeina: You mean, if you want to remove the clone at some point? Just call `$("#idOfClone").remove()`: http://api.jquery.com/remove/
T.J. Crowder
Thanks, you taught me much new stuff on jquery today. thanks for ur time.
zeina
+2  A: 

Try this:

$clone = $('#question1').clone();

$clone.attr('id','some_new_id');
// you don't need to search by class or id you can search for tags also,
// so you can get rid of some redundancy and write <legend>…</legend>
// instead of <legen class="legend">…</legend>
// siblings won't work with your example, because legend is a child not a sibling
// html= won't work either html on a jQuery object is a method not an attribute
$clone.find('legend').html("New text for the Legend");
jigfox
@zeina: If the contents of the fieldset have `id` s, though, you *will* need to clean those up unless they're being replaced because they're inside the `legend` elements. The HTML snippet in your question has them outside the `legend` elements (and they have `id` s), so this won't quite do it though it'll get you close.
T.J. Crowder