diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js
index 7dc2d13e5d8e8e83d0d6943c2d66c45ad03f9fba..04814fa0843cee9cad8d5549cf9b8cc246572709 100644
--- a/app/assets/javascripts/gl_form.js
+++ b/app/assets/javascripts/gl_form.js
@@ -35,8 +35,8 @@
         autosize(this.textarea);
         // form and textarea event listeners
         this.addEventListeners();
-        gl.text.init(this.form);
       }
+      gl.text.init(this.form);
       // hide discard button
       this.form.find('.js-note-discard').hide();
       return this.form.show();
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 0a0e73e0cccf7b0692c786d921d3de5400baecb3..31a71379af3886616cbdf0fd88193e14fb088a48 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -106,8 +106,9 @@
       );
     };
 
-    gl.utils.getPagePath = function() {
-      return $('body').data('page').split(':')[0];
+    gl.utils.getPagePath = function(index) {
+      index = index || 0;
+      return $('body').data('page').split(':')[index];
     };
 
     gl.utils.parseUrl = function (url) {
@@ -127,6 +128,17 @@
       return e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
     };
 
+    gl.utils.scrollToElement = function($el) {
+      var top = $el.offset().top;
+      gl.navBarHeight = gl.navBarHeight || $('.navbar-gitlab').height();
+      gl.navLinksHeight = gl.navLinksHeight || $('.nav-links').height();
+      gl.mrTabsHeight = gl.mrTabsHeight || $('.merge-request-tabs').height();
+
+      return $('body, html').animate({
+        scrollTop: top - (gl.navBarHeight + gl.navLinksHeight + gl.mrTabsHeight)
+      }, 200);
+    };
+
   })(window);
 
 }).call(this);
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index a8b9a352870b50d5bfc9c128e72c9b49417fba89..8de5a6191b6cd1ac364e71b2cdbee6900a85f211 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -52,6 +52,12 @@
       this.setupMainTargetNoteForm();
       this.initTaskList();
       this.collapseLongCommitList();
+
+      // We are in the Merge Requests page so we need another edit form for Changes tab
+      if (gl.utils.getPagePath(1) === 'merge_requests') {
+        $('.note-edit-form').clone()
+          .addClass('mr-note-edit-form').insertAfter('.note-edit-form');
+      }
     }
 
     Notes.prototype.addBinding = function() {
@@ -63,7 +69,7 @@
       // change note in UI after update
       $(document).on("ajax:success", "form.edit-note", this.updateNote);
       // Edit note link
-      $(document).on("click", ".js-note-edit", this.showEditForm);
+      $(document).on("click", ".js-note-edit", this.showEditForm.bind(this));
       $(document).on("click", ".note-edit-cancel", this.cancelEdit);
       // Reopen and close actions for Issue/MR combined with note form submit
       $(document).on("click", ".js-comment-button", this.updateCloseButton);
@@ -466,6 +472,7 @@
       var $html, $note_li;
       // Convert returned HTML to a jQuery object so we can modify it further
       $html = $(note.html);
+      this.revertNoteEditForm();
       gl.utils.localTimeAgo($('.js-timeago', $html));
       $html.renderGFM();
       $html.find('.js-task-list-container').taskList('enable');
@@ -480,48 +487,56 @@
     };
 
 
+    Notes.prototype.checkContentToAllowEditing = function($el) {
+      var initialContent = $el.find('.original-note-content').text().trim();
+      var currentContent = $el.find('.note-textarea').val();
+      var isAllowed = true;
+
+      if (currentContent === initialContent) {
+        this.removeNoteEditForm($el);
+      }
+      else {
+        var $buttons = $el.find('.note-form-actions');
+        var isWidgetVisible = gl.utils.isInViewport($el.get(0));
+
+        if (!isWidgetVisible) {
+          gl.utils.scrollToElement($el);
+        }
+
+        $el.find('.js-edit-warning').show();
+        isAllowed = false;
+      }
+
+      return isAllowed;
+    }
+
+
     /*
     Called in response to clicking the edit note link
 
     Replaces the note text with the note edit form
     Adds a data attribute to the form with the original content of the note for cancellations
-     */
-
+    */
     Notes.prototype.showEditForm = function(e, scrollTo, myLastNote) {
-      var $noteText, done, form, note;
       e.preventDefault();
-      note = $(this).closest(".note");
-      note.addClass("is-editting");
-      form = note.find(".note-edit-form");
-      form.addClass('current-note-edit-form');
-      // Show the attachment delete link
-      note.find(".js-note-attachment-delete").show();
-      done = function($noteText) {
-        var noteTextVal;
-        // Neat little trick to put the cursor at the end
-        noteTextVal = $noteText.val();
-        // Store the original note text in a data attribute to retrieve if a user cancels edit.
-        form.find('form.edit-note').data('original-note', noteTextVal);
-        return $noteText.val('').val(noteTextVal);
-      };
-      new GLForm(form);
-      if ((scrollTo != null) && (myLastNote != null)) {
-        // scroll to the bottom
-        // so the open of the last element doesn't make a jump
-        $('html, body').scrollTop($(document).height());
-        return $('html, body').animate({
-          scrollTop: myLastNote.offset().top - 150
-        }, 500, function() {
-          var $noteText;
-          $noteText = form.find(".js-note-text");
-          $noteText.focus();
-          return done($noteText);
-        });
-      } else {
-        $noteText = form.find('.js-note-text');
-        $noteText.focus();
-        return done($noteText);
+
+      var $target = $(e.target);
+      var $editForm = $(this.getEditFormSelector($target));
+      var $note = $target.closest('.note');
+      var $currentlyEditing = $('.note.is-editting:visible');
+
+      if ($currentlyEditing.length) {
+        var isEditAllowed = this.checkContentToAllowEditing($currentlyEditing);
+
+        if (!isEditAllowed) {
+          return;
+        }
       }
+
+      $note.find('.js-note-attachment-delete').show();
+      $editForm.addClass('current-note-edit-form');
+      $note.addClass('is-editting');
+      this.putEditFormInPlace($target);
     };
 
 
@@ -532,19 +547,41 @@
      */
 
     Notes.prototype.cancelEdit = function(e) {
-      var note;
       e.preventDefault();
-      note = $(e.target).closest('.note');
+      var $target = $(e.target);
+      var note = $target.closest('.note');
+      note.find('.js-edit-warning').hide();
+      this.revertNoteEditForm($target);
       return this.removeNoteEditForm(note);
     };
 
+    Notes.prototype.revertNoteEditForm = function($target) {
+      $target = $target || $('.note.is-editting:visible');
+      var selector = this.getEditFormSelector($target);
+      var $editForm = $(selector);
+
+      $editForm.insertBefore('.notes-form');
+      $editForm.find('.js-comment-button').enable();
+      $editForm.find('.js-edit-warning').hide();
+    };
+
+    Notes.prototype.getEditFormSelector = function($el) {
+      var selector = '.note-edit-form:not(.mr-note-edit-form)';
+
+      if ($el.parents('#diffs').length) {
+        selector = '.note-edit-form.mr-note-edit-form';
+      }
+
+      return selector;
+    };
+
     Notes.prototype.removeNoteEditForm = function(note) {
-      var form;
-      form = note.find(".current-note-edit-form");
-      note.removeClass("is-editting");
-      form.removeClass("current-note-edit-form");
+      var form = note.find('.current-note-edit-form');
+      note.removeClass('is-editting');
+      form.removeClass('current-note-edit-form');
+      form.find('.js-edit-warning').hide();
       // Replace markdown textarea text with original note text.
-      return form.find(".js-note-text").val(form.find('form.edit-note').data('original-note'));
+      return form.find('.js-note-text').val(form.find('form.edit-note').data('original-note'));
     };
 
 
@@ -837,15 +874,44 @@
 
     Notes.prototype.initTaskList = function() {
       this.enableTaskList();
-      return $(document).on('tasklist:changed', '.note .js-task-list-container', this.updateTaskList);
+      return $(document).on('tasklist:changed', '.note .js-task-list-container', this.updateTaskList.bind(this));
     };
 
     Notes.prototype.enableTaskList = function() {
       return $('.note .js-task-list-container').taskList('enable');
     };
 
-    Notes.prototype.updateTaskList = function() {
-      return $('form', this).submit();
+    Notes.prototype.putEditFormInPlace = function($el) {
+      var $editForm = $(this.getEditFormSelector($el));
+      var $note = $el.closest('.note');
+
+      $editForm.insertAfter($note.find('.note-text'));
+
+      var $originalContentEl = $note.find('.original-note-content');
+      var originalContent = $originalContentEl.text().trim();
+      var postUrl = $originalContentEl.data('post-url');
+      var targetId = $originalContentEl.data('target-id');
+      var targetType = $originalContentEl.data('target-type');
+
+      new GLForm($editForm.find('form'));
+
+      $editForm.find('form').attr('action', postUrl);
+      $editForm.find('.js-form-target-id').val(targetId);
+      $editForm.find('.js-form-target-type').val(targetType);
+      $editForm.find('.js-note-text').focus().val(originalContent);
+      $editForm.find('.js-md-write-button').trigger('click');
+      $editForm.find('.referenced-users').hide();
+    }
+
+    Notes.prototype.updateTaskList = function(e) {
+      var $target = $(e.target);
+      var $list = $target.closest('.js-task-list-container');
+      var $editForm = $(this.getEditFormSelector($target));
+      var $note = $list.closest('.note');
+
+      this.putEditFormInPlace($list);
+      $editForm.find('#note_note').val($note.find('.original-task-list').val());
+      $('form', $list).submit();
     };
 
     Notes.prototype.updateNotesCount = function(updateCount) {
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 9f1c6a8a26478caba5e18126aa2d25832351e481..f984b469609731a480e3cfc5aea03d4edb557bda 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -27,6 +27,7 @@
 .new-note,
 .note-edit-form {
   .note-form-actions {
+    position: relative;
     margin-top: $gl-padding;
   }
 
@@ -265,3 +266,18 @@
     }
   }
 }
+
+.note-edit-warning.settings-message {
+  display: none;
+  padding: 5px 10px;
+  position: absolute;
+  left: 127px;
+  top: 2px;
+
+  @media (max-width: $screen-xs-max) {
+    position: relative;
+    top: 0;
+    left: 0;
+    margin-bottom: 10px;
+  }
+}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 38c548908f87623b3f33d3df68b20cb14c232603..ad4c31ca29e92b188674ea45c9db5230650493e4 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -588,13 +588,11 @@ ul.notes {
 
 // Merge request notes in diffs
 .diff-file {
-
   // Diff is side by side
   .notes_content.parallel .note-header .note-headline-light {
     display: block;
     position: relative;
   }
-
   // Diff is inline
   .notes_content .note-header .note-headline-light {
     display: inline-block;
diff --git a/app/views/projects/notes/_edit_form.html.haml b/app/views/projects/notes/_edit_form.html.haml
index 8620f4922821725f50521b6ca467a010a669c36b..d36b4e6c8ab03d3cadf9d797f1d1899dbe42101e 100644
--- a/app/views/projects/notes/_edit_form.html.haml
+++ b/app/views/projects/notes/_edit_form.html.haml
@@ -1,11 +1,15 @@
 .note-edit-form
-  = form_for note, url: namespace_project_note_path(@project.namespace, @project, note), method: :put, remote: true, authenticity_token: true, html: { class: 'edit-note common-note-form js-quick-submit' } do |f|
-    = note_target_fields(note)
-    = render layout: 'projects/md_preview', locals: { preview_class: 'md-preview' } do
-      = render 'projects/zen', f: f, attr: :note, classes: 'note-textarea js-note-text js-task-list-field', placeholder: "Write a comment or drag your files here..."
+  = form_tag '#', method: :put, remote: true, class: 'edit-note common-note-form js-quick-submit' do
+    = hidden_field_tag :authenticity_token, form_authenticity_token
+    = hidden_field_tag :target_id, '', class: 'js-form-target-id'
+    = hidden_field_tag :target_type, '', class: 'js-form-target-type'
+    = render layout: 'projects/md_preview', locals: { preview_class: 'md-preview', referenced_users: true } do
+      = render 'projects/zen', attr: 'note[note]', classes: 'note-textarea js-note-text js-task-list-field', placeholder: "Write a comment or drag your files here..."
       = render 'projects/notes/hints'
 
     .note-form-actions.clearfix
-      = f.submit 'Save Comment', class: 'btn btn-nr btn-save js-comment-button'
+      .settings-message.note-edit-warning.js-edit-warning
+        Finish editing this message first!
+      = submit_tag 'Save Comment', class: 'btn btn-nr btn-save js-comment-button'
       %button.btn.btn-nr.btn-cancel.note-edit-cancel{ type: 'button' }
         Cancel
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index eb869ea85bfb42c551628eaca9078428b01be612..36c388c3318ae2505b39a9082531e600f6cc403c 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -67,7 +67,9 @@
             = note.redacted_note_html
         = edited_time_ago_with_tooltip(note, placement: 'bottom', html_class: 'note_edited_ago', include_author: true)
         - if note_editable
-          = render 'projects/notes/edit_form', note: note
+          .original-note-content.hidden{ data: { post_url: namespace_project_note_path(@project.namespace, @project, note), target_id: note.noteable.id, target_type: note.noteable.class.name.underscore } }
+            #{note.note}
+          %textarea.hidden.js-task-list-field.original-task-list #{note.note}
         .note-awards
           = render 'award_emoji/awards_block', awardable: note, inline: false
         - if note.system
diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml
index 00b62a595ff213fe190071003c1868f6cb5fdf06..f01bcfac898929a90ea3d11e1a87d3bdcb36396e 100644
--- a/app/views/projects/notes/_notes_with_form.html.haml
+++ b/app/views/projects/notes/_notes_with_form.html.haml
@@ -1,5 +1,8 @@
 %ul#notes-list.notes.main-notes-list.timeline
   = render "projects/notes/notes"
+
+= render 'projects/notes/edit_form'
+
 %ul.notes.notes-form.timeline
   %li.timeline-entry
     .flash-container.timeline-content
diff --git a/changelogs/unreleased/single-edit-comment-widget-2.yml b/changelogs/unreleased/single-edit-comment-widget-2.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e8b8beb15dee7b09487dcba2596f9eeba66c6e27
--- /dev/null
+++ b/changelogs/unreleased/single-edit-comment-widget-2.yml
@@ -0,0 +1,5 @@
+---
+title: Refactored note edit form to improve frontend performance on MR and Issues
+  pages, especially pages with has a lot of discussions in it
+merge_request: 8356
+author:
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index 9fffbb43e87e493f6912de64b00dfa5ef57d2d70..b785b2f7704a580c9e4387f0a4f5bd5685ff71bb 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -70,16 +70,15 @@ describe 'Comments', feature: true do
     end
 
     describe 'when editing a note', js: true do
-      it 'contains the hidden edit form' do
-        page.within("#note_#{note.id}") do
-          is_expected.to have_css('.note-edit-form', visible: false)
-        end
+      it 'there should be a hidden edit form' do
+        is_expected.to have_css('.note-edit-form:not(.mr-note-edit-form)', visible: false, count: 1)
+        is_expected.to have_css('.note-edit-form.mr-note-edit-form', visible: false, count: 1)
       end
 
       describe 'editing the note' do
         before do
           find('.note').hover
-          find(".js-note-edit").click
+          find('.js-note-edit').click
         end
 
         it 'shows the note edit form and hide the note body' do
@@ -90,14 +89,29 @@ describe 'Comments', feature: true do
           end
         end
 
-        # TODO: fix after 7.7 release
-        # it "should reset the edit note form textarea with the original content of the note if cancelled" do
-        #   within(".current-note-edit-form") do
-        #     fill_in "note[note]", with: "Some new content"
-        #     find(".btn-cancel").click
-        #     expect(find(".js-note-text", visible: false).text).to eq note.note
-        #   end
-        # end
+        it 'should reset the edit note form textarea with the original content of the note if cancelled' do
+          within('.current-note-edit-form') do
+            fill_in 'note[note]', with: 'Some new content'
+            find('.btn-cancel').click
+            expect(find('.js-note-text', visible: false).text).to eq ''
+          end
+        end
+
+        it 'allows using markdown buttons after saving a note and then trying to edit it again' do
+          page.within('.current-note-edit-form') do
+            fill_in 'note[note]', with: 'This is the new content'
+            find('.btn-save').click
+          end
+
+          find('.note').hover
+          find('.js-note-edit').click
+
+          page.within('.current-note-edit-form') do
+            expect(find('#note_note').value).to eq('This is the new content')
+            find('.js-md:first-child').click
+            expect(find('#note_note').value).to eq('This is the new content****')
+          end
+        end
 
         it 'appends the edited at time to the note' do
           page.within('.current-note-edit-form') do
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index d3bfa7730fa29029f8532a30e08a346677a4cfb0..bb13af7ac0c1f02ed6d2efdcdd2a5dce462904e6 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -19,6 +19,7 @@
       fixture.load(commentsTemplate);
       gl.utils.disableButtonIfEmptyField = _.noop;
       window.project_uploads_path = 'http://test.host/uploads';
+      $('body').data('page', 'projects:issues:show');
     });
 
     describe('task lists', function() {
diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js
index d80ce5a7f7e3a546cb6213027923d13db5fd5424..5b4d007c8f7363b7f555d83520f59cceb544ed9c 100644
--- a/spec/javascripts/zen_mode_spec.js
+++ b/spec/javascripts/zen_mode_spec.js
@@ -32,9 +32,9 @@
         return expect(Mousetrap.pause).toHaveBeenCalled();
       });
       return it('removes textarea styling', function() {
-        $('textarea').attr('style', 'height: 400px');
+        $('.notes-form textarea').attr('style', 'height: 400px');
         enterZen();
-        return expect('textarea').not.toHaveAttr('style');
+        return expect($('.notes-form textarea')).not.toHaveAttr('style');
       });
     });
     describe('in use', function() {
@@ -43,7 +43,7 @@
       });
       return it('exits on Escape', function() {
         escapeKeydown();
-        return expect($('.zen-backdrop')).not.toHaveClass('fullscreen');
+        return expect($('.notes-form .zen-backdrop')).not.toHaveClass('fullscreen');
       });
     });
     return describe('on exit', function() {
@@ -64,15 +64,15 @@
   });
 
   enterZen = function() {
-    return $('.js-zen-enter').click();
+    return $('.notes-form .js-zen-enter').click();
   };
 
-  exitZen = function() { // Ohmmmmmmm
-    return $('.js-zen-leave').click();
+  exitZen = function() {
+    return $('.notes-form .js-zen-leave').click();
   };
 
   escapeKeydown = function() {
-    return $('textarea').trigger($.Event('keydown', {
+    return $('.notes-form textarea').trigger($.Event('keydown', {
       keyCode: 27
     }));
   };