// Chops off the last string segment designated by delimiter. If no delimiter is found then the original string is // returned instead. The following attributes are accepted: // string = Required. The string to chop. // delimiter = Optional. The delimiter used to chop up the string. Defaults to '_'. function stringChop(string, delimiter) { var chopped = string; if (delimiter == undefined) {delimiter = '_';} var endIndex = string.lastIndexOf(delimiter); if (endIndex > 1) {chopped = string.slice(0, endIndex);} return chopped; }; // Increments a number embedded in the text by one. If no number is found then the original text is returned. function incrementText(text) { if (text != undefined) { var match = text.match(/\d+/); if (match != null) { var number = new Number(match); var newNumber = number + 1; text = text.replace(number, newNumber); } } return text; }; // Increments the input field ID number by one so ActiveRecord can save new record attributes. function incrementInputId(input) { id = $(input).attr("id"); id = incrementText(id); $(input).attr("id", id); }; // Increments the input field name number by one so ActiveRecord can save new record attributes. function incrementInputName(input) { name = $(input).attr("name"); name = incrementText(name); $(input).attr("name", name); }; // Generates a hidden input field based off original input field data that instructs ActiveRecord to delete // a record based on the ID of the input field. function generateDestroyInput(input) { $(input).attr("id", stringChop($(input).attr("id")) + "__delete"); $(input).attr("name", stringChop($(input).attr("name"), '[') + "[_delete]"); $(input).attr("type", "hidden"); $(input).attr("value", 1); return input; }; // Animates the removal of a DOM element. function animateDestroy(id) { $(id).animate({backgroundColor: "#FF0000", border: "0.2em solid #FF0000"}, 500); $(id).fadeOut(500); }; // UJS $(document).ready(function(){ // Nested New $("a.new-nested").click(function(){ var parentId = '#' + stringChop($(this).attr("id")); var child = $(parentId).children(":last").clone(true); var childId = child.attr("id"); child.attr("id", incrementText(childId)); $(parentId).append(child); // Ensure the cloned input fields are unique. $('#' + child.attr("id") + " :input").each(function(){ incrementInputId(this); incrementInputName(this); $(this).attr("value", ''); return this; }); // Ensure the cloned destroy link is unique. destroyLink = $("a.destroy-nested:last"); destroyLink.attr("id", incrementText(destroyLink.attr("id"))); // Ensure that the default event does not fire. return false; }); // Nested Destroy $("a.destroy-nested").click(function(){ try { var id = $(this).attr("id"); var parentId = stringChop(id); if (parentId != id) { parentId = '#' + parentId; $(parentId).prepend(generateDestroyInput($(parentId + " input:first").clone())); animateDestroy(parentId); } else { throw "Invalid ID"; } } catch (e) { alert("Error: " + e + ". Check that parent ID is defined and/or the link ID includes parent ID as part of the link ID."); } // Ensure that the default event does not fire. return false; }); // Destroy $("a.destroy").click(function(){ var result = confirm("Are you sure you want to delete this?"); if (result) { try { var id = $(this).attr("id"); var parentId = stringChop(id); if (parentId != id) { animateDestroy('#' + parentId); } else { throw "Invalid ID"; } // Finally, call the destroy action. $.post($(this).attr("href"), "_method=delete"); } catch (e) { alert("Error: " + e + ". Check that parent ID is defined and/or the link ID includes parent ID as part of the link ID."); } } // Ensure that the default event does not fire. return false; }); });