2012-02-28 61 views
1

首先,我不是FED(我专注于架构和后端代码),所以我的JQuery不如它可能。如果您对如何改进我的代码有任何建议,这将是受欢迎的。扩展现有的JQuery插件//变量作用域问题

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

我已经将代码添加到onComplete事件,以输出一些额外的表单域,允许我为每个上传的文件添加标题,随后通过MVC自动将它们自动魔术地绑定到正确的对象。所有这些工作都很好,但我确信有更好的方法来做到这一点。

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

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

我的方法可能是原油(评论欢迎!),但这里是我的代码,我到目前为止有:

$(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

我所面临的问题是,因为MVC3需要从零开始, 顺序中的命名约定一个IEnumerable指数为可枚举形式 字段以便由操作方法被接受。

不一定。看看this post和更具体的非循序索引对本文的结尾:

嗯,这是所有伟大和所有,但会发生什么,当你不能 保证提交的值会保持顺序索引? 例如,假设您希望允许在通过JavaScript提交 书籍列表之前删除行。好消息是,通过引入 一个额外的隐藏输入,您可以允许任意索引。在下面的 示例中,我们提供了一个隐藏输入。索引后缀 我们需要绑定到列表的每个项目。这些 隐藏输入中每一个的名称都是相同的,因此如前所述,这会给 模型绑定器一个很好的索引集合,以便在将 绑定到列表时寻找。

然后看看在史蒂芬·桑德森的excellent blog post中,他提出了Html.BeginCollectionItem扩展方法,可以让你做到这一点。

+0

一位同事指出我对你引用的Haacked帖子 - 我试图输出一个隐藏的元素并使用uploadify生成的ID,但它不会绑定。我必须使用ICollection,还是我可以继续使用IEnumerable? – Spikeh 2012-02-28 08:44:37

+0

@Spikeh,它可以正常工作,具有'IEnumerable ',如Steven Sanderson的博客文章所示。如果不绑定,则可能没有发送正确的POST值。 – 2012-02-28 08:46:15

+0

好的,我会检查出来的。谢谢:) – Spikeh 2012-02-28 08:50:49