From b512afe5c9a7c50fae2937b60ba62ffb51d21c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 11 Feb 2014 10:38:41 -0800 Subject: [PATCH] BUGFIX: make sure we bind the uploader only once --- .../discourse/views/composer/composer_view.js | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/discourse/views/composer/composer_view.js b/app/assets/javascripts/discourse/views/composer/composer_view.js index 47c5c5f5666..8b0fba501b4 100644 --- a/app/assets/javascripts/discourse/views/composer/composer_view.js +++ b/app/assets/javascripts/discourse/views/composer/composer_view.js @@ -97,9 +97,9 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { // One second from now, check to see if the last key was hit when // we recorded it. If it was, the user paused typing. - var composerView = this; + var self = this; Em.run.later(function() { - if (lastKeyUp !== composerView.get('lastKeyUp')) return; + if (lastKeyUp !== self.get('lastKeyUp')) return; // Search for similar topics if the user pauses typing controller.findSimilarTopics(); @@ -174,7 +174,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { initEditor: function() { // not quite right, need a callback to pass in, meaning this gets called once, // but if you start replying to another topic it will get the avatars wrong - var $wmdInput, editor, composerView = this; + var $wmdInput, editor, self = this; this.wmdInput = $wmdInput = $('#wmd-input'); if ($wmdInput.length === 0 || $wmdInput.data('init') === true) return; @@ -188,7 +188,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { dataSource: function(term) { return Discourse.UserSearch.search({ term: term, - topicId: composerView.get('controller.controllers.topic.model.id'), + topicId: self.get('controller.controllers.topic.model.id'), include_groups: true }); }, @@ -204,7 +204,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { this.editor = editor = Discourse.Markdown.createEditor({ lookupAvatarByPostNumber: function(postNumber) { - var posts = composerView.get('controller.controllers.topic.postStream.posts'); + var posts = self.get('controller.controllers.topic.postStream.posts'); if (posts) { var quotedPost = posts.findProperty("post_number", postNumber); if (quotedPost) { @@ -214,15 +214,14 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { } }); - var $uploadTarget = $('#reply-control'); this.editor.hooks.insertImageDialog = function(callback) { callback(null); - composerView.get('controller').send('showUploadSelector', composerView); + self.get('controller').send('showUploadSelector', self); return true; }; this.editor.hooks.onPreviewRefresh = function() { - return composerView.afterRender(); + return self.afterRender(); }; this.editor.run(); @@ -230,7 +229,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { this.loadingChanged(); var saveDraft = Discourse.debounce((function() { - return composerView.get('controller').saveDraft(); + return self.get('controller').saveDraft(); }), 2000); $wmdInput.keyup(function() { @@ -243,7 +242,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { $replyTitle.keyup(function() { saveDraft(); // removes the red background once the requirements are met - if (composerView.get('model.missingTitleCharacters') <= 0) { + if (self.get('model.missingTitleCharacters') <= 0) { $replyTitle.removeClass("requirements-not-met"); } return true; @@ -252,12 +251,17 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { // when the title field loses the focus... $replyTitle.blur(function(){ // ...and the requirements are not met (ie. the minimum number of characters) - if (composerView.get('model.missingTitleCharacters') > 0) { + if (self.get('model.missingTitleCharacters') > 0) { // then, "redify" the background $replyTitle.toggleClass("requirements-not-met", true); } }); + // in case it's still bound somehow + this._unbindUploadTarget(); + + var $uploadTarget = $('#reply-control'); + $uploadTarget.fileupload({ url: Discourse.getURL('/uploads'), dataType: 'json' @@ -267,14 +271,14 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { $uploadTarget.on('fileuploadsubmit', function (e, data) { var result = Discourse.Utilities.validateUploadedFiles(data.files); // reset upload status when everything is ok - if (result) composerView.setProperties({ uploadProgress: 0, isUploading: true }); + if (result) self.setProperties({ uploadProgress: 0, isUploading: true }); return result; }); // send - this event is triggered when the upload request is about to start $uploadTarget.on('fileuploadsend', function (e, data) { // hide the "file selector" modal - composerView.get('controller').send('closeModal'); + self.get('controller').send('closeModal'); // cf. https://github.com/blueimp/jQuery-File-Upload/wiki/API#how-to-cancel-an-upload var jqXHR = data.xhr(); // need to wait for the link to show up in the DOM @@ -293,7 +297,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { // progress all $uploadTarget.on('fileuploadprogressall', function (e, data) { var progress = parseInt(data.loaded / data.total * 100, 10); - composerView.set('uploadProgress', progress); + self.set('uploadProgress', progress); }); // done @@ -302,8 +306,8 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { if (data.result.url) { var markdown = Discourse.Utilities.getUploadMarkdown(data.result); // appends a space at the end of the inserted markdown - composerView.addMarkdown(markdown + " "); - composerView.set('isUploading', false); + self.addMarkdown(markdown + " "); + self.set('isUploading', false); } else { bootbox.alert(I18n.t('post.errors.upload')); } @@ -312,7 +316,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { // fail $uploadTarget.on('fileuploadfail', function (e, data) { // hide upload status - composerView.set('isUploading', false); + self.set('isUploading', false); // display an error message Discourse.Utilities.displayErrorForUpload(data); }); @@ -321,7 +325,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { // to finish. return Em.run.later(jQuery, (function() { var replyTitle = $('#reply-title'); - composerView.resize(); + self.resize(); return replyTitle.length ? replyTitle.putCursorAtEnd() : $wmdInput.putCursorAtEnd(); }), 300); }, @@ -356,9 +360,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { }, childWillDestroyElement: function() { - var $uploadTarget = $('#reply-control'); - $uploadTarget.fileupload('destroy'); - $uploadTarget.off(); + this._unbindUploadTarget(); }, toggleAdminOptions: function() { @@ -410,7 +412,13 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { if( reason ) { return Discourse.InputValidation.create({ failed: true, reason: reason }); } - }.property('model.reply', 'model.replyLength', 'model.missingReplyCharacters', 'model.minimumPostLength') + }.property('model.reply', 'model.replyLength', 'model.missingReplyCharacters', 'model.minimumPostLength'), + + _unbindUploadTarget: function() { + var $uploadTarget = $('#reply-control'); + $uploadTarget.fileupload('destroy'); + $uploadTarget.off(); + }, }); // not sure if this is the right way, keeping here for now, we could use a mixin perhaps