diff --git a/javascript/AssetAdmin.js b/javascript/AssetAdmin.js index 1f879155..8634e0e9 100755 --- a/javascript/AssetAdmin.js +++ b/javascript/AssetAdmin.js @@ -16,11 +16,10 @@ var _HANDLER_FORMS = { }; (function($) { - /** * Delete selected folders through "batch actions" tab. */ - $(function() { + $(document).ready(function() { $('#Form_BatchActionsForm').concrete('ss').register( // TODO Hardcoding of base URL 'admin/assets/batchactions/delete', @@ -36,32 +35,26 @@ var _HANDLER_FORMS = { ); }); - $('#Form_SyncForm').concrete('ss', function($) { - return { - onmatch: function() { - this.bind('submit', this._onsubmit); - this._super(); - }, - _onsubmit: function(e) { + $.concrete('ss', function($){ + $('#Form_SyncForm').concrete({ + onsubmit: function(e) { var button = jQuery(this).find(':submit:first'); button.addClass('loading'); $.get( jQuery(this).attr('action'), function() { button.removeClass('loading'); - // reload current var currNode = $('#sitetree')[0].firstSelected(); if(currNode) { var url = $(currNode).find('a').attr('href'); - $('#Form_EditForm').concrete('ss').loadForm(url); + $('#Form_EditForm').loadForm(url); } - } ); return false; } - }; + }); }); }(jQuery)); \ No newline at end of file diff --git a/javascript/CMSMain.EditForm.js b/javascript/CMSMain.EditForm.js index 8ec4d43c..11009ce4 100644 --- a/javascript/CMSMain.EditForm.js +++ b/javascript/CMSMain.EditForm.js @@ -1,43 +1,40 @@ (function($) { - /** - * Alert the user on change of page-type - this might have implications - * on the available form fields etc. - * @name ss.EditFormClassName - */ - $('#Form_EditForm :input[name=ClassName]').concrete('ss', function($){ - return/** @lends ss.EditFormClassName */{ + $.concrete('ss', function($){ + /** + * Alert the user on change of page-type - this might have implications + * on the available form fields etc. + * @name ss.EditFormClassName + */ + $('#Form_EditForm :input[name=ClassName]').concrete(/** @lends ss.EditFormClassName */{ onchange: function() { alert(ss.i18n._t('CMSMAIN.ALERTCLASSNAME')); } - }; - }); - - /** - * @class Input validation on the URLSegment field - * @name ss.EditForm.URLSegment - */ - $('#Form_EditForm input[name=URLSegment]').concrete('ss', function($){ - return/** @lends ss.EditForm.URLSegment */{ + }); + /** + * @class Input validation on the URLSegment field + * @name ss.EditForm.URLSegment + */ + $('#Form_EditForm input[name=URLSegment]').concrete(/** @lends ss.EditForm.URLSegment */{ FilterRegex: /[^A-Za-z0-9-]+/, - ValidationMessage: ss.i18n._t('CMSMAIN.URLSEGMENTVALIDATION'), - MaxLength: 50, - + onmatch : function() { var self = this; - + // intercept change event, do our own writing this.bind('change', function(e) { if(!self.validate()) { - jQuery.noticeAdd(self.ValidationMessage()); + jQuery.noticeAdd(self.getValidationMessage()); } self.val(self.suggestValue(e.target.value)); return false; }); + + this._super(); }, - + /** * Return a value matching the criteria. * @@ -46,38 +43,37 @@ */ suggestValue: function(val) { // TODO Do we want to enforce lowercasing in URLs? - return val.substr(0, this.MaxLength()).replace(this.FilterRegex(), '').toLowerCase(); + return val.substr(0, this.getMaxLength()).replace(this.getFilterRegex(), '').toLowerCase(); }, - + validate: function() { return ( - this.val().length > this.MaxLength() - || this.val().match(this.FilterRegex()) + this.val().length > this.getMaxLength() + || this.val().match(this.getFilterRegex()) ); } - }; - }); - - /** - * @class Input validation on the Title field - * @name ss.EditForm.Title - */ - $('#Form_EditForm input[name=Title]').concrete('ss', function($){ - return/** @lends ss.EditForm.Title */{ + }); + /** + * @class Input validation on the Title field + * @name ss.EditForm.Title + */ + $('#Form_EditForm input[name=Title]').concrete(/** @lends ss.EditForm.Title */{ onmatch : function() { var self = this; - + this.bind('change', function(e) { self.updateURLSegment(jQuery('#Form_EditForm input[name=URLSegment]')); // TODO We should really user-confirm these changes self.parents('form').find('input[name=MetaTitle], input[name=MenuTitle]').val(self.val()); }); + + this._super(); }, - + updateURLSegment: function(field) { if(!field || !field.length) return; - + // TODO language/logic coupling var isNew = this.val().indexOf("new") == 0; var suggestion = field.concrete('ss').suggestValue(this.val()); @@ -97,24 +93,22 @@ field.val(suggestion); } } - }; - }); + }); - /** - * @class ParentID field combination - mostly toggling between - * the two radiobuttons and setting the hidden "ParentID" field - * @name ss.EditForm.parentTypeSelector - */ - $('#Form_EditForm .parentTypeSelector').concrete('ss', function($){ - return/** @lends ss.EditForm.parentTypeSelector */{ + /** + * @class ParentID field combination - mostly toggling between + * the two radiobuttons and setting the hidden "ParentID" field + * @name ss.EditForm.parentTypeSelector + */ + $('#Form_EditForm .parentTypeSelector').concrete(/** @lends ss.EditForm.parentTypeSelector */{ onmatch : function() { var self = this; - this.find(':input[name=ParentType]').bind('click', function(e) {self._toggleSelection(e);}); - this._toggleSelection(); + + this._super(); }, - + _toggleSelection: function(e) { var selected = this.find(':input[name=ParentType]:checked').val(); // reset parent id if 'root' radiobutton is selected @@ -122,40 +116,38 @@ // toggle tree dropdown based on selection this.find('#ParentID').toggle(selected != 'root'); } - }; - }); + }); - /** - * @class Toggle display of group dropdown in "access" tab, - * based on selection of radiobuttons. - * @name ss.Form_EditForm.Access - */ - $('#Form_EditForm #CanViewType, #Form_EditForm #CanEditType').concrete('ss', function($){ - return/** @lends ss.Form_EditForm.Access */{ + /** + * @class Toggle display of group dropdown in "access" tab, + * based on selection of radiobuttons. + * @name ss.Form_EditForm.Access + */ + $('#Form_EditForm #CanViewType, #Form_EditForm #CanEditType').concrete(/** @lends ss.Form_EditForm.Access */{ onmatch: function() { // TODO Decouple var dropdown; if(this.attr('id') == 'CanViewType') dropdown = $('#ViewerGroups'); else if(this.attr('id') == 'CanEditType') dropdown = $('#EditorGroups'); - + this.find('.optionset :input').bind('change', function(e) { dropdown.toggle(e.target.value == 'OnlyTheseUsers'); }); - + // initial state var currentVal = this.find('input[name=' + this.attr('id') + ']:checked').val(); dropdown.toggle(currentVal == 'OnlyTheseUsers'); + + this._super(); } - }; - }); + }); - /** - * @class Email containing the link to the archived version of the page. - * Visible on readonly older versions of a specific page at the moment. - * @name ss.Form_EditForm_action_email - */ - $('#Form_EditForm .Actions #Form_EditForm_action_email').concrete('ss', function($){ - return/** @lends ss.Form_EditForm_action_email */{ + /** + * @class Email containing the link to the archived version of the page. + * Visible on readonly older versions of a specific page at the moment. + * @name ss.Form_EditForm_action_email + */ + $('#Form_EditForm .Actions #Form_EditForm_action_email').concrete(/** @lends ss.Form_EditForm_action_email */{ onclick: function(e) { window.open( 'mailto:?subject=' @@ -164,19 +156,17 @@ + $(':input[name=ArchiveEmailMessage]', this[0].form).val(), 'archiveemail' ); - + return false; } - }; - }); + }); - /** - * @class Open a printable representation of the form in a new window. - * Used for readonly older versions of a specific page. - * @name ss.Form_EditForm_action_print - */ - $('#Form_EditForm .Actions #Form_EditForm_action_print').concrete('ss', function($){ - return/** @lends ss.Form_EditForm_action_print */{ + /** + * @class Open a printable representation of the form in a new window. + * Used for readonly older versions of a specific page. + * @name ss.Form_EditForm_action_print + */ + $('#Form_EditForm .Actions #Form_EditForm_action_print').concrete(/** @lends ss.Form_EditForm_action_print */{ onclick: function(e) { var printURL = $(this[0].form).attr('action').replace(/\?.*$/,'') + '/printable/' @@ -184,22 +174,20 @@ if(printURL.substr(0,7) != 'http://') printURL = $('base').attr('href') + printURL; window.open(printURL, 'printable'); - + return false; } - }; - }); + }); - /** - * @class A "rollback" to a specific version needs user confirmation. - * @name ss.Form_EditForm_action_rollback - */ - $('#Form_EditForm .Actions #Form_EditForm_action_rollback').concrete('ss', function($){ - return/** @lends ss.Form_EditForm_action_rollback */{ + /** + * @class A "rollback" to a specific version needs user confirmation. + * @name ss.Form_EditForm_action_rollback + */ + $('#Form_EditForm .Actions #Form_EditForm_action_rollback').concrete(/** @lends ss.Form_EditForm_action_rollback */{ onclick: function(e) { // @todo i18n return confirm("Do you really want to copy the published content to the stage site?"); } - }; + }); }); }(jQuery)); \ No newline at end of file diff --git a/javascript/CMSMain.Translatable.js b/javascript/CMSMain.Translatable.js index cabe96cd..3fe3c8a9 100755 --- a/javascript/CMSMain.Translatable.js +++ b/javascript/CMSMain.Translatable.js @@ -1,20 +1,20 @@ (function($) { + $.concrete('ss', function($){ - /** - * @class Dropdown with languages above CMS tree, causing a redirect upon translation - * @name ss.CMSMain.LangSelector - */ - $('.CMSMain #Form_LangForm').concrete('ss', function($){ - return/** @lends ss.CMSMain.LangSelector */{ + /** + * @class Dropdown with languages above CMS tree, causing a redirect upon translation + * @name ss.CMSMain.LangSelector + */ + $('.CMSMain #Form_LangForm').concrete(/** @lends ss.CMSMain.LangSelector */{ onmatch: function() { var self = this; - + // monitor form loading for any locale changes $('#Form_EditForm').bind('loadnewpage', function(e) { var newLocale = $(this).find(':input[name=Locale]').val(); if(newLocale) self.val(newLocale); }); - + // whenever a new value is selected, reload the whole CMS in the new locale this.find(':input[name=Locale]').bind('change', function(e) { var url = document.location.href; @@ -24,29 +24,29 @@ document.location = url; return false; }); + + this._super(); } - }; - }); + }); - /** - * Loads /admin/createtranslation, which will create the new record, - * and redirect to an edit form. - * - * @class Dropdown in "Translation" tab in CMS forms, with button to - * trigger translating the currently loaded record. - * @name ss.CMSMain.createtranslation - * @requires jquery.metadata - */ - $('.CMSMain .createTranslation').concrete('ss', function($){ - return/** @lends ss.CMSMain.createtranslation */{ + /** + * Loads /admin/createtranslation, which will create the new record, + * and redirect to an edit form. + * + * @class Dropdown in "Translation" tab in CMS forms, with button to + * trigger translating the currently loaded record. + * @name ss.CMSMain.createtranslation + * @requires jquery.metadata + */ + $('.CMSMain .createTranslation').concrete(/** @lends ss.CMSMain.createtranslation */{ onmatch: function() { var self = this; - + this.find(':input[name=action_createtranslation]').bind('click', function(e) { var form = self.parents('form'); // redirect to new URL // TODO This should really be a POST request - + document.location.href = $('base').attr('href') + jQuery(self).metadata().url + '?ID=' + form.find(':input[name=ID]').val() + @@ -55,8 +55,9 @@ return false; }); + + this._super(); } - }; + }); }); - }(jQuery)); \ No newline at end of file diff --git a/javascript/CMSMain.js b/javascript/CMSMain.js index 3d23451a..7b9ece43 100644 --- a/javascript/CMSMain.js +++ b/javascript/CMSMain.js @@ -1,11 +1,11 @@ (function($) { + $.concrete('ss', function($){ - /** - * @class All forms in the right content panel should have closeable jQuery UI style titles. - * @name ss.contentPanel.form - */ - $('#contentPanel form').concrete('ss', function($){ - return/** @lends ss.contentPanel.form */{ + /** + * @class All forms in the right content panel should have closeable jQuery UI style titles. + * @name ss.contentPanel.form + */ + $('#contentPanel form').concrete(/** @lends ss.contentPanel.form */{ onmatch: function() { // Style as title bar this.find(':header:first').titlebar({ @@ -14,33 +14,27 @@ // The close button should close the east panel of the layout this.find(':header:first .ui-dialog-titlebar-close').bind('click', function(e) { $('body.CMSMain').concrete('ss').MainLayout().close('east'); - return false; }); + + this._super(); } - }; - }); + }); - /** - * @class Control the site tree filter. - * Toggles search form fields based on a dropdown selection, - * similar to "Smart Search" criteria in iTunes. - * @name ss.Form_SeachTreeForm - */ - $('#Form_SearchTreeForm').concrete('ss', function($) { - return/** @lends ss.Form_SeachTreeForm */{ - + /** + * @class Control the site tree filter. + * Toggles search form fields based on a dropdown selection, + * similar to "Smart Search" criteria in iTunes. + * @name ss.Form_SeachTreeForm + */ + $('#Form_SearchTreeForm').concrete(/** @lends ss.Form_SeachTreeForm */{ /** * @type DOMElement */ SelectEl: null, - + onmatch: function() { var self = this; - - // TODO Cant bind to onsubmit/onreset directly because of IE6 - this.bind('submit', function(e) {return self._submitForm(e);}); - this.bind('reset', function(e) {return self._resetForm(e);}); // only the first field should be visible by default this.find('.field').not(':first').hide(); @@ -52,39 +46,40 @@ ); this._setOptions(); - - }, + this._super(); + }, + _setOptions: function() { var self = this; - + // reset existing elements - self.SelectEl().find('option').remove(); - + self.getSelectEl().find('option').remove(); + // add default option // TODO i18n - jQuery('').appendTo(self.SelectEl()); - + jQuery('').appendTo(self.getSelectEl()); + // populate dropdown values from existing fields this.find('.field').each(function() { - $('').appendTo(self.SelectEl()) + $('').appendTo(self.getSelectEl()) .val(this.id) .text($(this).find('label').text()); }); }, - + /** * Filter tree based on selected criteria. */ - _submitForm: function(e) { + onsubmit: function(e) { var self = this; var data = []; - + // convert from jQuery object literals to hash map $(this.serializeArray()).each(function(i, el) { data[el.name] = el.value; }); - + // Set new URL $('#sitetree')[0].setCustomURL(this.attr('action') + '&action_getfilteredsubtree=1', data); @@ -92,20 +87,20 @@ // @todo: Make them work together if ($('#sitetree')[0].isDraggable) $('#sitetree')[0].stopBeingDraggable(); this.find('.checkboxAboveTree :checkbox').val(false).attr('disabled', true); - + // disable buttons to avoid multiple submission //this.find(':submit').attr('disabled', true); - + this.find(':submit[name=action_getfilteredsubtree]').addClass('loading'); - + this._reloadSitetree(); - + return false; }, - - _resetForm: function(e) { + + onreset: function(e) { this.find('.field').clearFields().not(':first').hide(); - + // Reset URL to default $('#sitetree')[0].clearCustomURL(); @@ -114,29 +109,29 @@ // reset all options, some of the might be removed this._setOptions(); - + this._reloadSitetree(); - + return false; }, - + _addField: function(e) { var $select = $(e.target); // show formfield matching the option this.find('#' + $select.val()).show(); - + // remove option from dropdown, each field should just exist once this.find('option[value=' + $select.val() + ']').remove(); - + // jump back to default entry $select.val(0); - + return false; }, - + _reloadSitetree: function() { var self = this; - + $('#sitetree')[0].reload({ onSuccess : function(response) { self.find(':submit').attr('disabled', false).removeClass('loading'); @@ -150,32 +145,27 @@ } }); } - }; - }); + }); - /** - * @class Simple form with a page type dropdown - * which creates a new page through #Form_EditForm and adds a new tree node. - * @name ss.reports_holder - */ - $('#Form_ReportForm').concrete(function($) { - return/** @lends ss.reports_holder */{ + /** + * @class Simple form with a page type dropdown + * which creates a new page through #Form_EditForm and adds a new tree node. + * @name ss.reports_holder + */ + $('#Form_ReportForm').concrete(/** @lends ss.reports_holder */{ onmatch: function() { var self = this; - - this.bind('submit', function(e) { - return self._submit(e); - }); - + // integrate with sitetree selection changes + // TODO Only trigger when report is visible jQuery('#sitetree').bind('selectionchanged', function(e, data) { self.find(':input[name=ID]').val(data.node.getIdx()); self.trigger('submit'); }); - + // move submit button to the top this.find('#ReportClass').after(this.find('.Actions')); - + // links in results this.find('ul a').bind('click', function(e) { var $link = $(this); @@ -188,18 +178,20 @@ ); return false; }); - }, - _submit: function(e) { + this._super(); + }, + + onsubmit: function(e) { var self = this; - + // dont process if no report is selected var reportClass = this.find(':input[name=ReportClass]').val(); if(!reportClass) return false; - + var button = this.find(':submit:first'); button.addClass('loading'); - + jQuery.ajax({ url: this.attr('action'), data: this.serializeArray(), @@ -212,60 +204,58 @@ button.removeClass('loading'); } }); - + return false; } - }; - }); + }); - /** - * @class Simple form showing versions of a specific page. - * @name ss.Form_VersionsForm - * @requires ss.i18n - */ - $('#Form_VersionsForm').concrete(function($) { - return/** @lends ss.Form_VersionsForm */{ + /** + * @class Simple form showing versions of a specific page. + * @name ss.Form_VersionsForm + * @requires ss.i18n + */ + $('#Form_VersionsForm').concrete(/** @lends ss.Form_VersionsForm */{ onmatch: function() { var self = this; - - this.bind('submit', function(e) { - return self._submit(e); - }); - + // set button to be available in form submit event later on this.find(':submit').bind('click', function(e) { self.data('_clickedButton', this); }); + this.bind('submit', function(e) { + return self._submit(); + }); + // integrate with sitetree selection changes jQuery('#sitetree').bind('selectionchanged', function(e, data) { self.find(':input[name=ID]').val(data.node.getIdx()); if(self.is(':visible')) self.trigger('submit'); }); - + // refresh when field is selected // TODO coupling $('#treepanes').bind('accordionchange', function(e, ui) { if($(ui.newContent).attr('id') == 'Form_VersionsForm') self.trigger('submit'); }); - + // submit when 'show unpublished versions' checkbox is changed this.find(':input[name=ShowUnpublished]').bind('change', function(e) { // force the refresh button, not 'compare versions' self.data('_clickedButton', self.find(':submit[name=action_versions]')); self.trigger('submit'); }); - + // move submit button to the top this.find('#ReportClass').after(this.find('.Actions')); - + // links in results this.find('td').bind('click', function(e) { var td = $(this); - + // exclude checkboxes if($(e.target).is(':input')) return true; - + var link = $(this).siblings('.versionlink').find('a').attr('href'); td.addClass('loading'); jQuery('#Form_EditForm').concrete('ss').loadForm( @@ -276,7 +266,7 @@ ); return false; }); - + // compare versions action this.find(':submit[name=action_compareversions]').bind('click', function(e) { // validation: only allow selection of exactly two versions @@ -288,31 +278,33 @@ )); return false; } - + // overloaded submission: refresh the right form instead self.data('_clickedButton', this); - self._submit(e, true); - + self._submit(true); + return false; - }) + }); + + this._super(); }, - + /** * @param {boolean} loadEditForm Determines if responses should show in current panel, * or in the edit form (in the case of 'compare versions'). */ - _submit: function(e, loadEditForm) { + _submit: function(loadEditForm) { var self = this; - + // Don't submit with empty ID if(!this.find(':input[name=ID]').val()) return false; - + var $button = (self.data('_clickedButton')) ? $(self.data('_clickedButton')) : this.find(':submit:first'); $button.addClass('loading'); - + var data = this.serializeArray(); data.push({name:$button.attr('name'), value: $button.val()}); - + if(loadEditForm) { jQuery('#Form_EditForm').concrete('ss').loadForm( this.attr('action'), @@ -335,9 +327,8 @@ }); } - return false; } - }; + }); }); })(jQuery); \ No newline at end of file diff --git a/javascript/LeftAndMain.AddForm.js b/javascript/LeftAndMain.AddForm.js index 35fe5f5e..aab57e6f 100644 --- a/javascript/LeftAndMain.AddForm.js +++ b/javascript/LeftAndMain.AddForm.js @@ -1,60 +1,58 @@ (function($) { - /** - * @class Simple form with a page type dropdown - * which creates a new page through #Form_EditForm and adds a new tree node. - * @name ss.Form_AddForm - * @requires ss.i18n - * @requires ss.Form_EditForm - */ - $('#Form_AddForm').concrete(function($) { - return/** @lends ss.Form_AddForm */{ + $.concrete('ss', function($){ + /** + * @class Simple form with a page type dropdown + * which creates a new page through #Form_EditForm and adds a new tree node. + * @name ss.Form_AddForm + * @requires ss.i18n + * @requires ss.Form_EditForm + */ + $('#Form_AddForm').concrete(/** @lends ss.Form_AddForm */{ /** * @type DOMElement */ Tree: null, - + /** * @type Array Internal counter to create unique page identifiers prior to ajax saving */ - _NewPages: [], - + NewPages: [], + onmatch: function() { var self = this; - - this.bind('submit', function(e) { - return self._submit(e); - }); - + Observable.applyTo(this[0]); - + var tree = jQuery('#sitetree')[0]; this.setTree(tree); jQuery(tree).bind('selectionchanged', function(e, data) {self.treeSelectionChanged(e, data);}); - - this.find(':input[name=PageType]').bind('change', this.typeDropdownChanged); - }, - _submit: function(e) { - var newPages = this._NewPages(); - var tree = this.Tree(); + this.find(':input[name=PageType]').bind('change', this.typeDropdownChanged); + + this._super(); + }, + + onsubmit: function(e) { + var newPages = this.getNewPages(); + var tree = this.getTree(); var parentID = (tree.firstSelected()) ? tree.getIdxOf(tree.firstSelected()) : 0; // TODO: Remove 'new-' code http://open.silverstripe.com/ticket/875 if(parentID && parentID.substr(0,3) == 'new') { alert(ss.i18n._t('CMSMAIN.WARNINGSAVEPAGESBEFOREADDING')); } - + if(tree.firstSelected() && jQuery(tree.firstSelected()).hasClass("nochildren")) { alert(ss.i18n._t('CMSMAIN.CANTADDCHILDREN') ); } - + // Optionally initalize the new pages tracker if(!newPages[parentID] ) newPages[parentID] = 1; // default to first button var button = jQuery(this).find(':submit:first'); button.addClass('loading'); - + // collect data and submit the form var data = jQuery(this).serializeArray(); data.push({name:'Suffix',value:newPages[parentID]++}); @@ -67,26 +65,26 @@ }, {type: 'POST', data: data} ); - - this.set_NewPages(newPages); + + this.setNewPages(newPages); return false; }, treeSelectionChanged : function(e, data) { var selectedNode = data.node; - + if(selectedNode.hints && selectedNode.hints.defaultChild) { this.find(':input[name=PageType]').val(selectedNode.hints.defaultChild); } - - var parentID = this.Tree().getIdxOf(selectedNode); + + var parentID = this.getTree().getIdxOf(selectedNode); this.find(':input[name=ParentID]').val(parentID ? parentID : 0); }, typeDropdownChanged : function() { - var tree = this.Tree(); - + var tree = this.getTree(); + // Don't do anything if we're already on an appropriate node var sel = tree.firstSelected(); if(sel && sel.hints && sel.hints.allowedChildren) { @@ -102,6 +100,6 @@ if(newNode) tree.changeCurrentTo(newNode); } } - }; + }); }); }(jQuery)); \ No newline at end of file diff --git a/javascript/LeftAndMain.BatchActions.js b/javascript/LeftAndMain.BatchActions.js index 67a877fa..8294f8c4 100644 --- a/javascript/LeftAndMain.BatchActions.js +++ b/javascript/LeftAndMain.BatchActions.js @@ -1,69 +1,68 @@ (function($) { + $.concrete('ss', function($){ + + /** + * @class Batch actions which take a bunch of selected pages, + * usually from the CMS tree implementation, and perform serverside + * callbacks on the whole set. We make the tree selectable when the jQuery.UI tab + * enclosing this form is opened. + * @name ss.Form_BatchActionsForm + * + * Events: + * - register: Called before an action is added. + * - unregister: Called before an action is removed. + */ + $('#Form_BatchActionsForm').concrete(/** @lends ss.Form_BatchActionsForm */{ - /** - * @class Batch actions which take a bunch of selected pages, - * usually from the CMS tree implementation, and perform serverside - * callbacks on the whole set. We make the tree selectable when the jQuery.UI tab - * enclosing this form is opened. - * @name ss.Form_BatchActionsForm - * - * Events: - * - register: Called before an action is added. - * - unregister: Called before an action is removed. - */ - $('#Form_BatchActionsForm').concrete('ss', function($){ - return/** @lends ss.Form_BatchActionsForm */{ - /** * @type {DOMElement} */ Tree: null, - + /** * @type {Array} Stores all actions that can be performed on the collected IDs as * function closures. This might trigger filtering of the selected IDs, * a confirmation message, etc. */ Actions: [], - + onmatch: function() { var self = this; this.setTree($('#sitetree')[0]); - - $(this.Tree()).bind('selectionchanged', function(e, data) { + + $(this.getTree()).bind('selectionchanged', function(e, data) { self._treeSelectionChanged(data.node); }); - + // if tab which contains this form is shown, make the tree selectable $('#TreeActions').bind('tabsselect', function(e, ui) { if($(ui.panel).attr('id') != 'TreeActions-batchactions') return; - + // if the panel is visible (meaning about to be closed), // disable tree selection and reset any values. Otherwise enable it. if($(ui.panel).is(':visible')) { - $(self.Tree()).removeClass('multiselect'); + $(self.getTree()).removeClass('multiselect'); } else { self._multiselectTransform(); } - + }); - this.bind('submit', function(e) {return self._submit(e);}); + this._super(); }, - + /** * @param {String} type * @param {Function} callback */ register: function(type, callback) { this.trigger('register', {type: type, callback: callback}); - - var actions = this.Actions(); + var actions = this.getActions(); actions[type] = callback; this.setActions(actions); }, - + /** * Remove an existing action. * @@ -71,12 +70,12 @@ */ unregister: function(type) { this.trigger('unregister', {type: type}); - - var actions = this.Actions(); + + var actions = this.getActions(); if(actions[type]) delete actions[type]; this.setActions(actions); }, - + /** * Determines if we should allow and track tree selections. * @@ -86,10 +85,10 @@ _isActive: function() { return $('#TreeActions-batchactions').is(':visible'); }, - - _submit: function(e) { + + onsubmit: function(e) { var ids = []; - var tree = this.Tree(); + var tree = this.getTree(); // find all explicitly selected IDs $(tree).find('li.selected').each(function() { ids.push(tree.getIdxOf(this)); @@ -98,29 +97,27 @@ ids.push(tree.getIdxOf(this)); }); }); - + // if no nodes are selected, return with an error if(!ids || !ids.length) { alert(ss.i18n._t('CMSMAIN.SELECTONEPAGE')); return false; } - + // apply callback, which might modify the IDs var type = this.find(':input[name=Action]').val(); - if(this.Actions()[type]) ids = this.Actions()[type].apply(this, [ids]); - + if(this.getActions()[type]) ids = this.getActions()[type].apply(this, [ids]); + // if no IDs are selected, stop here. This is an implict way for the // callback to cancel the actions - if(!ids || !ids.length) { - return false; - } + if(!ids || !ids.length) return false; // write IDs to the hidden field this.find(':input[name=csvIDs]').val(ids.join(',')); - + var button = this.find(':submit:first'); button.addClass('loading'); - + jQuery.ajax({ // don't use original form url url: type, @@ -128,7 +125,7 @@ data: this.serializeArray(), complete: function(xmlhttp, status) { button.removeClass('loading'); - + // status message var msg = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText; statusMessage(msg, (status == 'success') ? 'good' : 'bad'); @@ -146,11 +143,11 @@ if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node); } } - + // reset selection state // TODO Should unselect all selected nodes as well jQuery(tree).removeClass('multiselect'); - + // Check if current page still exists, and refresh it. // Otherwise remove the current form var selectedNode = tree.firstSelected(); @@ -165,14 +162,14 @@ } else { $('#Form_EditForm').concrete('ss').removeForm(); } - + // close panel // TODO Coupling with tabs $('#TreeActions').tabs('select', -1); }, dataType: 'json' }); - + return false; }, @@ -181,10 +178,10 @@ */ _multiselectTransform : function() { // make tree selectable - jQuery(this.Tree()).addClass('multiselect'); + jQuery(this.getTree()).addClass('multiselect'); // auto-select the current node - var node = this.Tree().firstSelected(); + var node = this.getTree().firstSelected(); if(node){ node.removeNodeClass('current'); node.addNodeClass('selected'); @@ -197,7 +194,7 @@ }); } }, - + /** * Only triggers if the field is considered 'active'. * @todo Most of this is basically simulating broken behaviour of the MultiselectTree mixin, @@ -205,7 +202,7 @@ */ _treeSelectionChanged: function(node) { if(!this._isActive()) return; - + if(node.selected) { node.removeNodeClass('selected'); node.selected = false; @@ -213,7 +210,7 @@ // Select node node.addNodeClass('selected'); node.selected = true; - + // Open node in order to allow proper selection of children if($(node).hasClass('unexpanded')) { node.open(); @@ -226,7 +223,7 @@ }); } } - }; + }); }); $(document).ready(function() { diff --git a/javascript/LeftAndMain.EditForm.js b/javascript/LeftAndMain.EditForm.js index 22355466..aad4cdd5 100644 --- a/javascript/LeftAndMain.EditForm.js +++ b/javascript/LeftAndMain.EditForm.js @@ -1,53 +1,48 @@ (function($) { + $.concrete('ss', function($){ - /** - * @class Base edit form, provides ajaxified saving - * and reloading itself through the ajax return values. - * Takes care of resizing tabsets within the layout container. - * @name ss.Form_EditForm - * @require jquery.changetracker - * - *