diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index 7bd961fbc..d3548e44c 100755 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -377,17 +377,20 @@ class LeftAndMain extends Controller { if(!$title) $title = preg_replace('/Admin$/', '', $class); return $title; } - + public function show($request) { // TODO Necessary for TableListField URLs to work properly if($request->param('ID')) $this->setCurrentPageID($request->param('ID')); if($this->isAjax()) { - SSViewer::setOption('rewriteHashlinks', false); - $form = $this->getEditForm($request->param('ID')); - $content = $form->formHtmlContent(); + if($request->getVar('cms-view-form')) { + $form = $this->getEditForm(); + $content = $form->forTemplate(); + } else { + // Rendering is handled by template, which will call EditForm() eventually + $content = $this->renderWith($this->getTemplatesWithSuffix('_Content')); + } } else { - // Rendering is handled by template, which will call EditForm() eventually $content = $this->renderWith($this->getViewer('show')); } @@ -636,7 +639,7 @@ class LeftAndMain extends Controller { // write process might've changed the record, so we reload before returning $form = $this->getEditForm($record->ID); - return $form->formHtmlContent(); + return $form->forTemplate(); } public function delete($data, $form) { @@ -648,7 +651,7 @@ class LeftAndMain extends Controller { $record->delete(); if($this->isAjax()) { - return $this->EmptyForm()->formHtmlContent(); + return $this->EmptyForm()->forTemplate(); } else { $this->redirectBack(); } @@ -954,7 +957,7 @@ class LeftAndMain extends Controller { return $record->ID; } else if($this->isAjax()) { $form = $this->getEditForm($record->ID); - return $form->formHtmlContent(); + return $form->forTemplate(); } else { return $this->redirect(Controller::join_links($this->Link('show'), $record->ID)); } diff --git a/admin/code/ModelAdmin.php b/admin/code/ModelAdmin.php index dae73578b..2ac480841 100755 --- a/admin/code/ModelAdmin.php +++ b/admin/code/ModelAdmin.php @@ -664,7 +664,7 @@ class ModelAdmin_CollectionController extends Controller { $msg = _t('ModelAdmin.NORESULTS',"Your search didn't return any matching items"); } return new SS_HTTPResponse( - $resultsForm->formHtmlContent(), + $resultsForm->forTemplate(), 200, $msg ); @@ -794,7 +794,7 @@ class ModelAdmin_CollectionController extends Controller { */ function add($request) { return new SS_HTTPResponse( - $this->AddForm()->formHtmlContent(), + $this->AddForm()->forTemplate(), 200, sprintf( _t('ModelAdmin.ADDFORM', "Fill out this form to add a %s to the database."), @@ -845,6 +845,7 @@ class ModelAdmin_CollectionController extends Controller { $form = new Form($this, "AddForm", $fields, $actions, $validator); $form->loadDataFrom($newRecord); + $form->addExtraClass('cms-edit-form'); return $form; } @@ -862,7 +863,7 @@ class ModelAdmin_CollectionController extends Controller { $class = $this->parentController->getRecordControllerClass($this->getModelClass()); $recordController = new $class($this, $request, $model->ID); return new SS_HTTPResponse( - $recordController->EditForm()->formHtmlContent(), + $recordController->EditForm()->forTemplate(), 200, sprintf( _t('ModelAdmin.LOADEDFOREDITING', "Loaded '%s' for editing."), @@ -912,7 +913,7 @@ class ModelAdmin_RecordController extends Controller { function edit($request) { if ($this->currentRecord) { if($this->isAjax()) { - $this->response->setBody($this->EditForm()->formHtmlContent()); + $this->response->setBody($this->EditForm()->forTemplate()); $this->response->setStatusCode( 200, sprintf( @@ -924,10 +925,10 @@ class ModelAdmin_RecordController extends Controller { } else { // This is really quite ugly; to fix will require a change in the way that customise() works. :-( return $this->parentController->parentController->customise(array( - 'Right' => $this->parentController->parentController->customise(array( + 'Content' => $this->parentController->parentController->customise(array( 'EditForm' => $this->EditForm() - ))->renderWith(array("{$this->class}_right",'LeftAndMain_right')) - ))->renderWith(array('ModelAdmin','LeftAndMain')); + ))->renderWith(array("{$this->class}_Content",'ModelAdmin_Content', 'LeftAndMain_Content')) + ))->renderWith(array('ModelAdmin', 'LeftAndMain')); } } else { return _t('ModelAdmin.ITEMNOTFOUND', "I can't find that item"); @@ -963,6 +964,7 @@ class ModelAdmin_RecordController extends Controller { $form = new Form($this, "EditForm", $fields, $actions, $validator); $form->loadDataFrom($this->currentRecord); + $form->addExtraClass('cms-edit-form'); return $form; } @@ -1017,7 +1019,7 @@ class ModelAdmin_RecordController extends Controller { function view($request) { if($this->currentRecord) { $form = $this->ViewForm(); - return $form->formHtmlContent(); + return $form->forTemplate(); } else { return _t('ModelAdmin.ITEMNOTFOUND'); } diff --git a/admin/css/layout.css b/admin/css/layout.css index de4a5a1c4..773c6cc08 100755 --- a/admin/css/layout.css +++ b/admin/css/layout.css @@ -27,8 +27,8 @@ html, body { width: 100%; height: 100%; padding: 0; margin: 0; overflow: hidden; .cms-menu .cms-panel-content { width: 250px; } .cms-menu.collapsed { width: 40px; } -.cms-preview, .cms-menu, .cms-content, .cms-content-header, .cms-content-tools, .cms-content-form { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; vertical-align: middle; *vertical-align: auto; } -.cms-preview, .cms-menu, .cms-content, .cms-content-header, .cms-content-tools, .cms-content-form { *display: inline; } +.cms-preview, .cms-menu, .cms-content, .cms-content-header, .cms-content-tools, .cms-content-form, .cms-edit-form { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; vertical-align: middle; *vertical-align: auto; } +.cms-preview, .cms-menu, .cms-content, .cms-content-header, .cms-content-tools, .cms-content-form, .cms-edit-form { *display: inline; } .cms-content-tools { width: 230px; overflow: auto; } .cms-content-tools .cms-panel-header, .cms-content-tools .cms-panel-content { padding: 10px; } diff --git a/admin/css/screen.css b/admin/css/screen.css index 63707e33c..184bd9165 100755 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -144,7 +144,7 @@ li.jstree-closed > ul { display: none; } .cms-menu-list li { background-color: #b0bfc6; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #b0bfc6), color-stop(100%, #758f9b)); background-image: -moz-linear-gradient(top, #b0bfc6 0%, #758f9b 100%); background-image: linear-gradient(top, #b0bfc6 0%, #758f9b 100%); border-bottom: 1px solid #aaaaaa; } .cms-menu-list li a { display: block; height: 32px; vertical-align: middle; font-size: 14px; text-shadow: #aaaaaa 1px 1px 1px; color: #333333; padding: 5px; } -.cms-menu-list li a .icon { display: block; float: left; margin-right: 5px; background: url('../images/icons-32.png?1305837920') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } +.cms-menu-list li a .icon { display: block; float: left; margin-right: 5px; background: url('../images/icons-32.png?1306441269') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } .cms-menu-list li a:hover .icon { background-position: -32px 0px; } .cms-menu-list li a .text { display: block; padding-top: 10px; } .cms-menu-list li.current { background-color: #338dc1; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #338dc1), color-stop(100%, #1e5270)); background-image: -moz-linear-gradient(top, #338dc1 0%, #1e5270 100%); background-image: linear-gradient(top, #338dc1 0%, #1e5270 100%); } diff --git a/admin/javascript/LeftAndMain.AddForm.js b/admin/javascript/LeftAndMain.AddForm.js index 896f0e47b..8f9176cf8 100755 --- a/admin/javascript/LeftAndMain.AddForm.js +++ b/admin/javascript/LeftAndMain.AddForm.js @@ -91,8 +91,9 @@ data.push({name:button.attr('name'),value:button.val()}); // TODO Should be set by hiddenfield already - jQuery('.cms-edit-form').entwine('ss').loadForm( + jQuery('.cms-content').entwine('ss').loadForm( this.attr('action'), + null, function() { // Tree updates are triggered by Form_EditForm load events button.removeClass('loading'); @@ -129,7 +130,7 @@ dropdown.find('option').remove(); //Use tree hints to find allowed children for this node - if (className && typeof siteTreeHints !== 'undefined') { + if (className && siteTreeHints) { disallowed = siteTreeHints[className].disallowedChildren; } diff --git a/admin/javascript/LeftAndMain.Content.js b/admin/javascript/LeftAndMain.Content.js index 529dedd87..896eda0af 100644 --- a/admin/javascript/LeftAndMain.Content.js +++ b/admin/javascript/LeftAndMain.Content.js @@ -4,36 +4,228 @@ $('.LeftAndMain .cms-content').entwine({ - redraw: function() { + onmatch: function() { + var self = this; + + // Listen to tree selection events + $('.cms-tree').bind('select_node.jstree', function(e, data) { + var node = data.rslt.obj, loadedNodeID = self.find(':input[name=ID]').val() + + // Don't allow checking disabled nodes + if($(node).hasClass('disabled')) return false; + + // Don't allow reloading of currently selected node, + // mainly to avoid doing an ajax request on initial page load + if($(node).data('id') == loadedNodeID) return; + + var url = $(node).find('a:first').attr('href'); + if(url && url != '#') { + var xmlhttp = self.loadForm( + url, + null, + function(response) {} + ); + } else { + self.removeForm(); + } + }); + + this._super(); + }, + + beforeLoad: function(url) { + this.addClass('loading'); + this.cleanup(); }, cleanup: function() { this.empty(); }, - - loadPanel: function(url, callback, ajaxOptions) { + + /** + * Function: loadForm + * + * Parameters: + * (String) url - .. + * (Function) callback - (Optional) Called after the form content as been loaded + * (Object) ajaxOptions - Object literal merged into the jQuery.ajax() call (Optional) + * + * Returns: + * (XMLHTTPRequest) + */ + loadForm: function(url, form, callback, ajaxOptions) { var self = this; + if(!form || !form.length) var form = $('.cms-content-form form:first'); - this.trigger('load', {url: url, args: arguments}); + // Alert when unsaved changes are present + if(form._checkChangeTracker(true) == false) return false; + + // hide existing form - shown again through _loadResponse() + form.addClass('loading'); - this.cleanup(); + this.trigger('loadform', {form: form, url: url}); + + form.cleanup(); - // TODO Add browser history support - return $.ajax($.extend({ + return jQuery.ajax(jQuery.extend({ url: url, + // Ensure that form view is loaded (rather than whole "Content" template) + data: {'cms-view-form': 1}, complete: function(xmlhttp, status) { - self.loadPanel_onSuccess(xmlhttp.responseText, status, xmlhttp); - self.removeClass('loading'); - + self.loadForm_responseHandler(form, xmlhttp.responseText, status, xmlhttp); if(callback) callback.apply(self, arguments); }, dataType: 'html' }, ajaxOptions)); }, + + loadForm_responseHandler: function(oldForm, html, status, xmlhttp) { + oldForm.replaceWith(html); // triggers onmatch() on form + + // set status message based on response + var _statusMessage = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText; + }, + + /** + * 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'); + + this.trigger('submitform', {form: form, button: button}); + + // set button to "submitting" state + $(button).addClass('loading'); + + // @todo TinyMCE coupling + if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave(); + + // validate if required + if(!form.validate()) { + // TODO Automatically switch to the tab/position of the first error + statusMessage("Validation failed.", "bad"); - loadPanel_onSuccess: function(html, status, xmlhttp) { - this.html(html); - this.redraw(); + $(button).removeClass('loading'); + + return false; + } + + // save tab selections in order to reconstruct them later + var selectedTabs = []; + form.find('.ss-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'}); + jQuery.ajax(jQuery.extend({ + 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('ss-tabset')) self.removeClass('ss-tabset').addClass('ss-tabset'); + + // re-select previously saved tabs + $.each(selectedTabs, function(i, selectedTab) { + form.find('#' + selectedTab.id).tabs('select', selectedTab.selected); + }); + }, + 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') { + var form = this.replaceForm(oldForm, data); + + Behaviour.apply(); // refreshes ComplexTableField + + this.trigger('loadnewpage', {form: form, origData: origData, xmlhttp: xmlhttp}); + } + + // set status message based on response + var _statusMessage = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText; + }, + + /** + * @return {jQuery} New form element + */ + replaceForm: function(form, html) { + form.cleanup(); + 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._checkChangeTracker(true) == false) 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 de192dfb2..eac77c808 100755 --- a/admin/javascript/LeftAndMain.EditForm.js +++ b/admin/javascript/LeftAndMain.EditForm.js @@ -40,33 +40,47 @@ var self = this; this._setupChangeTracker(); - - $('.cms-tree').bind('select_node.jstree', function(e, data) { - var node = data.rslt.obj, loadedNodeID = self.find(':input[name=ID]').val() - - // Don't allow checking disabled nodes - if($(node).hasClass('disabled')) return false; - - // Don't allow reloading of currently selected node, - // mainly to avoid doing an ajax request on initial page load - if($(node).data('id') == loadedNodeID) return; - - var url = $(node).find('a:first').attr('href'); - if(url && url != '#') { - var xmlhttp = self.loadForm( - url, - function(response) {} - ); - } else { - self.removeForm(); - } - }); // Can't bind this through jQuery window.onbeforeunload = function(e) {return self._checkChangeTracker(false);}; + + // focus input on first form element + this.find(':input:visible:first').focus(); + + // Optionally get the form attributes from embedded fields, see Form->formHtmlContent() + for(var overrideAttr in {'action':true,'method':true,'enctype':true,'name':true}) { + var el = this.find(':input[name='+ '_form_' + overrideAttr + ']'); + if(el) { + this.attr(overrideAttr, el.val()); + el.remove(); + } + } + + // TODO + // // Rewrite # links + // html = html.replace(/(]+href *= *")#/g, '$1' + window.location.href.replace(/#.*$/,'') + '#'); + // + // // Rewrite iframe links (for IE) + // html = html.replace(/(]*src=")([^"]+)("[^>]*>)/g, '$1' + $('base').attr('href') + '$2$3'); + + // Show validation errors if necessary + if(this.hasClass('validationerror')) { + // TODO validation shouldnt need a special case + statusMessage(ss.i18n._t('ModelAdmin.VALIDATIONERROR', 'Validation Error'), 'bad'); + } this._super(); }, + + onunmatch: function() { + // Prepare iframes for removal, otherwise we get loading bugs + this.find('iframe').each(function() { + this.contentWindow.location.href = 'about:blank'; + $(this).remove(); + }); + + this._super(); + }, /** * Function: _setupChangeTracker @@ -114,90 +128,11 @@ * Suppress submission unless it is handled through ajaxSubmit(). */ onsubmit: function(e) { - this.ajaxSubmit(); + this.parents('.cms-content').submitForm(this); return false; }, - /** - * 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) - */ - ajaxSubmit: function(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'); - - this.trigger('ajaxsubmit', {button: button}); - - // set button to "submitting" state - $(button).addClass('loading'); - - // @todo TinyMCE coupling - if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave(); - - // validate if required - if(!this.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 = []; - this.find('.ss-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 = this.serializeArray(); - // add button action - formData.push({name: $(button).attr('name'), value:'1'}); - jQuery.ajax(jQuery.extend({ - url: this.attr('action'), - data: formData, - type: 'POST', - complete: function(xmlhttp, status) { - $(button).removeClass('loading'); - - // TODO This should be using the plugin API - self.removeClass('changed'); - - if(callback) callback(xmlhttp, status); - - // pass along original form data to enable old/new comparisons - if(loadResponse !== false) { - self._loadResponse(xmlhttp.responseText, status, xmlhttp, formData); - } - - // Re-init tabs (in case the form tag itself is a tabset) - if(self.hasClass('ss-tabset')) self.removeClass('ss-tabset').addClass('ss-tabset'); - - // re-select previously saved tabs - $.each(selectedTabs, function(i, selectedTab) { - self.find('#' + selectedTab.id).tabs('select', selectedTab.selected); - }); - }, - dataType: 'html' - }, ajaxOptions)); - - return false; - }, - /** * Function: validate * @@ -217,67 +152,6 @@ return isValid; }, - /** - * Function: loadForm - * - * Parameters: - * (String) url - .. - * (Function) callback - (Optional) Called after the form content as been loaded - * (Object) ajaxOptions - Object literal merged into the jQuery.ajax() call (Optional) - * - * Returns: - * (XMLHTTPRequest) - */ - loadForm: function(url, callback, ajaxOptions) { - var self = this; - - // Alert when unsaved changes are present - if(this._checkChangeTracker(true) == false) return false; - - // hide existing form - shown again through _loadResponse() - this.addClass('loading'); - - this.trigger('load', {url: url}); - - this.cleanup(); - - return jQuery.ajax(jQuery.extend({ - url: url, - complete: function(xmlhttp, status) { - // TODO This should be using the plugin API - self.removeClass('changed'); - - self._loadResponse(xmlhttp.responseText, status, xmlhttp); - - self.removeClass('loading'); - - if(callback) callback.apply(self, arguments); - }, - dataType: 'html' - }, ajaxOptions)); - }, - - /** - * 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(placeholderHtml) { - if(!placeholderHtml) placeholderHtml = this.getPlaceholderHtml(); - // Alert when unsaved changes are present - if(this._checkChangeTracker(true) == false) return; - this.trigger('removeform'); - this.html(placeholderHtml); - // TODO This should be using the plugin API - this.removeClass('changed'); - }, - /** * Function: cleanup * @@ -287,79 +161,9 @@ cleanup: function() { if((typeof tinymce != 'undefined') && tinymce.editors) { $(tinymce.editors).each(function() { - if(typeof(this.remove) == 'function') { - this.remove(); - } + if(typeof(this.remove) == 'function') this.remove(); }); } - }, - - /** - * 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. - */ - _loadResponse: function(data, status, xmlhttp, origData) { - if(status == 'success') { - this.cleanup(); - - var html = data; - - // Rewrite # links - html = html.replace(/(]+href *= *")#/g, '$1' + window.location.href.replace(/#.*$/,'') + '#'); - - // Rewrite iframe links (for IE) - html = html.replace(/(]*src=")([^"]+)("[^>]*>)/g, '$1' + $('base').attr('href') + '$2$3'); - - // Prepare iframes for removal, otherwise we get loading bugs - this.find('iframe').each(function() { - this.contentWindow.location.href = 'about:blank'; - $(this).remove(); - }); - - // update form content - if(html) { - this.html(html); - } else { - this.removeForm(); - } - - // If the form itself is a tabset, force re-rendering - if(this.hasClass('ss-tabset')) this.tabs('destroy').tabs(); - - this._setupChangeTracker(); - - // Optionally get the form attributes from embedded fields, see Form->formHtmlContent() - for(var overrideAttr in {'action':true,'method':true,'enctype':true,'name':true}) { - var el = this.find(':input[name='+ '_form_' + overrideAttr + ']'); - if(el) { - this.attr(overrideAttr, el.val()); - el.remove(); - } - } - - Behaviour.apply(); // refreshes ComplexTableField - - // focus input on first form element - this.find(':input:visible:first').focus(); - - this.trigger('loadnewpage', {data: data, origData: origData, xmlhttp: xmlhttp}); - } - - // set status message based on response - var _statusMessage = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText; - if(this.hasClass('validationerror')) { - // TODO validation shouldnt need a special case - statusMessage(ss.i18n._t('ModelAdmin.VALIDATIONERROR', 'Validation Error'), 'bad'); - } } }); @@ -376,7 +180,7 @@ * Function: onclick */ onclick: function(e) { - jQuery('.cms-edit-form').entwine('ss').ajaxSubmit(this); + $('.cms-content').submitForm(this.parents('form'), this); return false; } }); diff --git a/admin/javascript/LeftAndMain.js b/admin/javascript/LeftAndMain.js index 9576164d9..794a46bdf 100755 --- a/admin/javascript/LeftAndMain.js +++ b/admin/javascript/LeftAndMain.js @@ -73,6 +73,8 @@ }, redraw: function() { + // Not all edit forms are layouted + var editForm = this.find('.cms-edit-form[data-layout]').layout(); this.find('.cms-content').layout(); this.find('.cms-container').layout({resize: false}) } diff --git a/admin/javascript/ModelAdmin.js b/admin/javascript/ModelAdmin.js index 7f78fa66c..dcbad80ab 100755 --- a/admin/javascript/ModelAdmin.js +++ b/admin/javascript/ModelAdmin.js @@ -71,8 +71,9 @@ var btn = $(this[0].clickedButton); btn.addClass('loading'); - $('.cms-edit-form').loadForm( + $('.cms-content').loadForm( this.attr('action'), + null, function() { btn.removeClass('loading'); }, @@ -135,7 +136,8 @@ onclick: function(e) { var firstLink = this.find('a[href]'); if(!firstLink) return; - $('.cms-edit-form').loadForm(firstLink.attr('href')); + + window.History.pushState({selector: '.cms-edit-form'}, '', firstLink.attr('href')); return false; } }); @@ -153,8 +155,9 @@ className = $('select option:selected', this).val(); requestPath = this.attr('action').replace('ManagedModelsSelect', className + '/add'); var $button = $(':submit', this); - $('.cms-edit-form').loadForm( + $('.cms-content').loadForm( requestPath, + null, function() { $button.removeClass('loading'); $button = null; diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index c36c6411c..1665c48e0 100755 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -51,7 +51,8 @@ body .ui-widget { .cms-content, .cms-content-header, .cms-content-tools, -.cms-content-form { +.cms-content-form, +.cms-edit-form { @include inline-block; } diff --git a/admin/templates/Includes/LeftAndMain_Content.ss b/admin/templates/Includes/LeftAndMain_Content.ss index c74f54b0a..40443e046 100755 --- a/admin/templates/Includes/LeftAndMain_Content.ss +++ b/admin/templates/Includes/LeftAndMain_Content.ss @@ -1,3 +1 @@ -

-$EditForm -
\ No newline at end of file +$EditForm \ No newline at end of file diff --git a/admin/templates/Includes/LeftAndMain_EditForm.ss b/admin/templates/Includes/LeftAndMain_EditForm.ss index 93c09d44d..16a96631a 100755 --- a/admin/templates/Includes/LeftAndMain_EditForm.ss +++ b/admin/templates/Includes/LeftAndMain_EditForm.ss @@ -1,34 +1,32 @@ -
-
-

My Page Title

- <% if Fields.hasTabset %> - <% with Fields.fieldByName('Root') %> -
-
    - <% control Tabs %> -
  • $Title
  • - <% end_control %> -
- <% end_with %> -
- <% end_if %> +<% if IncludeFormTag %> + +<% end_if %> + +
+
+

My Page Title

+ <% if Fields.hasTabset %> + <% with Fields.fieldByName('Root') %> +
+
    + <% control Tabs %> +
  • $Title
  • + <% end_control %> +
+ <% end_with %> +
+ <% end_if %> - + +
-
-
+
- <% if IncludeFormTag %> - - <% end_if %> + - - -
- <% if Message %>

$Message

<% else %> @@ -55,8 +53,6 @@ <% end_if %>
- <% if IncludeFormTag %> - - <% end_if %> - -
\ No newline at end of file +<% if IncludeFormTag %> + +<% end_if %> \ No newline at end of file diff --git a/admin/templates/Includes/ModelAdmin.ss b/admin/templates/Includes/ModelAdmin.ss deleted file mode 100755 index e69de29bb..000000000