views:

44

answers:

2

Hi there,

I'm cloning a fieldset and incrementing the attribute names as a new clone is created. However I want the same to happen if I delete I clone so that any cloned fieldset after the deleted will fill in the gaps. As in, if the 2nd clone is deleted, the 3rd with be renamed as the 2nd etc.

I'm trying to change a the classes and IDs that all end with '_3' to end with '_2' (or similarly, changing classes and id's ending in '_2' to end in '_1'). Currently, I'm using jQuery to change each specific class or ID separately, and I just think there has to be a more efficient way of searching for them by filtering out the underscore part of the class or ID name and specifying what to change that to.

My HTML code that is being cloned:

<fieldset class="basic_info">
    <h3 class="title_0">About You </h3>
                <div class="details">
                    <a class="delete driver_0" href="javascript:void(0);">Delete this driver</a>
                    <div class="proposer dob">
                        <label for="dob_0">Date of Birth</label><input type="text" name="dob_0" id="dob_0" /><span>Example: 30/07/1980</span>
                    </div>
                    <div class="proposer gender">
                        <span class="gender">Gender</span>
                        <input type="radio" name="gender_0" id="female_0" value="female" />
                        <label for="female_0">Female</label>
                    </div>
                    <div class="proposer gender">
                        <span class="invisible">&nbsp;</span>
                        <input type="radio" name="gender_0" id="male_0" value="male" />
                        <label for="male_0">Male</label>
                    </div>
                    <div class="proposer license_type">
                        <label for="license_type_0">License Type</label><select name="license_type_0" id="license_type_0"><option id="0">Please Select ...</option><option id="hide">Provisional</option><option id="show1">Full EU</option><option id="show2">Full Irish</option></select>
                    </div>
                    <div class="license_age_0 opt_show1 opt_show2">
                        <div>
                            <span>How long have you had your full license?</span>
                            <input type="radio" name="license_age_0" id="plus_five_yrs_0" value="female" />
                            <label for="plus_five_yrs_0">More than 5 Years</label>
                        </div>
                        <div>
                            <span class="invisible">&nbsp;</span>
                            <input type="radio" name="license_age_0" id="lessthan_five_yrs_0" value="male" />
                            <label for="lessthan_five_yrs_0">Less than 5 Years</label>
                        </div>
                    </div>

                </div>
            </fieldset>

Here is my jquery code for the renaming after a delete occurs:

$('.delete').live('click', function() {
if($(this).hasClass('driver_1')){
    $('<h3 class="title_1">Driver 1</h3>').replaceAll('.title_2');
    $('<h3 class="title_2">Driver 2</h3>').replaceAll('.title_3');
    $(".driver_2").addClass("driver_1").removeClass("driver_2");
    $(".driver_3").addClass("driver_2").removeClass("driver_3");
    $("#dob_2").attr("id","dob_1");
    $("#dob_3").attr("id","dob_2");
    $('label[for="dob_2"]').attr("for","dob_1");
    $('label[for="dob_3"]').attr("for","dob_2");
    $('label[for="female_2"]').attr("for","female_1");
    $('label[for="female_3"]').attr("for","female_2");
    $('label[for="male_2"]').attr("for","male_1");
    $('label[for="male_3"]').attr("for","male_2");
    $('label[for="license_type_2"]').attr("for","license_type_1");
    $('label[for="license_type_3"]').attr("for","license_type_2");
    $('label[for="plus_five_yrs_2"]').attr("for","plus_five_yrs_1");
    $('label[for="plus_five_yrs_3"]').attr("for","plus_five_yrs_2");
    $('label[for="lessthan_five_yrs_2"]').attr("for","lessthan_five_yrs_1");
    $('label[for="lessthan_five_yrs_3"]').attr("for","lessthan_five_yrs_2");
    $("#female_2").attr("id","female_1").attr("name","gender_1");
    $("#female_3").attr("id","female_2").attr("name","gender_2");
    $("#male_2").attr("id","male_1").attr("name","gender_1");
    $("#male_3").attr("id","male_2").attr("name","gender_2");
    $("#gender_2").attr("id","gender_1").attr("name","gender_1");
    $("#gender_3").attr("id","gender_2").attr("name","gender_2");
    $("#licence_type_2").attr("id","licence_type_1");
    $("#licence_type_3").attr("id","licence_type_2");
    $("#plus_five_yrs_2").attr("id","plus_five_yrs_1");
    $("#plus_five_yrs_3").attr("id","plus_five_yrs_2");
    $("#lessthan_five_yrs_2").attr("id","lessthan_five_yrs_1");
    $("#lessthan_five_yrs_3").attr("id","lessthan_five_yrs_2");
}
if($(this).hasClass('driver_2')){
    $('<h3 class="title_2" style="-moz-border-radius-topleft: 7px; -moz-border-radius-topright: 7px;">Driver 2</h3>').replaceAll('.title_3');
    $(".driver_3").addClass("driver_2").removeClass("driver_3");
    $("#dob_3").attr("id","dob_2");
    $('label[for="dob_3"]').attr("for","dob_2");
    $('label[for="female_3"]').attr("for","female_2");
    $('label[for="male_3"]').attr("for","male_2");
    $('label[for="license_type_3"]').attr("for","license_type_2");
    $('label[for="plus_five_yrs_3"]').attr("for","plus_five_yrs_2");
    $('label[for="lessthan_five_yrs_3"]').attr("for","lessthan_five_yrs_2");
    $("#female_3").attr("id","female_2").attr("name","gender_2");
    $("#male_3").attr("id","male_2").attr("name","gender_2");
    $("#gender_3").attr("id","gender_2").attr("name","gender_2");
    $("#licence_type_3").attr("id","licence_type_2").attr("name","licence_type_2");
    $("#plus_five_yrs_3").attr("id","plus_five_yrs_2").attr("name","license_age_2");

$("#lessthan_five_yrs_3").attr("id","lessthan_five_yrs_2").attr("name","license_age_2");
}
$(this).parent().parent('.additional_driver').remove();
$('#clonetrigger').show();
    $('h3').corner("7px tl tr");

    return false;
        });

    }
};

Would anyone be able to help point me in the the right direction. I think the way I'm approaching this is dangerous, as any changes to the html means that those changes will need to be reflected in the above jquery code, leaving a lot of room for errors to occur.

Thanks, ali

Update:

From the suggestion below, I think I'm nearly there, although I don't think I've got my syntax correct (see code comments):

        $('.delete').live('click', function() {
            if($(this).hasClass('driver_1')){
                var id_1 = $("[id$=_1]").attr("id"); // THIS WORKS PERFECTLY
                var class_1 = $("[class$=_1]").attr("class"); // THIS WORKS PERFECTLY
                var for_1 = $("[for$=_1]").attr("for"); // THIS WORKS PERFECTLY
                var name_1 = $("[name$=_2]").attr("name"); // THIS WORKS PERFECTLY
                var id_2 = $("[id$=_2]").attr("id"); // THIS WORKS PERFECTLY
                var class_2 = $("[class$=_2]").attr("class"); // THIS WORKS PERFECTLY
                var for_2 = $("[for$=_2]").attr("for"); // THIS WORKS PERFECTLY
                var name_2 = $("[name$=_2]").attr("name");// THIS WORKS PERFECTLY
                var id_3 = $("[id$=_3]").attr("id"); // THIS WORKS PERFECTLY
                var class_3 = $("[class$=_3]").attr("class"); // THIS WORKS PERFECTLY
                var for_3 = $("[for$=_3").attr("for"); // THIS WORKS PERFECTLY
                var name_3 = $("[name$=_3]").attr("name"); // THIS WORKS PERFECTLY
                $(fieldclone).find(id_2).each(function(){
                    ("id_2").replaceWith.("id_1"); // THIS LINE ISN'T EXECUTING
                });
                $(fieldclone).find(id_3).each(function(){
                    ("id_3").replaceWith.("id_2"); // THIS LINE ISN'T EXECUTING
                });
            }

Thanks, ali

A: 

Jquery has selectors for attributes that let you do startsWith and endswith.

$("id$=_2") would be the selector for "id ends with _2"

Then you could loop over the resulting list and set the new id based on the old one.

Reference: http://api.jquery.com/attribute-ends-with-selector/

UPDATE:

I'm starting to worry that you might be making this more complex than it should be. You may want to back up and think about how you're styling this page, if this is something you're going to have to do whenever new elements are added and removed from this list.

With that said, I was thinking of something more like this:

$("id$=_2").each( updateID );

//This'll only do IDs, but you can extned it to do the other attributes
function updateID()  
{
    //Jquery changes 'this' to point to the current 
    //element in the list when you use the 'each' method
    var old_id = $(this).attr("id");  //get the old id
    var new_id = old_id.replace("_2", "_3"); //update it
    $(this).attr("id", new_id);  //set it
}

But trying to set all of the styles on these elements like this is probably not the right solution to the problem IMHO. There's probably a better way to do this, but without having a complete understanding of the problem, and without seeing your HTML and CSS, it'd be hard to take a stab at what the right answer really is.

Chris Jaynes
Hi Chris - thanks for showing me that. I've updated my original post trying to incorporate what you suggest, but i think I have syntax issue ..
aligreene
@Chris - I think you're right. Basically I have a fieldset that is going to be cloned to a maximum of 3 times. I think I need a) a for loop that counts the number of field sets, b) Add new/Clone function, c) Delete clone function,
aligreene
So I think I need to start from scratch and restructure my javascript file again. I'll keep your suggestion in mind - thanks so much!
aligreene
Also, Christ, I've added a working-not-so-happy-with-this-code version at: jsbin.com/axowa/edit ... and an attempt of what I'm trying to do here: http://jsbin.com/eheve4/5/edit
aligreene
A: 
$(fieldclone).find(id_2).each(function(){
   ("id_2").replaceWith.("id_1"); // THIS LINE ISN'T EXECUTING
});
$(fieldclone).find(id_3).each(function(){
   ("id_3").replaceWith.("id_2"); // THIS LINE ISN'T EXECUTING
});

Two things that come to mind:

  1. the two lines that aren't executing are those that use $(fieldclone) as a selector; is this returning any elements on which to operate?
  2. To use ('id_3') as a selector, it should be wrapped in a jQuery object, and look more like $('id_3')

Also, you say that you've tried to implement @Chris Jaynes' answer, which doesn't seem to be visible in your posted code, $('id_3') is not equivalent to his suggested $('id$=3').

David Thomas
Hi David - 1: fieldclone returns a fieldset with all the elements. These are being cloned from an original fieldset, their attributes being incremented by one for each new clone. If I were to remove one of, say the middle clones, I need the other clones below that to be able to take their place in line. i.e. if I remove the 2nd clone, all attributes for the third needs to become the named like the now deleted second clone. 2: I'll try this out and see if it works
aligreene
Well at the beginning of updated script, I have a few veriables that describe each attribute I want to target that way - var id_1 = $("[id$=_1]").attr("id"); After that, I've been calling that variable.
aligreene
$("[id$=_1]") was targetting the entire element, whereas changing it to: $("[id$=_1]").attr('id') gave me the actual text of the id attribute.
aligreene
@aligreene, fair dos, those were just things that came to mind, and they were too wordy to post as a comment. =)
David Thomas
if you want to see an example, i can email a link to you?
aligreene
@aligreene, you can do, yeah. It might be easier to drop it into [JS Bin](http://jsbin.com/) or [JS Fiddle](http://jsfiddle.net/)? That way you can share it with people in general for editing and experimentation to make it work.
David Thomas
Great - I've added a working-not-so-happy-with-this-code version at: http://jsbin.com/axowa/edit ... and an attempt of what I'm trying to do here: http://jsbin.com/eheve4/3.
aligreene