diff --git a/admin/javascript/LeftAndMain.AddForm.js b/admin/javascript/LeftAndMain.AddForm.js index 5f32a841a..57eef8278 100644 --- a/admin/javascript/LeftAndMain.AddForm.js +++ b/admin/javascript/LeftAndMain.AddForm.js @@ -91,7 +91,7 @@ data.push({name:button.attr('name'),value:button.val()}); // TODO Should be set by hiddenfield already - $('.cms-content').submitForm( + $('.cms-container').submitForm( this, button, function() { diff --git a/admin/javascript/LeftAndMain.Content.js b/admin/javascript/LeftAndMain.Content.js index 2f69663ad..819292a0d 100644 --- a/admin/javascript/LeftAndMain.Content.js +++ b/admin/javascript/LeftAndMain.Content.js @@ -27,168 +27,6 @@ this.add(this.find('.cms-tabset')).redrawTabs(); this.layout(); - }, - - /** - * Function: ajaxSubmit - * - * Parameters: - * {DOMElement} button - The pressed button (optional) - * {Function} callback - Called in complete() handler of jQuery.ajax() - * {Object} ajaxOptions - Object literal to merge into $.ajax() call - * {boolean} loadResponse - Render response through _loadResponse() (Default: true) - * - * Returns: - * (boolean) - */ - submitForm: function(form, button, callback, ajaxOptions, loadResponse) { - var self = this; - - // look for save button - if(!button) button = this.find('.Actions :submit[name=action_save]'); - // default to first button if none given - simulates browser behaviour - if(!button) button = this.find('.Actions :submit:first'); - - form.trigger('beforesave'); - this.trigger('submitform', {form: form, button: button}); - - // set button to "submitting" state - $(button).addClass('loading'); - - // validate if required - if(!form.validate()) { - // TODO Automatically switch to the tab/position of the first error - statusMessage("Validation failed.", "bad"); - - $(button).removeClass('loading'); - - return false; - } - - // save tab selections in order to reconstruct them later - var selectedTabs = []; - form.find('.cms-tabset').each(function(i, el) { - if($(el).attr('id')) selectedTabs.push({id:$(el).attr('id'), selected:$(el).tabs('option', 'selected')}); - }); - - // get all data from the form - var formData = form.serializeArray(); - // add button action - formData.push({name: $(button).attr('name'), value:'1'}); - // Artificial HTTP referer, IE doesn't submit them via ajax. - // Also rewrites anchors to their page counterparts, which is important - // as automatic browser ajax response redirects seem to discard the hash/fragment. - formData.push({name: 'BackURL', value:History.getPageUrl()}); - - // Standard Pjax behaviour is to replace the submitted form with new content. - // The returned view isn't always decided upon when the request - // is fired, so the server might decide to change it based on its own logic, - // sending back different `X-Pjax` headers and content - jQuery.ajax(jQuery.extend({ - headers: { - "X-Pjax" : "CurrentForm,Breadcrumbs" - }, - url: form.attr('action'), - data: formData, - type: 'POST', - complete: function(xmlhttp, status) { - $(button).removeClass('loading'); - - // TODO This should be using the plugin API - form.removeClass('changed'); - - if(callback) callback(xmlhttp, status); - - // pass along original form data to enable old/new comparisons - if(loadResponse !== false) { - self.submitForm_responseHandler(form, xmlhttp.responseText, status, xmlhttp, formData); - } - - // Re-init tabs (in case the form tag itself is a tabset) - if(self.hasClass('cms-tabset')) self.removeClass('cms-tabset').addClass('cms-tabset'); - - // re-select previously saved tabs - $.each(selectedTabs, function(i, selectedTab) { - form.find('#' + selectedTab.id).tabs('select', selectedTab.selected); - }); - - // Redraw the layout - $('.cms-container').redraw(); - }, - dataType: 'html' - }, ajaxOptions)); - - return false; - }, - - /** - * Function: _loadResponse - * - * Parameters: - * {String} data - Either HTML for straight insertion, or eval'ed JavaScript. - * If passed as HTML, it is assumed that everying inside the
tag is replaced, - * but the old tag itself stays intact. - * {String} status - * {XMLHTTPRequest} xmlhttp - .. - * {Array} origData - The original submitted data, useful to do comparisons of changed - * values in new form output, e.g. to detect a URLSegment being changed on the serverside. - * Array in jQuery serializeArray() notation. - */ - submitForm_responseHandler: function(oldForm, data, status, xmlhttp, origData) { - if(status == 'success') { - if(!data) return; - - var form, newContent = $(data); - - // HACK If response contains toplevel panel rather than a form, replace it instead. - // For example, a page view shows tree + edit form. Deleting this page redirects to - // the "pages" overview, which doesn't have a separate tree panel. - if(newContent.is('.cms-content')) { - $('.cms-content').replaceWith(newContent); - } else { - form = this.replaceForm(oldForm, newContent); - } - - if(typeof(Behaviour) != 'undefined') Behaviour.apply(); // refreshes ComplexTableField - - this.trigger('reloadeditform', {form: form, origData: origData, xmlhttp: xmlhttp}); - } - }, - - /** - * @return {jQuery} New form element - */ - replaceForm: function(form, html) { - if(html) { - var parent = form.parent(), id = form.attr('id'); - form.replaceWith(html); - // Try to get the new form by ID (assuming they're identical), otherwise fall back to the first form in the parent - return id ? $('#' + id) : parent.children('form:first'); - } else { - this.removeForm(form); - return null; - } - }, - - /** - * Function: removeForm - * - * Remove everying inside the tag - * with a custom HTML fragment. Useful e.g. for deleting a page in the CMS. - * Checks for unsaved changes before removing the form - * - * Parameters: - * {String} placeholderHtml - Short note why the form has been removed, displayed in

tags. - * Falls back to the default RemoveText() option (Optional) - */ - removeForm: function(form, placeholderHtml) { - if(!placeholderHtml) placeholderHtml = this.getPlaceholderHtml(); - // Alert when unsaved changes are present - if(!form.confirmUnsavedChanges()) return; - this.trigger('removeform'); - this.html(placeholderHtml); - // TODO This should be using the plugin API - this.removeClass('changed'); } }); diff --git a/admin/javascript/LeftAndMain.EditForm.js b/admin/javascript/LeftAndMain.EditForm.js index 821a79f0f..df21d57eb 100644 --- a/admin/javascript/LeftAndMain.EditForm.js +++ b/admin/javascript/LeftAndMain.EditForm.js @@ -29,7 +29,6 @@ * Events: * ajaxsubmit - Form is about to be submitted through ajax * validate - Contains validation result - * removeform - A form is about to be removed from the DOM * load - Form is about to be loaded through ajax */ $('.cms-edit-form').entwine(/** @lends ss.Form_EditForm */{ @@ -158,7 +157,7 @@ // which means the browser auto-selects the first available form button. // This might be an unrelated button of the form field, // or a destructive action (if "save" is not available, or not on first position). - if(button) this.closest('.cms-content').submitForm(this, button); + if(button) this.closest('.cms-container').submitForm(this, button); return false; }, diff --git a/admin/javascript/LeftAndMain.js b/admin/javascript/LeftAndMain.js index 8fec12c78..d3fe34a4f 100644 --- a/admin/javascript/LeftAndMain.js +++ b/admin/javascript/LeftAndMain.js @@ -178,6 +178,98 @@ jQuery.noConflict(); window.location = $.path.makeUrlAbsolute(url, $('base').attr('href')); } }, + + /** + * Function: submitForm + * + * Parameters: + * {DOMElement} form - The form to be submitted. Needs to be passed + * in to avoid entwine methods/context being removed through replacing the node itself. + * {DOMElement} button - The pressed button (optional) + * {Function} callback - Called in complete() handler of jQuery.ajax() + * {Object} ajaxOptions - Object literal to merge into $.ajax() call + * + * Returns: + * (boolean) + */ + submitForm: function(form, button, callback, ajaxOptions) { + var self = this; + + // look for save button + if(!button) button = this.find('.Actions :submit[name=action_save]'); + // default to first button if none given - simulates browser behaviour + if(!button) button = this.find('.Actions :submit:first'); + + form.trigger('beforesave'); + this.trigger('submitform', {form: form, button: button}); + + // set button to "submitting" state + $(button).addClass('loading'); + + // validate if required + if(!form.validate()) { + // TODO Automatically switch to the tab/position of the first error + statusMessage("Validation failed.", "bad"); + + $(button).removeClass('loading'); + + return false; + } + + // save tab selections in order to reconstruct them later + var selectedTabs = []; + form.find('.cms-tabset').each(function(i, el) { + if($(el).attr('id')) selectedTabs.push({id:$(el).attr('id'), selected:$(el).tabs('option', 'selected')}); + }); + + // get all data from the form + var formData = form.serializeArray(); + // add button action + formData.push({name: $(button).attr('name'), value:'1'}); + // Artificial HTTP referer, IE doesn't submit them via ajax. + // Also rewrites anchors to their page counterparts, which is important + // as automatic browser ajax response redirects seem to discard the hash/fragment. + formData.push({name: 'BackURL', value:History.getPageUrl()}); + + // Standard Pjax behaviour is to replace the submitted form with new content. + // The returned view isn't always decided upon when the request + // is fired, so the server might decide to change it based on its own logic, + // sending back different `X-Pjax` headers and content + jQuery.ajax(jQuery.extend({ + headers: {"X-Pjax" : "CurrentForm,Breadcrumbs"}, + url: form.attr('action'), + data: formData, + type: 'POST', + complete: function() { + $(button).removeClass('loading'); + }, + success: function(data, status, xhr) { + form.removeClass('changed'); // TODO This should be using the plugin API + if(callback) callback(xmlhttp, status); + + var newContentEls = self.handleAjaxResponse(data, status, xhr); + if(!newContentEls) return; + + var newForm = newContentEls.filter('form'); + + // Re-init tabs (in case the form tag itself is a tabset) + if(newForm.hasClass('cms-tabset')) newForm.removeClass('cms-tabset').addClass('cms-tabset'); + + // re-select previously saved tabs + $.each(selectedTabs, function(i, selectedTab) { + newForm.find('#' + selectedTab.id).tabs('select', selectedTab.selected); + }); + + // Redraw the layout + $('.cms-container').redraw(); + + form.trigger('reloadeditform', {form: newForm, formData: formData, xmlhttp: xhr}); + }, + dataType: 'json' + }, ajaxOptions)); + + return false; + }, /** * Handles ajax loading of new panels through the window.History object.