如何更新计数器并用按钮单击替换文本

时间:2013-09-19 12:20:09

标签: javascript django django-forms

我有一个表单,人们可以通过按钮添加更多输入。

javascript函数克隆了“origin-item”,但我似乎无法使函数正确更新#id_nested-TOTAL_FORMS中的值,并且__prefix__不会被计数器替换,它只是复制并添加__prefix__而不是12等等。

任何人都知道这个功能有什么问题?

脚本在此处找到:https://github.com/rotaris/dynamicformdjango/blob/master/todo/templates/edit_items_in_list.html

<input id="id_nested-TOTAL_FORMS" name="nested-TOTAL_FORMS" type="hidden" value="1">    
<input id="id_nested-INITIAL_FORMS" name="nested-INITIAL_FORMS" type="hidden" value="0">
<input id="id_nested-MAX_NUM_FORMS" name="nested-MAX_NUM_FORMS" type="hidden" value="1000">


<div id="origin-item" class="hide item">
    <div id="div_id_nested-__prefix__-name">
        <label for="id_nested-__prefix__-name">Name</label>
    <div class="controls col-lg-10">
        <input id="id_nested-__prefix__-name" name="nested-__prefix__-name" type="text" />
    </div>
</div>


<p><a id="add-new-item" href="#">Add new person</a></p>




<script type="text/javascript">

var prefix = 'nested';
var MAX_FORMS = '1000';
var MIN_FORMS = 1;

/*
 * Perform any enhancements you'd like to a given item here
 * e.g. add datepicker widgets, popovers etc.
 */
function enhanceItem(item) {    
    $('.btn.delete', item).popover({
            offset: 10
    });
}

function enhanceItems() {       
        $('.item').each(function() {
                enhanceItem(this);
        });
}

/*
 * The opposite of enhanceItem()
 */
function diminishItem(item) {   
        $('.btn.delete', item).unbind();
}

function diminishItems() {      
        $('.item').each(function() {
                diminishItem(this);
        });
}


$(document).ready(function() {
        enhanceItems();
});


function getFormCount() {
    return parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
}

function updateFormCount(newValue) {
    $('#id_' + prefix + '-TOTAL_FORMS').val(newValue);
}



/*
 * ====================================================
 * General Notes: 'Form' and 'Item' are used somewhat interchangeably.
 * ====================================================
 */
$.fn.clearForm = function() {
  return this.each(function() {
    var type = this.type, tag = this.tagName.toLowerCase();
    if (tag == 'form')
      return $(':input',this).clearForm();
    if (type == 'text' || type == 'password' || tag == 'textarea')
      this.value = '';
    else if (type == 'checkbox' || type == 'radio')
      this.checked = false;
    else if (tag == 'select')
      this.selectedIndex = -1;
  });
};


/*
 * Given an element, this function replaces a given string/regex
 * with another specified replacement (new_value) within the element
 */
function updateElement(el, target_regex, replacement) {
        var id_regex = target_regex;

        if ($(el).attr("for")) {
                $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
        }
        if (el.id) {
                el.id = el.id.replace(id_regex, replacement);

                // Update the value of the hidden ID
                // This hidden ID represents the ID of the model instance
                var hidden_ID_patt = new RegExp('id_(' + prefix + '-\\d+)-id');
                // Only update if an ID exists (i.e. if a corresponding model instance exists)
                if (hidden_ID_patt.test(el.id)) {
                    $(el).val(new_value + 1);
                }
        }
        if (el.name) {
                el.name = el.name.replace(id_regex, replacement);
        }
}


/*
 * Given an element, this function replaces (the first?) occurence of a number
 * that follows a specific prefix (e.g. 'exampleprefix-n')
 * with another specified number (new_value) within the element
 * where n is a number
 */
function updateElementIndex(el, prefix, new_value) {
        var id_regex = new RegExp('(' + prefix + '-\\d+-)');
        var replacement = prefix + '-' + new_value + '-';

        updateElement(this, id_regex, replacement);
}



function reapplyEnhancements() {
    // Apply some fresh enhancements 
    diminishItems();
    enhanceItems();
}



/*
 * btn = the button (or link or some source object) that instigated this action
 * prefix = the prefix used in the formset (?)
 */
function addItem(btn, prefix) {
        var formCount = getFormCount();

        // You might like/want to do some validation before proceeding in this function
        // i.e. before adding an item
        // In this case, I'm limiting it to max number of forms
        if (formCount < MAX_FORMS) {
            // Clone a item (without event handlers) from the first item
            //var item = $(".item:first").clone(false).get(0);
            // Clone the origin item
            var item = $("#origin-item").clone(false).get(0);
            $(item).removeAttr("id");
            $(item).removeClass("hide");
            // Clear its values
            $(':input', item).clearForm();

            // Insert it after the last item
            $(item).removeAttr('id').hide().insertAfter("form .item:last").slideDown(300);

            $(':input, label', item).each(function() {
                    // Relabel/rename all the relevant bits
                    // '__prefix__' comes from #origin-item
                    // see 'empty_form': https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#empty-form
                    var target_regex = new RegExp('(' + prefix + '-__prefix__-)');
                    var replacement = prefix + '-' + formCount + '-';
                    updateElement(this, target_regex, replacement);
                    // Remove error classes
                    $(this).removeClass("error");
            });

            reapplyEnhancements();

            // Update the total form count (in the management form)
            updateFormCount(formCount + 1);

        }
        else {
            // Feel free to notify the user using some other technique instead of an JS alert
            alert("Sorry, you can only have a maximum of " + MAX_FORMS + " goals.");
        }
}


/*
 * Relabel all items
 */
function relabelItems() {
    var forms = $('.item'); // Get all the forms

    // Update the total number of forms (likely 1 less than before)
    $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);

    var i = 0;
    // Go through the forms and set their indices, names and IDs
    for (formCount = forms.length; i < formCount; i++) {
        $(":input, label", forms.get(i)).each(function() {
            updateElementIndex(this, prefix, i);
        });
    }
}


/*
 * Removes an item from a list of items
 */
function removeItem(btn, prefix) {
        var formCount = getFormCount();

        // Do some validation before proceeding
        // In this case, just make sure there is at least one item
        if (formCount > MIN_FORMS) {
            var item = $(btn).parents('.item');

            // Delete the item
            $("*", item).fadeOut();
            $(item).animate({'backgroundColor':'#fb6c6c'}, 300).slideUp('slow', function() { 
                    $(item).remove(); 
                    relabelItems(); 
            });

            // Apply enhancements
            enhanceItems();
        }
        else {
            // Feel free to notify the user using some other technique instead of an JS alert
            alert("Come on now, you need to have at least a minimum of " + MIN_FORMS + " item(s).");
        }
}


// JavaScript to create a new items/entries
$(document).ready(function() {
        $('#add-new-item').click(function(e) {
                addItem(this, prefix);
                return false;
        });

        $('a.delete').live("click", function(e) {
                removeItem(this, prefix);
                return false;
        });
});

</script>

1 个答案:

答案 0 :(得分:0)

此代码中的错误似乎是由名为prefix的变量用于2个不同的任务引起的。

这里使用它

$('#id_' + prefix + '-TOTAL_FORMS').val(newValue);

我假设前缀被指定为'_ 前缀_ ',但稍后会像这样使用

var target_regex = new RegExp('(' + prefix + '-__prefix__-)');

我假设前缀被赋予'id'

如果您要将变量前缀排序为仅包含一种类型的信息,请使用具有不同名称的2个变量。 我很确定一切都会落实到位。