2

I have a form (commonStuff) cloned this way (and an html page, designed in jquery mobile, where the form appears multiple times, cloned):

var commonClone = commonStuff.cloneNode(true);

and this function

function renameNodes(node) {
    var i;
    if (node.length) {
        for (i = 0; i < node.length; i += 1) {
            renameNodes(node[i]);
        }
    } else {
        // rename any form-related elements
        if (typeof node.form !== 'undefined') {
           node.id = currentPrefix + '_' + node.id;
           node.name = currentPrefix + '_' + node.name;

        // This assumes that form elements do not have child form elements!
        } else if (node.children) {
            renameNodes(node.children);
        }
    }
}

which add a prefix 'form1_', 'form_2' (the currentPrefix) to id and names of any element in the form and is applied to commonClone (and so recursively to his sons).

renameNodes(commonClone);

It work perfectly in case of text inputs like

    <div data-role="fieldcontain" class="ui-field-contain ui-body ui-br">
        <label for="foo" class="ui-input-text">Age:</label>
        <input type="text" name="age" id="age" value="" class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset">
    </div>

But it fails on radio buttons like

  <div data-role="fieldcontain">
        <fieldset data-role="controlgroup" data-type="horizontal">
            <legend>Address:</legend>
                <input type="radio" name="radio-address" id="radio-address_female" value="1" checked="checked" />
                <label for="radio-address_female">Address 1</label>

                <input type="radio" name="radio-address" id="radio-address_male" value="2"  />
                <label for="radio-address_male">Address 2</label>
        </fieldset>
    </div>

applying the renaming to the outer divs like 'fieldcontain' and 'controlgroup'. It works if i remove those two divs but the graphical effect is unacceptable...

As far as now, i got the problem is in the last 'else if' block for it doesn't care of siblings, but I don't really know how to fix this. Any idea?

EDIT: This code comes from this answer How to create a tabbed html form with a common div

Community
  • 1
  • 1
Sasha Grievus
  • 2,566
  • 5
  • 31
  • 58

2 Answers2

2

As you use jQuery mobile, jQuery will be available. I hope this code will point you in the right direction:

var i = 0;
$("form").each(function() {
  $(this).find("input, select").each(function() {
    $(this).attr("id", "form" + i + "_" + $(this).attr("id"));
    $(this).attr("name", "form" + i + "_" + $(this).attr("name"));
  });
  $(this).find("label").each(function() {
    $(this).attr("for", "form" + i + "_" + $(this).attr("for"));
  });
  i++;
});

EDIT:

I understand your current approach fails with labels. Consider to wrap your input elements inside the label tag. In that case, you won't need the for-attribute. This is in accordance with the docs: http://api.jquerymobile.com/checkboxradio/ Consider this:

HTML

<form>
  <div data-role="fieldcontain">
    <fieldset data-role="controlgroup" data-type="horizontal">
      <legend>Address:</legend>
      <label><input type="radio" name="radio-address" id="radio-address_female" value="1" checked="checked" />Address 1</label>
      <label><input type="radio" name="radio-address" id="radio-address_male" value="2" />Address 2</label>
    </fieldset>
  </div>
  <div data-role="fieldcontain" class="ui-field-contain ui-body ui-br">
    <label><input type="text" name="age" id="age" value="" class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset">Age:</label>
  </div>
</form>

jQuery

var i = 0, currentPrefix = "form";
$("form").each(function() {
  $(this).find("input, select").each(function() {
    $(this).attr("id", currentPrefix + i + "_" + $(this).attr("id"));
    $(this).attr("name", currentPrefix + i + "_" + $(this).attr("name"));
  });
  i++;
});

Workin fiddle: https://jsfiddle.net/EliteSystemer/8sx6rnwo/

Gjermund Dahl
  • 1,410
  • 17
  • 25
  • Thank you. This is similar to the code I finally produced (see my own answer). I was hoping to find a more elegant way to manage this thing using the recursive method on the cloned nodes instead of directly renaming the elements in the page :) – Sasha Grievus Jun 14 '16 at 08:33
  • Wow, this is interesting! Thank you! – Sasha Grievus Jun 14 '16 at 10:53
  • @SashaGrievus If my answer was of help, please accept is as the formal answer. – Gjermund Dahl Jun 15 '16 at 12:48
  • It was of help, indeed, however i did not accept it for it is not really the answer to the question I asked. This works for a normal form, but i am not sure it would work with a 'cloned' one. Also it is not complete for it doesn't rename 'all' the possible elements of a form (textarea, button and so on). I'm not accepting mine for the same reasons. I'm too meticolous, I know, sorry. ^^' – Sasha Grievus Jun 15 '16 at 19:58
1

Truly, this is far from elegant, but a solution, anyway. In any node, this searches manually for input and labels, changing id, names and 'for' attribute in case of labels.

 function renameNodes(node) {
    var i;
    if (node.length) {
        for (i = 0; i < node.length; i += 1) {
           renameNodes(node[i]);
        }
    } else {
        // rename any form-related elements
        if (typeof node.form !== 'undefined') {
           node.id = currentPrefix + '_' + node.id;
           node.name = currentPrefix + '_' + node.name;

           var inputs = node.getElementsByTagName('input');
           for (i = 0; i < inputs.length; ++i) {
                inputs[i].id = currentPrefix + '_' + inputs[i].id;
                inputs[i].name = currentPrefix + '_' + inputs[i].name;
           }
           var labels = node.getElementsByTagName('label');
           for (i = 0; i < labels.length; ++i) {
                labels[i].setAttribute('for', currentPrefix + '_' + labels[i].getAttribute("for"));
           }
        } else if (node.children) {
           renameNodes(node.children);
        }
    }
 }
Sasha Grievus
  • 2,566
  • 5
  • 31
  • 58