"Add & Remove Product Attributes Sortable 2"
Bootstrap 3.3.0 Snippet by falvarez1

<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script> <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <!------ Include the above in your HEAD tag ----------> <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script> <div class="container"> <div class="row clearfix"> <div class=""> <h3>Product Attributes</h3> <table class="table table-bordered table-hover table-sortable table-striped" id="tab_logic"> <thead> <tr> <th class="text-center vcenter" style="width: 20px;"></th> <th style="width: 300px;">Label</th> <th>Description</th> <th class="text-center vcenter"></th> </tr> </thead> <tbody class="container-items tableForm"> <tr id='attr0' data-id="0" class="hidden"> <td data-name="sort" style="width: 20px;"> <span class="glyphicon glyphicon glyphicon-sort"></span> </td> <td data-name="label"> <input type="text" class="form-control" name="label" placeholder="Product Attribute Description" maxlength="255"> </td> <td data-name="description"> <textarea class="form-control" rows="5" name="description" placeholder="Product Attribute Description"></textarea> </td> <td data-name="del" style="width: 90px;"> <button type="button" class="btn-remove btn btn-danger btn-xs row-remove"><span class="glyphicon glyphicon-minus"></span></button> </td> </tr> </tbody> </table> </div> <input type="hidden" name="serializedData" id="serializedData" value="default"/> <a id="add_row" class="btn btn-success pull-right"><span class="glyphicon glyphicon-plus"></span> Add Product Attribute</a> </div> <div class="row clearfix"> <textarea id="debugSerialization" rows="4" cols="50"></textarea><br/> <a id="rehydrateBtn" class="btn btn-info"><span class="glyphicon glyphicon-save"></span>Rehydrate</a> </div> </div>
.table-sortable tbody tr td:first-child { cursor: move; } .table-sortable tbody tr td:last-child { text-align: center; }
function exportJSON(formTable, control) { if(!control) { //if control is not defined then used the debugger control = $("#debugSerialization"); } var ret = []; $("tbody tr", formTable).not(".hidden").each(function (index) { var item = {}; var tr = $(this); tr.find(":input").not("button").each(function (j) { var curInput = $(this); item[curInput.data("name")] = curInput.val(); }); ret.push(item); }); var json = JSON.stringify(ret); console.log(json); control.val(json); } function initSortable(formTable) { // Sortable Code var fixHelperModified = function(e, tr) { var $originals = tr.children(); var $helper = tr.clone(); $helper.children().each(function(index) { //alert(index); $(this).width($originals.eq(index).width()); }); return $helper; }; $("tbody", formTable).sortable({ helper: fixHelperModified, handle: "td:first", update: function () { exportJSON(formTable); } }).disableSelection(); $("thead", formTable).disableSelection(); } function hydrateFormTable(formTable, data) { if (data) { try { var parsedJSON = JSON.parse(data); console.log("parsed data is:", parsedJSON); $.each(parsedJSON, function(k, v) { //display the key and value pair //console.log(k, v); addRow(formTable, v); }); } catch(e) { console.log("error parsing the JSON",e); } } } function clearFormTable(formTable){ //remove any current rows $("tbody tr", formTable).not(".hidden").remove(); } function addRow(formTable, formData) { // Dynamic Rows Code // Get max row id and set new id var newid = 0; $.each($("tr", formTable), function () { if (parseInt($(this).data("id")) > newid) { newid = parseInt($(this).data("id")); } }); newid++; var tr = $("<tr></tr>", { id: "attr" + newid, "data-id": newid }); // loop through each td and create new elements with name of newid $.each($("tbody tr:nth(0) td", formTable), function () { var cur_td = $(this); var children = cur_td.children(); // add new td and element if it has a nane if ($(this).data("name") !== undefined) { var td = $("<td></td>", { "data-name": $(cur_td).data("name") }); var c = $(cur_td).find($(children[0]).prop('tagName')).clone().val(""); c.attr("name", $(cur_td).data("name") + '[' + newid + ']'); c.data("name", $(cur_td).data("name")); c.appendTo($(td)); td.appendTo($(tr)); } else { var td = $("<td></td>", { 'text': $('tr', formTable).length }).appendTo($(tr)); } }); //hydrate fields if there's data if(formData !== undefined) { $.each(formData, function(i, j) { console.log("adding input data:", i, j, $("[data-label]", tr)); $("td[data-name="+ i +"] :input", tr).val(j); }); } $(tr).appendTo(formTable); $(tr).find("td button.row-remove").on("click", function () { $(this).closest("tr").remove(); exportJSON(formTable); }); } function initTable(formTable){ initSortable(formTable); addRow(formTable); // $(":input", formTable).change(function () { // console.log("there is an update"); // exportJSON(formTable, $("#debugSerialization")); // }); //setup auto-hydrating formTable.on('input', function () { exportJSON(formTable); }); } $(document).ready(function() { var formTable = $("#tab_logic"); var hiddenSerializedData = $("#serializedData"); $("#rehydrateBtn").click(function(){ clearFormTable(formTable); //add rows with JSON data hydrateFormTable(formTable, debugDataField.val()); }); initTable(formTable); $("#add_row").on("click", function() { addRow(formTable); }); });

Related: See More


Questions / Comments: