扩展现有的JQuery插件//变量范围问题

时间:2012-02-28 08:25:11

标签: jquery asp.net-mvc-3 jquery-plugins uploadify extend

首先,我不是FED(我专注于架构和后端代码)所以我的JQuery不是那么好。如果您对如何改进我的代码有任何建议,那将是受欢迎的。

我正在使用uploadify jQuery插件将图片上传到我的网站。我使用ASP.Net MVC3构建了网站,我正在使用表单的复杂类型(使用编辑器模板)。基本上,我的结构允许我输出对象的枚举,每个对象都有一个uploadify控件,允许上传多个文件。如果你需要看,我可以告诉你这段代码,但基本上我已经实现了Phil Haack IEnumerable<HttpPostedFileBase>示例here的更高版本。

我已经在onComplete事件中添加了代码,以输出一些额外的表单字段,允许我为每个上传的文件添加标题,然后由MVC自动神奇地绑定到正确的对象。所有这些都很好,虽然我确信有更好的方法可以做到。

我面临的问题是,因为MVC3在可枚举表单字段的命名约定中需要基于零的顺序索引,以便操作方法接受IEnumerable。当我删除其中一个动态创建的表单控件(使用取消按钮)时,索引序列被破坏。

现在 - 因为有多个uploadify元素,每个元素都需要维护自己的索引。我希望能够扩展uploadify插件的每个实例以具有可跟踪的“fileIndex”属性,并且还使用“reindexFiles()”方法扩展它,该方法将遍历所有剩余的控件并重命名&amp;重新认识他们。

我的方法可能很粗糙(评论欢迎!),但这是我到目前为止的代码:

$(document).ready(function () {
    var uploadedIndex = 0;

    $('div[id$="UploadedImages"]').uploadify({
        script: '/ControlPanel/Media/UploadRelatedImages',
        auto: true,
        fileDesc: 'Image Files (*.jpg;*.jpeg;*.gif;*.png)',
        fileExt: '*.jpg;*.jpeg;*.gif;*.png',
        buttonText: 'Select Images',
        fileDataName: 'files',
        multi: true,
        removeCompleted: false,
        simUploadLimit: 3,
        queueSizeLimit: 100,
        sizeLimit: 1048576, // 1Mb max limit
        onSelectOnce: function (event, data) {
            var uploader = $("#" + event.delegateTarget.id);
            var mediaFormatID = uploader.closest('.mediaFormat').children('input[type="hidden"][name$="MediaFormatID"]').first().val();

            var sd = {
                ASPSESSID: $("#ASPSESSID").val(),
                AUTHID: $("#AUTHID").val(),
                mediaFormatID: mediaFormatID // The first grandparent that ends with MediaFormatID, for the hidden field
            };
            uploader.uploadifySettings('scriptData', sd);
            // TODO : The index needs to be managed per instance
            // Reset index (this will reset each time a group of images are uploaded)
            uploadedIndex = 0;
        },
        onComplete: function (event, ID, fileObj, response, data) {
            // Get the json response
            var json = $.parseJSON(response)[0];

            // Get the newly created queue item
            var queueItem = $("#" + event.delegateTarget.id + ID);

            if (json.HasError) {
                // Text error in response - show it and highlight
                queueItem.children('.percentage').html('<br/>' + json.ErrorMessage);
                queueItem.addClass('uploadifyError');
                return false;
            }

            var textBoxId = event.delegateTarget.id + "_" + uploadedIndex + "__Caption";
            var textBoxName = event.delegateTarget.attributes['name'].value + "[" + uploadedIndex + "].Caption";

            var hiddenId = event.delegateTarget.id + "_" + uploadedIndex + "__MediaFormatImageID";
            var hiddenName = event.delegateTarget.attributes['name'].value + "[" + uploadedIndex + "].MediaFormatImageID";

            // Create container
            var container = $("<div/>").addClass('captionContainer');

            // Create bound hidden field
            $('<input />', {
                'type': 'hidden',
                'id': hiddenId,
                'name': hiddenName,
                'value': json.MediaFormatImageID
            }).appendTo(container);

            // Display the image thumb
            $("<img/>", {
                'src': json.ThumbnailPath
            }).appendTo(container);

            // Create Textbox label
            $('<label />', {
                'for': textBoxId
            }).text('Image Caption')
                .appendTo(container);

            // Create bound text box
            $('<input />', {
                'type': 'text',
                'id': textBoxId,
                'name': textBoxName,
                'maxlength': 100
            }).appendTo(container);

            // Append container to queue item
            container.appendTo(queueItem);

            // Increment index
            uploadedIndex++;
        },
        onCancel: function (event, ID, fileObj, data) {
            // Delete the file from the server
            var uploader = $("#" + event.delegateTarget.id);
            // Get image ID from created hidden input
            var hiddenId = event.delegateTarget.id + "_" + uploadedIndex + "__MediaFormatImageID";
            var hidden = $("#" + hiddenId);

            $.ajax({
                url: '/ControlPanel/Media/DeleteRelatedImage',
                type: "POST",
                context: uploader,
                data: {
                    mediaFormatImageID: hidden.val()
                },
                success: function () {
                    // TODO: Reindex form images

                }
            });
        }
    });
});

onCancel方法不完整且未经测试。正如您所看到的,我正在使用文件名的全局索引,但它不适用于第一个之后的任何uploadify实例,因为索引将从存储的最后一个索引开始,而不是0.我这样做,但是,需要维护每个uploadify元素的索引,因为用户可能会在添加第一批图片后尝试添加更多图片。

我已经查看了jquery的$ .extend()功能,但无法获得任何成功的功能。任何帮助都会一如既往地受到赞赏。

1 个答案:

答案 0 :(得分:1)

  

我面临的问题是,因为MVC3需要从零开始,   可枚举表单的命名约定中的顺序索引   字段,以便动作方法接受IEnumerable。

不一定。在文章的最后看一下this post,更具体地说是非顺序指数

  

嗯,这一切都很棒,但是当你做不到时会发生什么   保证提交的值是否会保持顺序索引?   例如,假设您希望在提交之前允许删除行   通过JavaScript的书籍列表。好消息是通过介绍   一个额外的隐藏输入,你可以允许任意索引。在里面   在下面的示例中,我们提供了带有.Index后缀的隐藏输入   我们需要绑定到列表的每个项目。每个人的名字   隐藏的输入是相同的,所以如前所述,这将给出   模型绑定器绑定时要查找的一组很好的索引   列表。

然后看看Steven Sanderson的excellent blog post,其中提出了Html.BeginCollectionItem扩展方法,可以让你实现这一目标。