luisquike
4/1/2018 - 5:41 PM

Form Clone JS

Clone HTML form with Js

<!doctype html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang=""> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8" lang=""> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9" lang=""> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang=""> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="apple-touch-icon" href="apple-touch-icon.png">

        <link rel="stylesheet" href="css/bootstrap.min.css">
        <style>
            body {
                padding-top: 50px;
                padding-bottom: 20px;
            }
        </style>
        <link rel="stylesheet" href="css/bootstrap-theme.min.css">
        <link rel="stylesheet" href="css/main.css">

        <script src="js/vendor/modernizr-2.8.3-respond-1.4.2.min.js"></script>
    </head>
    <body>
        <!--[if lt IE 8]>
            <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Project name</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <form class="navbar-form navbar-right" role="form">
            <div class="form-group">
              <input type="text" placeholder="Email" class="form-control">
            </div>
            <div class="form-group">
              <input type="password" placeholder="Password" class="form-control">
            </div>
            <button type="submit" class="btn btn-success">Sign in</button>
          </form>
        </div><!--/.navbar-collapse -->
      </div>
    </nav>

    <!-- Main jumbotron for a primary marketing message or call to action -->
    <div class="jumbotron">
      <div class="container">
        <h4>Clones</h4>
        <p>Code for clone inputs and forms.</p>
      </div>
    </div>

    <div class="container">

      <div class="duplicate" data-type="forms" data-maxOccurs="2" data-reference="special_instruction">
        <div class="row">
          <div class="col-sm-6">
            <div class="duplicate" data-type="inputs" data-maxOccurs="3" data-reference="text">
              <div class="fg-line">
                <input type="text" id="receipt_aditional_complement_special_instruction_text" name="receipt[aditional_complement][special_instruction][0][text][0]" class="form-control", placeholder="text">
              </div>
            </div>
          </div>
          <div class="col-sm-6">
            <div class="duplicate" data-type="inputs" data-maxOccurs="5" data-reference="test">
              <div class="fg-line">
                <input type="text" name="receipt[aditional_complement][special_instruction][0][test][0]" class="form-control", placeholder="test">
              </div>
            </div>
          </div>
        </div>
      </div>

      <hr>

      <div class="duplicate" data-type="forms" data-maxOccurs="2" data-reference="special_instruction">
        <div class="row">
          <div class="col-sm-6">
            <div class="duplicate" data-type="inputs" data-maxOccurs="3" data-reference="text">
              <div class="fg-line">
                <input type="text" id="receipt_aditional_complement_special_instruction_text" name="receipt[aditional_complement][special_instruction][0][text][0]" class="form-control", placeholder="text">
              </div>
            </div>
          </div>
          <div class="col-sm-6">
            <div class="duplicate" data-type="inputs" data-maxOccurs="5" data-reference="test">
              <div class="fg-line">
                <input type="text" name="receipt[aditional_complement][special_instruction][0][test][0]" class="form-control", placeholder="test">
              </div>
            </div>
          </div>
        </div>
      </div>

      <hr>

      <footer>
        <p>&copy; Company 2015</p>
      </footer>
    </div> <!-- /container -->        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
        <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.2.min.js"><\/script>')</script>
        <script src="js/vendor/bootstrap.min.js"></script>
        <script src="js/main.js"></script>
    </body>
</html>
// element: contenido del nodo a clonar
// type: tipo de nodo "referencia para return structure"
// index: identificador unico para cada nodo
function addClone(element, type, index) {
  let button = ''
  switch(type) {
    case "inputs":
      button = '<span class="input-group-addon last"><button class="btn btn-default btn-add-clone" type="button"><i class="zmdi zmdi-plus"></i></button></span>'
      return  '<div class="clonned input-group" data-index="'+index+'">'+element+button+'</div>'
      break
    case "forms":
      button = '<span class="pull-right"><button class="btn btn-primary btn-add-clone" type="button"><i class="zmdi zmdi-plus"></i></button></span>'
      return  '<div class="clonned row" data-index="'+index+'">'+element+button+'</div>'
      break
  }
}

let clones = {"inputs": [], "forms": []}

$.each(clones, function(type, _) {
  let duplicates = $(".duplicate[data-type='"+type+"']")
  for (var i = 0; i < duplicates.length; i++) {
    duplicates[i].dataset.id = i
    clones[type][i] = duplicates[i].innerHTML
    duplicates[i].innerHTML = addClone(clones[type][i], type, 0)

    //delete this lines
    let input = $(duplicates[i]).find(".clonned:last-child input")
    $(input).attr("placeholder", $(input).attr("name"))

  }
})

$(document).on('click', '.btn-add-clone', function(event){
  event.preventDefault()

  //Verificar estructura para determinar si se puede remover un padre SPAN
  let clonned = $(this).parent().parent()
  let duplicate = clonned.parent()
  let maxOccurs = duplicate.attr("data-maxOccurs")
  let clonnes = duplicate.find("> .clonned")

  if(maxOccurs != undefined){
    if (parseInt(clonnes.length) >= parseInt(maxOccurs)) {
      return false
    }
  }

  let id = duplicate.attr("data-id")
  let type = duplicate.attr("data-type")
  let reference = duplicate.attr("data-reference")
  let index = parseInt(clonned.attr("data-index")) + 1

  let regex = new RegExp("\\["+reference+"\\]\\[(\\d+)\\]", "g")
  let clone = clones[type][id].replace(regex, "["+reference+"]["+index+"]")

  let clone_parents = duplicate.parents(".clonned")
  if (clone_parents.length > 0) {
    for (var i = clone_parents.length - 1; i >= 0; i--) {
      let parent_index = clone_parents[i].dataset.index
      reference = clone_parents[i].parentElement.dataset.reference
      regex = new RegExp("\\["+reference+"\\]\\[(\\d+)\\]", "g")
      clone = clone.replace(regex, "["+reference+"]["+parent_index+"]")
    }
  }

  $(duplicate).append(addClone(clone, type, index))

  //delete this lines
  let inputs = $(duplicate).find(".clonned input")
  for (var i = inputs.length - 1; i >= 0; i--) {
    $(inputs[i]).attr("placeholder", $(inputs[i]).attr("name"))
  }

  $(this).removeClass('btn-add-clone').addClass('btn-remove-clone')
         .html('<i class="zmdi zmdi-minus"></i>')

}).on('click', '.btn-remove-clone', function(event){
  $(this).parent().parent().remove()
  event.preventDefault()
  return false
});