diff --git a/lib/assets/javascripts/views/answers/edit.js b/lib/assets/javascripts/views/answers/edit.js index f7d8f25..6c52889 100644 --- a/lib/assets/javascripts/views/answers/edit.js +++ b/lib/assets/javascripts/views/answers/edit.js @@ -12,6 +12,7 @@ const hideSavingMessage = jQuery => jQuery.closest('.question-form').find('.saving-message').hide(); const closestUnsavedMessage = jQuery => jQuery.closest('.question-form').find('.unsaved-message'); const questionId = jQuery => jQuery.closest('.form-answer').attr('data-autosave'); + const isStale = jQuery => jQuery.closest('.question-form').find('.answer-locking').html().length !== 0; /* * A map of debounced functions, one for each input, textarea or select change at any * form with class form-answer. The key represents a question id and the value holds @@ -22,7 +23,7 @@ */ const debounceMap = {}; const autoSaving = (jQuery) => { - if (jQuery.closest('.question-form').find('.answer-locking').html().length === 0) { + if (!isStale(jQuery)) { jQuery.closest('.form-answer').trigger('submit'); } }; @@ -66,8 +67,7 @@ } }; const failCallback = (error, jQuery) => { - hideSavingMessage(jQuery); // TODO function expects elem not jQuery - closestUnsavedMessage(jQuery).html( // TODO function expects elem not jQuery + closestUnsavedMessage(jQuery).html( (isObject(error.responseJSON) && isString(error.responseJSON.detail)) ? error.responseJSON.detail : error.statusText).show(); }; @@ -89,32 +89,35 @@ // (e.g. user clicks the button before the delay is met) debounceMap[id].cancel(); } - showSavingMessage(target); - const formElements = form.serializeArray(); - const answerId = formElements.find(el => el.name === 'answer[id]'); - - if (answerId) { - $.ajax({ - method: form.attr('method'), - url: form.attr('action'), - data: formElements, - }).done((data) => { - doneCallback(data, target); - }).fail((error) => { - failCallback(error, target); - }); - } + $.ajax({ + method: form.attr('method'), + url: form.attr('action'), + data: form.serializeArray(), + beforeSend: () => { + showSavingMessage(target); + }, + complete: () => { + hideSavingMessage(target); + }, + }).done((data) => { + doneCallback(data, target); + }).fail((error) => { + failCallback(error, target); + }); }; const blurHandler = (editor) => { - const id = questionId($(`#${editor.id}`)); - $(`#${editor.id}`).val(editor.getContent()); // Updates target element of editor with its content - if (!debounceMap[id]) { - debounceMap[id] = debounce(autoSaving); + const target = $(editor.getElement()); + const id = questionId(target); + if (editor.isDirty()) { + editor.save(); // Saves contents from editor to the textarea element + if (!debounceMap[id]) { + debounceMap[id] = debounce(autoSaving); + } + debounceMap[id](target); } - debounceMap[id]($(`#${editor.id}`)); }; const focusHandler = (editor) => { - const id = questionId($(`#${editor.id}`)); + const id = questionId($(editor.getElement())); if (debounceMap[id]) { /* Cancels the delayed execution of autoSaving, either because user * transitioned from an option_based question to the comment or