MINOR Adjusted CMS JavaScript to new jquery-concrete API: Getters have 'get' prefix, namespaces are defined in blocks, event handlers work consistently. Mostly indentation and structure changes, no logic changes.

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92825 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2009-11-21 03:19:59 +00:00
parent 1036329e86
commit 4d60aa5c83
11 changed files with 651 additions and 725 deletions

View File

@ -16,11 +16,10 @@ var _HANDLER_FORMS = {
}; };
(function($) { (function($) {
/** /**
* Delete selected folders through "batch actions" tab. * Delete selected folders through "batch actions" tab.
*/ */
$(function() { $(document).ready(function() {
$('#Form_BatchActionsForm').concrete('ss').register( $('#Form_BatchActionsForm').concrete('ss').register(
// TODO Hardcoding of base URL // TODO Hardcoding of base URL
'admin/assets/batchactions/delete', 'admin/assets/batchactions/delete',
@ -36,32 +35,26 @@ var _HANDLER_FORMS = {
); );
}); });
$('#Form_SyncForm').concrete('ss', function($) { $.concrete('ss', function($){
return { $('#Form_SyncForm').concrete({
onmatch: function() { onsubmit: function(e) {
this.bind('submit', this._onsubmit);
this._super();
},
_onsubmit: function(e) {
var button = jQuery(this).find(':submit:first'); var button = jQuery(this).find(':submit:first');
button.addClass('loading'); button.addClass('loading');
$.get( $.get(
jQuery(this).attr('action'), jQuery(this).attr('action'),
function() { function() {
button.removeClass('loading'); button.removeClass('loading');
// reload current // reload current
var currNode = $('#sitetree')[0].firstSelected(); var currNode = $('#sitetree')[0].firstSelected();
if(currNode) { if(currNode) {
var url = $(currNode).find('a').attr('href'); var url = $(currNode).find('a').attr('href');
$('#Form_EditForm').concrete('ss').loadForm(url); $('#Form_EditForm').loadForm(url);
} }
} }
); );
return false; return false;
} }
}; });
}); });
}(jQuery)); }(jQuery));

View File

@ -1,43 +1,40 @@
(function($) { (function($) {
/** $.concrete('ss', function($){
* Alert the user on change of page-type - this might have implications /**
* on the available form fields etc. * Alert the user on change of page-type - this might have implications
* @name ss.EditFormClassName * on the available form fields etc.
*/ * @name ss.EditFormClassName
$('#Form_EditForm :input[name=ClassName]').concrete('ss', function($){ */
return/** @lends ss.EditFormClassName */{ $('#Form_EditForm :input[name=ClassName]').concrete(/** @lends ss.EditFormClassName */{
onchange: function() { onchange: function() {
alert(ss.i18n._t('CMSMAIN.ALERTCLASSNAME')); 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-]+/, FilterRegex: /[^A-Za-z0-9-]+/,
ValidationMessage: ss.i18n._t('CMSMAIN.URLSEGMENTVALIDATION'), ValidationMessage: ss.i18n._t('CMSMAIN.URLSEGMENTVALIDATION'),
MaxLength: 50, MaxLength: 50,
onmatch : function() { onmatch : function() {
var self = this; var self = this;
// intercept change event, do our own writing // intercept change event, do our own writing
this.bind('change', function(e) { this.bind('change', function(e) {
if(!self.validate()) { if(!self.validate()) {
jQuery.noticeAdd(self.ValidationMessage()); jQuery.noticeAdd(self.getValidationMessage());
} }
self.val(self.suggestValue(e.target.value)); self.val(self.suggestValue(e.target.value));
return false; return false;
}); });
this._super();
}, },
/** /**
* Return a value matching the criteria. * Return a value matching the criteria.
* *
@ -46,38 +43,37 @@
*/ */
suggestValue: function(val) { suggestValue: function(val) {
// TODO Do we want to enforce lowercasing in URLs? // 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() { validate: function() {
return ( return (
this.val().length > this.MaxLength() this.val().length > this.getMaxLength()
|| this.val().match(this.FilterRegex()) || 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() { onmatch : function() {
var self = this; var self = this;
this.bind('change', function(e) { this.bind('change', function(e) {
self.updateURLSegment(jQuery('#Form_EditForm input[name=URLSegment]')); self.updateURLSegment(jQuery('#Form_EditForm input[name=URLSegment]'));
// TODO We should really user-confirm these changes // TODO We should really user-confirm these changes
self.parents('form').find('input[name=MetaTitle], input[name=MenuTitle]').val(self.val()); self.parents('form').find('input[name=MetaTitle], input[name=MenuTitle]').val(self.val());
}); });
this._super();
}, },
updateURLSegment: function(field) { updateURLSegment: function(field) {
if(!field || !field.length) return; if(!field || !field.length) return;
// TODO language/logic coupling // TODO language/logic coupling
var isNew = this.val().indexOf("new") == 0; var isNew = this.val().indexOf("new") == 0;
var suggestion = field.concrete('ss').suggestValue(this.val()); var suggestion = field.concrete('ss').suggestValue(this.val());
@ -97,24 +93,22 @@
field.val(suggestion); field.val(suggestion);
} }
} }
}; });
});
/** /**
* @class ParentID field combination - mostly toggling between * @class ParentID field combination - mostly toggling between
* the two radiobuttons and setting the hidden "ParentID" field * the two radiobuttons and setting the hidden "ParentID" field
* @name ss.EditForm.parentTypeSelector * @name ss.EditForm.parentTypeSelector
*/ */
$('#Form_EditForm .parentTypeSelector').concrete('ss', function($){ $('#Form_EditForm .parentTypeSelector').concrete(/** @lends ss.EditForm.parentTypeSelector */{
return/** @lends ss.EditForm.parentTypeSelector */{
onmatch : function() { onmatch : function() {
var self = this; var self = this;
this.find(':input[name=ParentType]').bind('click', function(e) {self._toggleSelection(e);}); this.find(':input[name=ParentType]').bind('click', function(e) {self._toggleSelection(e);});
this._toggleSelection(); this._toggleSelection();
this._super();
}, },
_toggleSelection: function(e) { _toggleSelection: function(e) {
var selected = this.find(':input[name=ParentType]:checked').val(); var selected = this.find(':input[name=ParentType]:checked').val();
// reset parent id if 'root' radiobutton is selected // reset parent id if 'root' radiobutton is selected
@ -122,40 +116,38 @@
// toggle tree dropdown based on selection // toggle tree dropdown based on selection
this.find('#ParentID').toggle(selected != 'root'); this.find('#ParentID').toggle(selected != 'root');
} }
}; });
});
/** /**
* @class Toggle display of group dropdown in "access" tab, * @class Toggle display of group dropdown in "access" tab,
* based on selection of radiobuttons. * based on selection of radiobuttons.
* @name ss.Form_EditForm.Access * @name ss.Form_EditForm.Access
*/ */
$('#Form_EditForm #CanViewType, #Form_EditForm #CanEditType').concrete('ss', function($){ $('#Form_EditForm #CanViewType, #Form_EditForm #CanEditType').concrete(/** @lends ss.Form_EditForm.Access */{
return/** @lends ss.Form_EditForm.Access */{
onmatch: function() { onmatch: function() {
// TODO Decouple // TODO Decouple
var dropdown; var dropdown;
if(this.attr('id') == 'CanViewType') dropdown = $('#ViewerGroups'); if(this.attr('id') == 'CanViewType') dropdown = $('#ViewerGroups');
else if(this.attr('id') == 'CanEditType') dropdown = $('#EditorGroups'); else if(this.attr('id') == 'CanEditType') dropdown = $('#EditorGroups');
this.find('.optionset :input').bind('change', function(e) { this.find('.optionset :input').bind('change', function(e) {
dropdown.toggle(e.target.value == 'OnlyTheseUsers'); dropdown.toggle(e.target.value == 'OnlyTheseUsers');
}); });
// initial state // initial state
var currentVal = this.find('input[name=' + this.attr('id') + ']:checked').val(); var currentVal = this.find('input[name=' + this.attr('id') + ']:checked').val();
dropdown.toggle(currentVal == 'OnlyTheseUsers'); dropdown.toggle(currentVal == 'OnlyTheseUsers');
this._super();
} }
}; });
});
/** /**
* @class Email containing the link to the archived version of the page. * @class Email containing the link to the archived version of the page.
* Visible on readonly older versions of a specific page at the moment. * Visible on readonly older versions of a specific page at the moment.
* @name ss.Form_EditForm_action_email * @name ss.Form_EditForm_action_email
*/ */
$('#Form_EditForm .Actions #Form_EditForm_action_email').concrete('ss', function($){ $('#Form_EditForm .Actions #Form_EditForm_action_email').concrete(/** @lends ss.Form_EditForm_action_email */{
return/** @lends ss.Form_EditForm_action_email */{
onclick: function(e) { onclick: function(e) {
window.open( window.open(
'mailto:?subject=' 'mailto:?subject='
@ -164,19 +156,17 @@
+ $(':input[name=ArchiveEmailMessage]', this[0].form).val(), + $(':input[name=ArchiveEmailMessage]', this[0].form).val(),
'archiveemail' 'archiveemail'
); );
return false; return false;
} }
}; });
});
/** /**
* @class Open a printable representation of the form in a new window. * @class Open a printable representation of the form in a new window.
* Used for readonly older versions of a specific page. * Used for readonly older versions of a specific page.
* @name ss.Form_EditForm_action_print * @name ss.Form_EditForm_action_print
*/ */
$('#Form_EditForm .Actions #Form_EditForm_action_print').concrete('ss', function($){ $('#Form_EditForm .Actions #Form_EditForm_action_print').concrete(/** @lends ss.Form_EditForm_action_print */{
return/** @lends ss.Form_EditForm_action_print */{
onclick: function(e) { onclick: function(e) {
var printURL = $(this[0].form).attr('action').replace(/\?.*$/,'') var printURL = $(this[0].form).attr('action').replace(/\?.*$/,'')
+ '/printable/' + '/printable/'
@ -184,22 +174,20 @@
if(printURL.substr(0,7) != 'http://') printURL = $('base').attr('href') + printURL; if(printURL.substr(0,7) != 'http://') printURL = $('base').attr('href') + printURL;
window.open(printURL, 'printable'); window.open(printURL, 'printable');
return false; return false;
} }
}; });
});
/** /**
* @class A "rollback" to a specific version needs user confirmation. * @class A "rollback" to a specific version needs user confirmation.
* @name ss.Form_EditForm_action_rollback * @name ss.Form_EditForm_action_rollback
*/ */
$('#Form_EditForm .Actions #Form_EditForm_action_rollback').concrete('ss', function($){ $('#Form_EditForm .Actions #Form_EditForm_action_rollback').concrete(/** @lends ss.Form_EditForm_action_rollback */{
return/** @lends ss.Form_EditForm_action_rollback */{
onclick: function(e) { onclick: function(e) {
// @todo i18n // @todo i18n
return confirm("Do you really want to copy the published content to the stage site?"); return confirm("Do you really want to copy the published content to the stage site?");
} }
}; });
}); });
}(jQuery)); }(jQuery));

View File

@ -1,20 +1,20 @@
(function($) { (function($) {
$.concrete('ss', function($){
/** /**
* @class Dropdown with languages above CMS tree, causing a redirect upon translation * @class Dropdown with languages above CMS tree, causing a redirect upon translation
* @name ss.CMSMain.LangSelector * @name ss.CMSMain.LangSelector
*/ */
$('.CMSMain #Form_LangForm').concrete('ss', function($){ $('.CMSMain #Form_LangForm').concrete(/** @lends ss.CMSMain.LangSelector */{
return/** @lends ss.CMSMain.LangSelector */{
onmatch: function() { onmatch: function() {
var self = this; var self = this;
// monitor form loading for any locale changes // monitor form loading for any locale changes
$('#Form_EditForm').bind('loadnewpage', function(e) { $('#Form_EditForm').bind('loadnewpage', function(e) {
var newLocale = $(this).find(':input[name=Locale]').val(); var newLocale = $(this).find(':input[name=Locale]').val();
if(newLocale) self.val(newLocale); if(newLocale) self.val(newLocale);
}); });
// whenever a new value is selected, reload the whole CMS in the new locale // whenever a new value is selected, reload the whole CMS in the new locale
this.find(':input[name=Locale]').bind('change', function(e) { this.find(':input[name=Locale]').bind('change', function(e) {
var url = document.location.href; var url = document.location.href;
@ -24,29 +24,29 @@
document.location = url; document.location = url;
return false; return false;
}); });
this._super();
} }
}; });
});
/** /**
* Loads /admin/createtranslation, which will create the new record, * Loads /admin/createtranslation, which will create the new record,
* and redirect to an edit form. * and redirect to an edit form.
* *
* @class Dropdown in "Translation" tab in CMS forms, with button to * @class Dropdown in "Translation" tab in CMS forms, with button to
* trigger translating the currently loaded record. * trigger translating the currently loaded record.
* @name ss.CMSMain.createtranslation * @name ss.CMSMain.createtranslation
* @requires jquery.metadata * @requires jquery.metadata
*/ */
$('.CMSMain .createTranslation').concrete('ss', function($){ $('.CMSMain .createTranslation').concrete(/** @lends ss.CMSMain.createtranslation */{
return/** @lends ss.CMSMain.createtranslation */{
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this.find(':input[name=action_createtranslation]').bind('click', function(e) { this.find(':input[name=action_createtranslation]').bind('click', function(e) {
var form = self.parents('form'); var form = self.parents('form');
// redirect to new URL // redirect to new URL
// TODO This should really be a POST request // TODO This should really be a POST request
document.location.href = $('base').attr('href') + document.location.href = $('base').attr('href') +
jQuery(self).metadata().url + jQuery(self).metadata().url +
'?ID=' + form.find(':input[name=ID]').val() + '?ID=' + form.find(':input[name=ID]').val() +
@ -55,8 +55,9 @@
return false; return false;
}); });
this._super();
} }
}; });
}); });
}(jQuery)); }(jQuery));

View File

@ -1,11 +1,11 @@
(function($) { (function($) {
$.concrete('ss', function($){
/** /**
* @class All forms in the right content panel should have closeable jQuery UI style titles. * @class All forms in the right content panel should have closeable jQuery UI style titles.
* @name ss.contentPanel.form * @name ss.contentPanel.form
*/ */
$('#contentPanel form').concrete('ss', function($){ $('#contentPanel form').concrete(/** @lends ss.contentPanel.form */{
return/** @lends ss.contentPanel.form */{
onmatch: function() { onmatch: function() {
// Style as title bar // Style as title bar
this.find(':header:first').titlebar({ this.find(':header:first').titlebar({
@ -14,33 +14,27 @@
// The close button should close the east panel of the layout // The close button should close the east panel of the layout
this.find(':header:first .ui-dialog-titlebar-close').bind('click', function(e) { this.find(':header:first .ui-dialog-titlebar-close').bind('click', function(e) {
$('body.CMSMain').concrete('ss').MainLayout().close('east'); $('body.CMSMain').concrete('ss').MainLayout().close('east');
return false; return false;
}); });
this._super();
} }
}; });
});
/** /**
* @class Control the site tree filter. * @class Control the site tree filter.
* Toggles search form fields based on a dropdown selection, * Toggles search form fields based on a dropdown selection,
* similar to "Smart Search" criteria in iTunes. * similar to "Smart Search" criteria in iTunes.
* @name ss.Form_SeachTreeForm * @name ss.Form_SeachTreeForm
*/ */
$('#Form_SearchTreeForm').concrete('ss', function($) { $('#Form_SearchTreeForm').concrete(/** @lends ss.Form_SeachTreeForm */{
return/** @lends ss.Form_SeachTreeForm */{
/** /**
* @type DOMElement * @type DOMElement
*/ */
SelectEl: null, SelectEl: null,
onmatch: function() { onmatch: function() {
var self = this; 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 // only the first field should be visible by default
this.find('.field').not(':first').hide(); this.find('.field').not(':first').hide();
@ -52,39 +46,40 @@
); );
this._setOptions(); this._setOptions();
},
this._super();
},
_setOptions: function() { _setOptions: function() {
var self = this; var self = this;
// reset existing elements // reset existing elements
self.SelectEl().find('option').remove(); self.getSelectEl().find('option').remove();
// add default option // add default option
// TODO i18n // TODO i18n
jQuery('<option value="0">Add Criteria</option>').appendTo(self.SelectEl()); jQuery('<option value="0">Add Criteria</option>').appendTo(self.getSelectEl());
// populate dropdown values from existing fields // populate dropdown values from existing fields
this.find('.field').each(function() { this.find('.field').each(function() {
$('<option />').appendTo(self.SelectEl()) $('<option />').appendTo(self.getSelectEl())
.val(this.id) .val(this.id)
.text($(this).find('label').text()); .text($(this).find('label').text());
}); });
}, },
/** /**
* Filter tree based on selected criteria. * Filter tree based on selected criteria.
*/ */
_submitForm: function(e) { onsubmit: function(e) {
var self = this; var self = this;
var data = []; var data = [];
// convert from jQuery object literals to hash map // convert from jQuery object literals to hash map
$(this.serializeArray()).each(function(i, el) { $(this.serializeArray()).each(function(i, el) {
data[el.name] = el.value; data[el.name] = el.value;
}); });
// Set new URL // Set new URL
$('#sitetree')[0].setCustomURL(this.attr('action') + '&action_getfilteredsubtree=1', data); $('#sitetree')[0].setCustomURL(this.attr('action') + '&action_getfilteredsubtree=1', data);
@ -92,20 +87,20 @@
// @todo: Make them work together // @todo: Make them work together
if ($('#sitetree')[0].isDraggable) $('#sitetree')[0].stopBeingDraggable(); if ($('#sitetree')[0].isDraggable) $('#sitetree')[0].stopBeingDraggable();
this.find('.checkboxAboveTree :checkbox').val(false).attr('disabled', true); this.find('.checkboxAboveTree :checkbox').val(false).attr('disabled', true);
// disable buttons to avoid multiple submission // disable buttons to avoid multiple submission
//this.find(':submit').attr('disabled', true); //this.find(':submit').attr('disabled', true);
this.find(':submit[name=action_getfilteredsubtree]').addClass('loading'); this.find(':submit[name=action_getfilteredsubtree]').addClass('loading');
this._reloadSitetree(); this._reloadSitetree();
return false; return false;
}, },
_resetForm: function(e) { onreset: function(e) {
this.find('.field').clearFields().not(':first').hide(); this.find('.field').clearFields().not(':first').hide();
// Reset URL to default // Reset URL to default
$('#sitetree')[0].clearCustomURL(); $('#sitetree')[0].clearCustomURL();
@ -114,29 +109,29 @@
// reset all options, some of the might be removed // reset all options, some of the might be removed
this._setOptions(); this._setOptions();
this._reloadSitetree(); this._reloadSitetree();
return false; return false;
}, },
_addField: function(e) { _addField: function(e) {
var $select = $(e.target); var $select = $(e.target);
// show formfield matching the option // show formfield matching the option
this.find('#' + $select.val()).show(); this.find('#' + $select.val()).show();
// remove option from dropdown, each field should just exist once // remove option from dropdown, each field should just exist once
this.find('option[value=' + $select.val() + ']').remove(); this.find('option[value=' + $select.val() + ']').remove();
// jump back to default entry // jump back to default entry
$select.val(0); $select.val(0);
return false; return false;
}, },
_reloadSitetree: function() { _reloadSitetree: function() {
var self = this; var self = this;
$('#sitetree')[0].reload({ $('#sitetree')[0].reload({
onSuccess : function(response) { onSuccess : function(response) {
self.find(':submit').attr('disabled', false).removeClass('loading'); self.find(':submit').attr('disabled', false).removeClass('loading');
@ -150,32 +145,27 @@
} }
}); });
} }
}; });
});
/** /**
* @class Simple form with a page type dropdown * @class Simple form with a page type dropdown
* which creates a new page through #Form_EditForm and adds a new tree node. * which creates a new page through #Form_EditForm and adds a new tree node.
* @name ss.reports_holder * @name ss.reports_holder
*/ */
$('#Form_ReportForm').concrete(function($) { $('#Form_ReportForm').concrete(/** @lends ss.reports_holder */{
return/** @lends ss.reports_holder */{
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this.bind('submit', function(e) {
return self._submit(e);
});
// integrate with sitetree selection changes // integrate with sitetree selection changes
// TODO Only trigger when report is visible
jQuery('#sitetree').bind('selectionchanged', function(e, data) { jQuery('#sitetree').bind('selectionchanged', function(e, data) {
self.find(':input[name=ID]').val(data.node.getIdx()); self.find(':input[name=ID]').val(data.node.getIdx());
self.trigger('submit'); self.trigger('submit');
}); });
// move submit button to the top // move submit button to the top
this.find('#ReportClass').after(this.find('.Actions')); this.find('#ReportClass').after(this.find('.Actions'));
// links in results // links in results
this.find('ul a').bind('click', function(e) { this.find('ul a').bind('click', function(e) {
var $link = $(this); var $link = $(this);
@ -188,18 +178,20 @@
); );
return false; return false;
}); });
},
_submit: function(e) { this._super();
},
onsubmit: function(e) {
var self = this; var self = this;
// dont process if no report is selected // dont process if no report is selected
var reportClass = this.find(':input[name=ReportClass]').val(); var reportClass = this.find(':input[name=ReportClass]').val();
if(!reportClass) return false; if(!reportClass) return false;
var button = this.find(':submit:first'); var button = this.find(':submit:first');
button.addClass('loading'); button.addClass('loading');
jQuery.ajax({ jQuery.ajax({
url: this.attr('action'), url: this.attr('action'),
data: this.serializeArray(), data: this.serializeArray(),
@ -212,60 +204,58 @@
button.removeClass('loading'); button.removeClass('loading');
} }
}); });
return false; return false;
} }
}; });
});
/** /**
* @class Simple form showing versions of a specific page. * @class Simple form showing versions of a specific page.
* @name ss.Form_VersionsForm * @name ss.Form_VersionsForm
* @requires ss.i18n * @requires ss.i18n
*/ */
$('#Form_VersionsForm').concrete(function($) { $('#Form_VersionsForm').concrete(/** @lends ss.Form_VersionsForm */{
return/** @lends ss.Form_VersionsForm */{
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this.bind('submit', function(e) {
return self._submit(e);
});
// set button to be available in form submit event later on // set button to be available in form submit event later on
this.find(':submit').bind('click', function(e) { this.find(':submit').bind('click', function(e) {
self.data('_clickedButton', this); self.data('_clickedButton', this);
}); });
this.bind('submit', function(e) {
return self._submit();
});
// integrate with sitetree selection changes // integrate with sitetree selection changes
jQuery('#sitetree').bind('selectionchanged', function(e, data) { jQuery('#sitetree').bind('selectionchanged', function(e, data) {
self.find(':input[name=ID]').val(data.node.getIdx()); self.find(':input[name=ID]').val(data.node.getIdx());
if(self.is(':visible')) self.trigger('submit'); if(self.is(':visible')) self.trigger('submit');
}); });
// refresh when field is selected // refresh when field is selected
// TODO coupling // TODO coupling
$('#treepanes').bind('accordionchange', function(e, ui) { $('#treepanes').bind('accordionchange', function(e, ui) {
if($(ui.newContent).attr('id') == 'Form_VersionsForm') self.trigger('submit'); if($(ui.newContent).attr('id') == 'Form_VersionsForm') self.trigger('submit');
}); });
// submit when 'show unpublished versions' checkbox is changed // submit when 'show unpublished versions' checkbox is changed
this.find(':input[name=ShowUnpublished]').bind('change', function(e) { this.find(':input[name=ShowUnpublished]').bind('change', function(e) {
// force the refresh button, not 'compare versions' // force the refresh button, not 'compare versions'
self.data('_clickedButton', self.find(':submit[name=action_versions]')); self.data('_clickedButton', self.find(':submit[name=action_versions]'));
self.trigger('submit'); self.trigger('submit');
}); });
// move submit button to the top // move submit button to the top
this.find('#ReportClass').after(this.find('.Actions')); this.find('#ReportClass').after(this.find('.Actions'));
// links in results // links in results
this.find('td').bind('click', function(e) { this.find('td').bind('click', function(e) {
var td = $(this); var td = $(this);
// exclude checkboxes // exclude checkboxes
if($(e.target).is(':input')) return true; if($(e.target).is(':input')) return true;
var link = $(this).siblings('.versionlink').find('a').attr('href'); var link = $(this).siblings('.versionlink').find('a').attr('href');
td.addClass('loading'); td.addClass('loading');
jQuery('#Form_EditForm').concrete('ss').loadForm( jQuery('#Form_EditForm').concrete('ss').loadForm(
@ -276,7 +266,7 @@
); );
return false; return false;
}); });
// compare versions action // compare versions action
this.find(':submit[name=action_compareversions]').bind('click', function(e) { this.find(':submit[name=action_compareversions]').bind('click', function(e) {
// validation: only allow selection of exactly two versions // validation: only allow selection of exactly two versions
@ -288,31 +278,33 @@
)); ));
return false; return false;
} }
// overloaded submission: refresh the right form instead // overloaded submission: refresh the right form instead
self.data('_clickedButton', this); self.data('_clickedButton', this);
self._submit(e, true); self._submit(true);
return false; return false;
}) });
this._super();
}, },
/** /**
* @param {boolean} loadEditForm Determines if responses should show in current panel, * @param {boolean} loadEditForm Determines if responses should show in current panel,
* or in the edit form (in the case of 'compare versions'). * or in the edit form (in the case of 'compare versions').
*/ */
_submit: function(e, loadEditForm) { _submit: function(loadEditForm) {
var self = this; var self = this;
// Don't submit with empty ID // Don't submit with empty ID
if(!this.find(':input[name=ID]').val()) return false; if(!this.find(':input[name=ID]').val()) return false;
var $button = (self.data('_clickedButton')) ? $(self.data('_clickedButton')) : this.find(':submit:first'); var $button = (self.data('_clickedButton')) ? $(self.data('_clickedButton')) : this.find(':submit:first');
$button.addClass('loading'); $button.addClass('loading');
var data = this.serializeArray(); var data = this.serializeArray();
data.push({name:$button.attr('name'), value: $button.val()}); data.push({name:$button.attr('name'), value: $button.val()});
if(loadEditForm) { if(loadEditForm) {
jQuery('#Form_EditForm').concrete('ss').loadForm( jQuery('#Form_EditForm').concrete('ss').loadForm(
this.attr('action'), this.attr('action'),
@ -335,9 +327,8 @@
}); });
} }
return false; return false;
} }
}; });
}); });
})(jQuery); })(jQuery);

View File

@ -1,60 +1,58 @@
(function($) { (function($) {
/** $.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. * @class Simple form with a page type dropdown
* @name ss.Form_AddForm * which creates a new page through #Form_EditForm and adds a new tree node.
* @requires ss.i18n * @name ss.Form_AddForm
* @requires ss.Form_EditForm * @requires ss.i18n
*/ * @requires ss.Form_EditForm
$('#Form_AddForm').concrete(function($) { */
return/** @lends ss.Form_AddForm */{ $('#Form_AddForm').concrete(/** @lends ss.Form_AddForm */{
/** /**
* @type DOMElement * @type DOMElement
*/ */
Tree: null, Tree: null,
/** /**
* @type Array Internal counter to create unique page identifiers prior to ajax saving * @type Array Internal counter to create unique page identifiers prior to ajax saving
*/ */
_NewPages: [], NewPages: [],
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this.bind('submit', function(e) {
return self._submit(e);
});
Observable.applyTo(this[0]); Observable.applyTo(this[0]);
var tree = jQuery('#sitetree')[0]; var tree = jQuery('#sitetree')[0];
this.setTree(tree); this.setTree(tree);
jQuery(tree).bind('selectionchanged', function(e, data) {self.treeSelectionChanged(e, data);}); jQuery(tree).bind('selectionchanged', function(e, data) {self.treeSelectionChanged(e, data);});
this.find(':input[name=PageType]').bind('change', this.typeDropdownChanged);
},
_submit: function(e) { this.find(':input[name=PageType]').bind('change', this.typeDropdownChanged);
var newPages = this._NewPages();
var tree = this.Tree(); this._super();
},
onsubmit: function(e) {
var newPages = this.getNewPages();
var tree = this.getTree();
var parentID = (tree.firstSelected()) ? tree.getIdxOf(tree.firstSelected()) : 0; var parentID = (tree.firstSelected()) ? tree.getIdxOf(tree.firstSelected()) : 0;
// TODO: Remove 'new-' code http://open.silverstripe.com/ticket/875 // TODO: Remove 'new-' code http://open.silverstripe.com/ticket/875
if(parentID && parentID.substr(0,3) == 'new') { if(parentID && parentID.substr(0,3) == 'new') {
alert(ss.i18n._t('CMSMAIN.WARNINGSAVEPAGESBEFOREADDING')); alert(ss.i18n._t('CMSMAIN.WARNINGSAVEPAGESBEFOREADDING'));
} }
if(tree.firstSelected() && jQuery(tree.firstSelected()).hasClass("nochildren")) { if(tree.firstSelected() && jQuery(tree.firstSelected()).hasClass("nochildren")) {
alert(ss.i18n._t('CMSMAIN.CANTADDCHILDREN') ); alert(ss.i18n._t('CMSMAIN.CANTADDCHILDREN') );
} }
// Optionally initalize the new pages tracker // Optionally initalize the new pages tracker
if(!newPages[parentID] ) newPages[parentID] = 1; if(!newPages[parentID] ) newPages[parentID] = 1;
// default to first button // default to first button
var button = jQuery(this).find(':submit:first'); var button = jQuery(this).find(':submit:first');
button.addClass('loading'); button.addClass('loading');
// collect data and submit the form // collect data and submit the form
var data = jQuery(this).serializeArray(); var data = jQuery(this).serializeArray();
data.push({name:'Suffix',value:newPages[parentID]++}); data.push({name:'Suffix',value:newPages[parentID]++});
@ -67,26 +65,26 @@
}, },
{type: 'POST', data: data} {type: 'POST', data: data}
); );
this.set_NewPages(newPages); this.setNewPages(newPages);
return false; return false;
}, },
treeSelectionChanged : function(e, data) { treeSelectionChanged : function(e, data) {
var selectedNode = data.node; var selectedNode = data.node;
if(selectedNode.hints && selectedNode.hints.defaultChild) { if(selectedNode.hints && selectedNode.hints.defaultChild) {
this.find(':input[name=PageType]').val(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); this.find(':input[name=ParentID]').val(parentID ? parentID : 0);
}, },
typeDropdownChanged : function() { typeDropdownChanged : function() {
var tree = this.Tree(); var tree = this.getTree();
// Don't do anything if we're already on an appropriate node // Don't do anything if we're already on an appropriate node
var sel = tree.firstSelected(); var sel = tree.firstSelected();
if(sel && sel.hints && sel.hints.allowedChildren) { if(sel && sel.hints && sel.hints.allowedChildren) {
@ -102,6 +100,6 @@
if(newNode) tree.changeCurrentTo(newNode); if(newNode) tree.changeCurrentTo(newNode);
} }
} }
}; });
}); });
}(jQuery)); }(jQuery));

View File

@ -1,69 +1,68 @@
(function($) { (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} * @type {DOMElement}
*/ */
Tree: null, Tree: null,
/** /**
* @type {Array} Stores all actions that can be performed on the collected IDs as * @type {Array} Stores all actions that can be performed on the collected IDs as
* function closures. This might trigger filtering of the selected IDs, * function closures. This might trigger filtering of the selected IDs,
* a confirmation message, etc. * a confirmation message, etc.
*/ */
Actions: [], Actions: [],
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this.setTree($('#sitetree')[0]); this.setTree($('#sitetree')[0]);
$(this.Tree()).bind('selectionchanged', function(e, data) { $(this.getTree()).bind('selectionchanged', function(e, data) {
self._treeSelectionChanged(data.node); self._treeSelectionChanged(data.node);
}); });
// if tab which contains this form is shown, make the tree selectable // if tab which contains this form is shown, make the tree selectable
$('#TreeActions').bind('tabsselect', function(e, ui) { $('#TreeActions').bind('tabsselect', function(e, ui) {
if($(ui.panel).attr('id') != 'TreeActions-batchactions') return; if($(ui.panel).attr('id') != 'TreeActions-batchactions') return;
// if the panel is visible (meaning about to be closed), // if the panel is visible (meaning about to be closed),
// disable tree selection and reset any values. Otherwise enable it. // disable tree selection and reset any values. Otherwise enable it.
if($(ui.panel).is(':visible')) { if($(ui.panel).is(':visible')) {
$(self.Tree()).removeClass('multiselect'); $(self.getTree()).removeClass('multiselect');
} else { } else {
self._multiselectTransform(); self._multiselectTransform();
} }
}); });
this.bind('submit', function(e) {return self._submit(e);}); this._super();
}, },
/** /**
* @param {String} type * @param {String} type
* @param {Function} callback * @param {Function} callback
*/ */
register: function(type, callback) { register: function(type, callback) {
this.trigger('register', {type: type, callback: callback}); this.trigger('register', {type: type, callback: callback});
var actions = this.getActions();
var actions = this.Actions();
actions[type] = callback; actions[type] = callback;
this.setActions(actions); this.setActions(actions);
}, },
/** /**
* Remove an existing action. * Remove an existing action.
* *
@ -71,12 +70,12 @@
*/ */
unregister: function(type) { unregister: function(type) {
this.trigger('unregister', {type: type}); this.trigger('unregister', {type: type});
var actions = this.Actions(); var actions = this.getActions();
if(actions[type]) delete actions[type]; if(actions[type]) delete actions[type];
this.setActions(actions); this.setActions(actions);
}, },
/** /**
* Determines if we should allow and track tree selections. * Determines if we should allow and track tree selections.
* *
@ -86,10 +85,10 @@
_isActive: function() { _isActive: function() {
return $('#TreeActions-batchactions').is(':visible'); return $('#TreeActions-batchactions').is(':visible');
}, },
_submit: function(e) { onsubmit: function(e) {
var ids = []; var ids = [];
var tree = this.Tree(); var tree = this.getTree();
// find all explicitly selected IDs // find all explicitly selected IDs
$(tree).find('li.selected').each(function() { $(tree).find('li.selected').each(function() {
ids.push(tree.getIdxOf(this)); ids.push(tree.getIdxOf(this));
@ -98,29 +97,27 @@
ids.push(tree.getIdxOf(this)); ids.push(tree.getIdxOf(this));
}); });
}); });
// if no nodes are selected, return with an error // if no nodes are selected, return with an error
if(!ids || !ids.length) { if(!ids || !ids.length) {
alert(ss.i18n._t('CMSMAIN.SELECTONEPAGE')); alert(ss.i18n._t('CMSMAIN.SELECTONEPAGE'));
return false; return false;
} }
// apply callback, which might modify the IDs // apply callback, which might modify the IDs
var type = this.find(':input[name=Action]').val(); 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 // if no IDs are selected, stop here. This is an implict way for the
// callback to cancel the actions // callback to cancel the actions
if(!ids || !ids.length) { if(!ids || !ids.length) return false;
return false;
}
// write IDs to the hidden field // write IDs to the hidden field
this.find(':input[name=csvIDs]').val(ids.join(',')); this.find(':input[name=csvIDs]').val(ids.join(','));
var button = this.find(':submit:first'); var button = this.find(':submit:first');
button.addClass('loading'); button.addClass('loading');
jQuery.ajax({ jQuery.ajax({
// don't use original form url // don't use original form url
url: type, url: type,
@ -128,7 +125,7 @@
data: this.serializeArray(), data: this.serializeArray(),
complete: function(xmlhttp, status) { complete: function(xmlhttp, status) {
button.removeClass('loading'); button.removeClass('loading');
// status message // status message
var msg = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText; var msg = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText;
statusMessage(msg, (status == 'success') ? 'good' : 'bad'); statusMessage(msg, (status == 'success') ? 'good' : 'bad');
@ -146,11 +143,11 @@
if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node); if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node);
} }
} }
// reset selection state // reset selection state
// TODO Should unselect all selected nodes as well // TODO Should unselect all selected nodes as well
jQuery(tree).removeClass('multiselect'); jQuery(tree).removeClass('multiselect');
// Check if current page still exists, and refresh it. // Check if current page still exists, and refresh it.
// Otherwise remove the current form // Otherwise remove the current form
var selectedNode = tree.firstSelected(); var selectedNode = tree.firstSelected();
@ -165,14 +162,14 @@
} else { } else {
$('#Form_EditForm').concrete('ss').removeForm(); $('#Form_EditForm').concrete('ss').removeForm();
} }
// close panel // close panel
// TODO Coupling with tabs // TODO Coupling with tabs
$('#TreeActions').tabs('select', -1); $('#TreeActions').tabs('select', -1);
}, },
dataType: 'json' dataType: 'json'
}); });
return false; return false;
}, },
@ -181,10 +178,10 @@
*/ */
_multiselectTransform : function() { _multiselectTransform : function() {
// make tree selectable // make tree selectable
jQuery(this.Tree()).addClass('multiselect'); jQuery(this.getTree()).addClass('multiselect');
// auto-select the current node // auto-select the current node
var node = this.Tree().firstSelected(); var node = this.getTree().firstSelected();
if(node){ if(node){
node.removeNodeClass('current'); node.removeNodeClass('current');
node.addNodeClass('selected'); node.addNodeClass('selected');
@ -197,7 +194,7 @@
}); });
} }
}, },
/** /**
* Only triggers if the field is considered 'active'. * Only triggers if the field is considered 'active'.
* @todo Most of this is basically simulating broken behaviour of the MultiselectTree mixin, * @todo Most of this is basically simulating broken behaviour of the MultiselectTree mixin,
@ -205,7 +202,7 @@
*/ */
_treeSelectionChanged: function(node) { _treeSelectionChanged: function(node) {
if(!this._isActive()) return; if(!this._isActive()) return;
if(node.selected) { if(node.selected) {
node.removeNodeClass('selected'); node.removeNodeClass('selected');
node.selected = false; node.selected = false;
@ -213,7 +210,7 @@
// Select node // Select node
node.addNodeClass('selected'); node.addNodeClass('selected');
node.selected = true; node.selected = true;
// Open node in order to allow proper selection of children // Open node in order to allow proper selection of children
if($(node).hasClass('unexpanded')) { if($(node).hasClass('unexpanded')) {
node.open(); node.open();
@ -226,7 +223,7 @@
}); });
} }
} }
}; });
}); });
$(document).ready(function() { $(document).ready(function() {

View File

@ -1,53 +1,48 @@
(function($) { (function($) {
$.concrete('ss', function($){
/** /**
* @class Base edit form, provides ajaxified saving * @class Base edit form, provides ajaxified saving
* and reloading itself through the ajax return values. * and reloading itself through the ajax return values.
* Takes care of resizing tabsets within the layout container. * Takes care of resizing tabsets within the layout container.
* @name ss.Form_EditForm * @name ss.Form_EditForm
* @require jquery.changetracker * @require jquery.changetracker
* *
* <h3>Events</h3> * <h3>Events</h3>
* - ajaxsubmit: Form is about to be submitted through ajax * - ajaxsubmit: Form is about to be submitted through ajax
* - validate: Contains validation result * - validate: Contains validation result
* - removeform: A form is about to be removed from the DOM * - removeform: A form is about to be removed from the DOM
* - load: Form is about to be loaded through ajax * - load: Form is about to be loaded through ajax
*/ */
$('#Form_EditForm').concrete('ss',function($){ $('#Form_EditForm').concrete(/** @lends ss.Form_EditForm */{
return/** @lends ss.Form_EditForm */{
/** /**
* @type String HTML text to show when no form content is chosen. * @type String HTML text to show when no form content is chosen.
* Will show inside the <form> tag. * Will show inside the <form> tag.
*/ */
PlaceholderHtml: '', PlaceholderHtml: '',
/** /**
* @type Object * @type Object
*/ */
ChangeTrackerOptions: {}, ChangeTrackerOptions: {},
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this._setupChangeTracker(); this._setupChangeTracker();
this.bind('submit', function(e) {
return self._submit(e);
});
// Can't bind this through jQuery // Can't bind this through jQuery
window.onbeforeunload = function(e) {return self._checkChangeTracker(false);}; window.onbeforeunload = function(e) {return self._checkChangeTracker(false);};
this._super(); this._super();
}, },
_setupChangeTracker: function() { _setupChangeTracker: function() {
// Don't bind any events here, as we dont replace the // Don't bind any events here, as we dont replace the
// full <form> tag by any ajax updates they won't automatically reapply // full <form> tag by any ajax updates they won't automatically reapply
this.changetracker(this.ChangeTrackerOptions()); this.changetracker(this.getChangeTrackerOptions());
}, },
/** /**
* Checks the jquery.changetracker plugin status for this form. * Checks the jquery.changetracker plugin status for this form.
* Usually bound to window.onbeforeunload. * Usually bound to window.onbeforeunload.
@ -58,10 +53,10 @@
*/ */
_checkChangeTracker: function(isUnloadEvent) { _checkChangeTracker: function(isUnloadEvent) {
var self = this; var self = this;
// @todo TinyMCE coupling // @todo TinyMCE coupling
if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave(); if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
// check for form changes // check for form changes
if(self.is('.changed')) { if(self.is('.changed')) {
// returned string will trigger a confirm() dialog, // returned string will trigger a confirm() dialog,
@ -73,17 +68,18 @@
} }
} }
}, },
/** /**
* Suppress submission unless it is handled through ajaxSubmit(). * Suppress submission unless it is handled through ajaxSubmit().
* *
* @param {Event} e * @param {Event} e
*/ */
_submit: function(e) { onsubmit: function(e) {
this.ajaxSubmit(); this.ajaxSubmit();
return false; return false;
}, },
/** /**
* @param {DOMElement} button The pressed button (optional) * @param {DOMElement} button The pressed button (optional)
* @param {Function} callback Called in complete() handler of jQuery.ajax() * @param {Function} callback Called in complete() handler of jQuery.ajax()
@ -92,20 +88,20 @@
*/ */
ajaxSubmit: function(button, callback, ajaxOptions, loadResponse) { ajaxSubmit: function(button, callback, ajaxOptions, loadResponse) {
var self = this; var self = this;
// look for save button // look for save button
if(!button) button = this.find('.Actions :submit[name=action_save]'); if(!button) button = this.find('.Actions :submit[name=action_save]');
// default to first button if none given - simulates browser behaviour // default to first button if none given - simulates browser behaviour
if(!button) button = this.find('.Actions :submit:first'); if(!button) button = this.find('.Actions :submit:first');
this.trigger('ajaxsubmit', {button: button}); this.trigger('ajaxsubmit', {button: button});
// set button to "submitting" state // set button to "submitting" state
$(button).addClass('loading'); $(button).addClass('loading');
// @todo TinyMCE coupling // @todo TinyMCE coupling
if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave(); if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
// validate if required // validate if required
if(!this.validate()) { if(!this.validate()) {
// TODO Automatically switch to the tab/position of the first error // TODO Automatically switch to the tab/position of the first error
@ -126,12 +122,12 @@
type: 'POST', type: 'POST',
complete: function(xmlhttp, status) { complete: function(xmlhttp, status) {
$(button).removeClass('loading'); $(button).removeClass('loading');
// TODO This should be using the plugin API // TODO This should be using the plugin API
self.removeClass('changed'); self.removeClass('changed');
if(callback) callback(xmlhttp, status); if(callback) callback(xmlhttp, status);
// pass along original form data to enable old/new comparisons // pass along original form data to enable old/new comparisons
if(loadResponse !== false) { if(loadResponse !== false) {
self._loadResponse(xmlhttp.responseText, status, xmlhttp, formData); self._loadResponse(xmlhttp.responseText, status, xmlhttp, formData);
@ -139,10 +135,10 @@
}, },
dataType: 'html' dataType: 'html'
}, ajaxOptions)); }, ajaxOptions));
return false; return false;
}, },
/** /**
* Hook in (optional) validation routines. * Hook in (optional) validation routines.
* Currently clientside validation is not supported out of the box in the CMS. * Currently clientside validation is not supported out of the box in the CMS.
@ -154,10 +150,10 @@
validate: function() { validate: function() {
var isValid = true; var isValid = true;
this.trigger('validate', {isValid: isValid}); this.trigger('validate', {isValid: isValid});
return isValid; return isValid;
}, },
/** /**
* @param {String} url * @param {String} url
* @param {Function} callback (Optional) Called after the form content as been loaded * @param {Function} callback (Optional) Called after the form content as been loaded
@ -168,12 +164,12 @@
// Alert when unsaved changes are present // Alert when unsaved changes are present
if(this._checkChangeTracker(true) == false) return false; if(this._checkChangeTracker(true) == false) return false;
// hide existing form - shown again through _loadResponse() // hide existing form - shown again through _loadResponse()
this.addClass('loading'); this.addClass('loading');
this.trigger('load', {url: url}); this.trigger('load', {url: url});
this.cleanup(); this.cleanup();
return jQuery.ajax(jQuery.extend({ return jQuery.ajax(jQuery.extend({
@ -183,7 +179,7 @@
self.removeClass('changed'); self.removeClass('changed');
self._loadResponse(xmlhttp.responseText, status, xmlhttp); self._loadResponse(xmlhttp.responseText, status, xmlhttp);
self.removeClass('loading'); self.removeClass('loading');
if(callback) callback.apply(self, arguments); if(callback) callback.apply(self, arguments);
@ -191,7 +187,7 @@
dataType: 'html' dataType: 'html'
}, ajaxOptions)); }, ajaxOptions));
}, },
/** /**
* Remove everying inside the <form> tag * Remove everying inside the <form> tag
* with a custom HTML fragment. Useful e.g. for deleting a page in the CMS. * with a custom HTML fragment. Useful e.g. for deleting a page in the CMS.
@ -201,19 +197,15 @@
* Falls back to the default RemoveText() option (Optional) * Falls back to the default RemoveText() option (Optional)
*/ */
removeForm: function(placeholderHtml) { removeForm: function(placeholderHtml) {
if(!placeholderHtml) placeholderHtml = this.PlaceholderHtml(); if(!placeholderHtml) placeholderHtml = this.getPlaceholderHtml();
// Alert when unsaved changes are present // Alert when unsaved changes are present
if(this._checkChangeTracker(true) == false) return false; if(this._checkChangeTracker(true) == false) return;
this.trigger('removeform'); this.trigger('removeform');
this.html(placeholderHtml); this.html(placeholderHtml);
// TODO This should be using the plugin API // TODO This should be using the plugin API
this.removeClass('changed'); this.removeClass('changed');
}, },
/** /**
* Remove all the currently active TinyMCE editors. * Remove all the currently active TinyMCE editors.
* Note: Everything that calls this externally has an inappropriate coupling to TinyMCE. * Note: Everything that calls this externally has an inappropriate coupling to TinyMCE.
@ -227,7 +219,7 @@
tinymce.EditorManager.editors = {}; tinymce.EditorManager.editors = {};
} }
}, },
/** /**
* @param {String} data Either HTML for straight insertion, or eval'ed JavaScript. * @param {String} data Either HTML for straight insertion, or eval'ed JavaScript.
* If passed as HTML, it is assumed that everying inside the <form> tag is replaced, * If passed as HTML, it is assumed that everying inside the <form> tag is replaced,
@ -241,7 +233,7 @@
_loadResponse: function(data, status, xmlhttp, origData) { _loadResponse: function(data, status, xmlhttp, origData) {
if(status == 'success') { if(status == 'success') {
this.cleanup(); this.cleanup();
var html = data; var html = data;
// Rewrite # links // Rewrite # links
@ -262,12 +254,12 @@
} else { } else {
this.removeForm(); this.removeForm();
} }
// @todo Coupling to avoid FOUC (concrete applies to late) // @todo Coupling to avoid FOUC (concrete applies to late)
this.find('.ss-tabset').tabs(); this.find('.ss-tabset').tabs();
this._setupChangeTracker();
this._setupChangeTracker();
// Optionally get the form attributes from embedded fields, see Form->formHtmlContent() // Optionally get the form attributes from embedded fields, see Form->formHtmlContent()
for(var overrideAttr in {'action':true,'method':true,'enctype':true,'name':true}) { for(var overrideAttr in {'action':true,'method':true,'enctype':true,'name':true}) {
var el = this.find(':input[name='+ '_form_' + overrideAttr + ']'); var el = this.find(':input[name='+ '_form_' + overrideAttr + ']');
@ -276,7 +268,7 @@
el.remove(); el.remove();
} }
} }
Behaviour.apply(); // refreshes ComplexTableField Behaviour.apply(); // refreshes ComplexTableField
// focus input on first form element // focus input on first form element
@ -294,45 +286,36 @@
statusMessage(_statusMessage, (xmlhttp.status >= 400) ? 'bad' : 'good'); statusMessage(_statusMessage, (xmlhttp.status >= 400) ? 'bad' : 'good');
} }
} }
}; });
});
/** /**
* @class All buttons in the right CMS form go through here by default. * @class All buttons in the right CMS form go through here by default.
* We need this onclick overloading because we can't get to the * We need this onclick overloading because we can't get to the
* clicked button from a form.onsubmit event. * clicked button from a form.onsubmit event.
* @name ss.Form_EditForm.Actions.submit * @name ss.Form_EditForm.Actions.submit
*/ */
$('#Form_EditForm .Actions :submit').concrete('ss', function($){ $('#Form_EditForm .Actions :submit').concrete(/** @lends ss.Form_EditForm.Actions.submit */{
return/** @lends ss.Form_EditForm.Actions.submit */{ onclick: function(e) {
onmatch: function() {
this.bind('click', this._onclick);
this._super();
},
_onclick: function() {
jQuery('#Form_EditForm').concrete('ss').ajaxSubmit(this); jQuery('#Form_EditForm').concrete('ss').ajaxSubmit(this);
return false; return false;
} }
}; });
});
/** /**
* @class Add tinymce to HtmlEditorFields within the CMS. * @class Add tinymce to HtmlEditorFields within the CMS.
* @name ss.Form_EditForm.textarea.htmleditor * @name ss.Form_EditForm.textarea.htmleditor
*/ */
$('#Form_EditForm textarea.htmleditor').concrete('ss', function($){ $('#Form_EditForm textarea.htmleditor').concrete(/** @lends ss.Form_EditForm.Actions.submit */{
return/** @lends ss.Form_EditForm.Actions.submit */{
onmatch : function() { onmatch : function() {
tinyMCE.execCommand("mceAddControl", true, this.attr('id')); tinyMCE.execCommand("mceAddControl", true, this.attr('id'));
this.isChanged = function() { this.isChanged = function() {
return tinyMCE.getInstanceById(this.attr('id')).isDirty(); return tinyMCE.getInstanceById(this.attr('id')).isDirty();
} };
this.resetChanged = function() { this.resetChanged = function() {
var inst = tinyMCE.getInstanceById(this.attr('id')); var inst = tinyMCE.getInstanceById(this.attr('id'));
if (inst) inst.startContent = tinymce.trim(inst.getContent({format : 'raw', no_events : 1})); if (inst) inst.startContent = tinymce.trim(inst.getContent({format : 'raw', no_events : 1}));
} };
} }
}; });
}); });
}(jQuery)); }(jQuery));

View File

@ -5,59 +5,58 @@
var ss_MainLayout; var ss_MainLayout;
(function($) { (function($) {
$.concrete('ss', function($){
// setup jquery.concrete // setup jquery.concrete
$.concrete.warningLevel = $.concrete.WARN_LEVEL_BESTPRACTISE; $.concrete.warningLevel = $.concrete.WARN_LEVEL_BESTPRACTISE;
// global ajax error handlers // global ajax error handlers
$.ajaxSetup({ $.ajaxSetup({
error: function(xmlhttp, status, error) { error: function(xmlhttp, status, error) {
var msg = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText; var msg = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText;
statusMessage(msg, 'bad'); statusMessage(msg, 'bad');
} }
}); });
/** /**
* Available Custom Events: * Available Custom Events:
* <ul> * <ul>
* <li>ajaxsubmit</li> * <li>ajaxsubmit</li>
* <li>validate</li> * <li>validate</li>
* <li>loadnewpage</li> * <li>loadnewpage</li>
* *
* @class Main LeftAndMain interface with some control * @class Main LeftAndMain interface with some control
* panel and an edit form. * panel and an edit form.
* @name ss.LeftAndMain * @name ss.LeftAndMain
*/ */
$('.LeftAndMain').concrete('ss', function($){ $('.LeftAndMain').concrete(/** @lends ss.EditMemberProfile */{
return/** @lends ss.EditMemberProfile */ {
/** /**
* Reference to jQuery.layout element * Reference to jQuery.layout element
* @type Object * @type Object
*/ */
MainLayout: null, MainLayout: null,
/** /**
* @type Number Interval in which /Security/ping will be checked for a valid login session. * @type Number Interval in which /Security/ping will be checked for a valid login session.
*/ */
PingIntervalSeconds: 5*60, PingIntervalSeconds: 5*60,
onmatch: function() { onmatch: function() {
var self = this; var self = this;
// Remove loading screen // Remove loading screen
$('.ss-loading-screen').hide(); $('.ss-loading-screen').hide();
$('body').removeClass('stillLoading'); $('body').removeClass('stillLoading');
// Layout // Layout
ss_MainLayout = this._setupLayout(); ss_MainLayout = this._setupLayout();
this.setMainLayout(ss_MainLayout); this.setMainLayout(ss_MainLayout);
layoutState.options.keys = "west.size,west.isClosed"; layoutState.options.keys = "west.size,west.isClosed";
$(window).unload(function(){ layoutState.save('ss_MainLayout');}); $(window).unload(function(){ layoutState.save('ss_MainLayout');});
this._setupPinging(); this._setupPinging();
this._resizeChildren(); this._resizeChildren();
// HACK Delay resizing to give jquery-ui tabs a change their dimensions // HACK Delay resizing to give jquery-ui tabs a change their dimensions
// through dynamically added css classes // through dynamically added css classes
$(window).resize(function () { $(window).resize(function () {
@ -67,10 +66,10 @@ var ss_MainLayout;
self._resizeChildren(); self._resizeChildren();
}, 200); }, 200);
}); });
// If tab has no nested tabs, set overflow to auto // If tab has no nested tabs, set overflow to auto
$(this).find('.tab').not(':has(.tab)').css('overflow', 'auto'); $(this).find('.tab').not(':has(.tab)').css('overflow', 'auto');
// @todo Doesn't resize properly if the response doesn't contain a tabset (see above) // @todo Doesn't resize properly if the response doesn't contain a tabset (see above)
$('#Form_EditForm').bind('loadnewpage', function() { $('#Form_EditForm').bind('loadnewpage', function() {
// HACK Delay resizing to give jquery-ui tabs a change their dimensions // HACK Delay resizing to give jquery-ui tabs a change their dimensions
@ -81,10 +80,10 @@ var ss_MainLayout;
self._resizeChildren(); self._resizeChildren();
}, 200); }, 200);
}); });
this._super(); this._super();
}, },
/** /**
* Initialize jQuery layout manager with the following panes: * Initialize jQuery layout manager with the following panes:
* - east: Tree, Page Version History, Site Reports * - east: Tree, Page Version History, Site Reports
@ -95,10 +94,10 @@ var ss_MainLayout;
*/ */
_setupLayout: function() { _setupLayout: function() {
var self = this; var self = this;
var widthEast = this.find('.ui-layout-east').width(); var widthEast = this.find('.ui-layout-east').width();
var widthWest = this.find('.ui-layout-west').width(); var widthWest = this.find('.ui-layout-west').width();
// layout containing the tree, CMS menu, the main form etc. // layout containing the tree, CMS menu, the main form etc.
var savedLayoutSettings = layoutState.load('ss_MainLayout'); var savedLayoutSettings = layoutState.load('ss_MainLayout');
@ -139,14 +138,14 @@ var ss_MainLayout;
center: {} center: {}
}, savedLayoutSettings); }, savedLayoutSettings);
var layout = $('body').layout(layoutSettings); var layout = $('body').layout(layoutSettings);
// Adjust tree accordion etc. in left panel to work correctly // Adjust tree accordion etc. in left panel to work correctly
// with jQuery.layout (see http://layout.jquery-dev.net/tips.html#Widget_Accordion) // with jQuery.layout (see http://layout.jquery-dev.net/tips.html#Widget_Accordion)
this.find("#treepanes").accordion({ this.find("#treepanes").accordion({
fillSpace: true, fillSpace: true,
animated: false animated: false
}); });
return layout; return layout;
}, },
@ -166,7 +165,7 @@ var ss_MainLayout;
} }
} }
}; };
// setup pinging for login expiry // setup pinging for login expiry
setInterval(function() { setInterval(function() {
jQuery.ajax({ jQuery.ajax({
@ -174,12 +173,13 @@ var ss_MainLayout;
global: false, global: false,
complete: onSessionLost complete: onSessionLost
}); });
}, this.PingIntervalSeconds() * 1000); }, this.getPingIntervalSeconds() * 1000);
}, },
/** /**
* Resize elements in center panel * Resize elements in center panel
* to fit the boundary box provided by the layout manager * to fit the boundary box provided by the layout manager.
* TODO Replace with automated less ugly parent/sibling traversal
*/ */
_resizeChildren: function() { _resizeChildren: function() {
$("#treepanes", this).accordion("resize"); $("#treepanes", this).accordion("resize");
@ -196,18 +196,16 @@ var ss_MainLayout;
$('#Form_EditForm fieldset > .ss-tabset > .tab > .ss-tabset', this).fitHeightToParent(); $('#Form_EditForm fieldset > .ss-tabset > .tab > .ss-tabset', this).fitHeightToParent();
$('#Form_EditForm fieldset > .ss-tabset > .tab > .ss-tabset > .tab', this).fitHeightToParent(); $('#Form_EditForm fieldset > .ss-tabset > .tab > .ss-tabset > .tab', this).fitHeightToParent();
} }
}; });
});
/**
/** * @class Make all buttons "hoverable" with jQuery theming.
* @class Make all buttons "hoverable" with jQuery theming. * Also sets the clicked button on a form submission, making it available through
* Also sets the clicked button on a form submission, making it available through * a new 'clickedButton' property on the form DOM element.
* a new 'clickedButton' property on the form DOM element. *
* * @name ss.LeftAndMain.Buttons
* @name ss.LeftAndMain.Buttons */
*/ $('.LeftAndMain :submit, .LeftAndMain button, .LeftAndMain :reset').concrete(/** @lends ss.LeftAndMain.Buttons */{
$('.LeftAndMain :submit, .LeftAndMain button, .LeftAndMain :reset').concrete('ss', function($){
return/** @lends ss.LeftAndMain.Buttons */{
onmatch: function() { onmatch: function() {
this.addClass( this.addClass(
'ui-state-default ' + 'ui-state-default ' +
@ -235,19 +233,16 @@ var ss_MainLayout;
// have fired on the form // have fired on the form
setTimeout(function() {form.clickedButton = null;}, 10); setTimeout(function() {form.clickedButton = null;}, 10);
}); });
this._super(); this._super();
} }
}; });
});
/**
/** * @class Container for tree actions like "create", "search", etc.
* @class Container for tree actions like "create", "search", etc. * @name ss.TreeActions
* @name ss.TreeActions */
*/ $('#TreeActions').concrete(/** @lends ss.TreeActions */{
$('#TreeActions').concrete('ss', function($){
return/** @lends ss.TreeActions */{
/** /**
* Setup "create", "search", "batch actions" layers above tree. * Setup "create", "search", "batch actions" layers above tree.
* All tab contents are closed by default. * All tab contents are closed by default.
@ -259,22 +254,19 @@ var ss_MainLayout;
cookie: { expires: 30, path: '/', name: 'ui-tabs-TreeActions' } cookie: { expires: 30, path: '/', name: 'ui-tabs-TreeActions' }
}); });
} }
}; });
});
/**
/** * @class Link for editing the profile for a logged-in member
* @class Link for editing the profile for a logged-in member * through a modal dialog.
* through a modal dialog. * @name ss.EditMemberProfile
* @name ss.EditMemberProfile */
*/ $('a#EditMemberProfile').concrete(/** @lends ss.EditMemberProfile */{
$('a#EditMemberProfile').concrete('ss', function($){
return/** @lends ss.EditMemberProfile */{
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this.bind('click', function(e) {return self._openPopup();}); this.bind('click', function(e) {return self._openPopup();});
$('body').append( $('body').append(
'<div id="ss-ui-dialog">' '<div id="ss-ui-dialog">'
+ '<iframe id="ss-ui-dialog-iframe" ' + '<iframe id="ss-ui-dialog-iframe" '
@ -282,7 +274,7 @@ var ss_MainLayout;
+ '</iframe>' + '</iframe>'
+ '</div>' + '</div>'
); );
var cookieVal = (jQuery.cookie) ? JSON.parse(jQuery.cookie('ss-ui-dialog')) : false; var cookieVal = (jQuery.cookie) ? JSON.parse(jQuery.cookie('ss-ui-dialog')) : false;
$("#ss-ui-dialog").dialog(jQuery.extend({ $("#ss-ui-dialog").dialog(jQuery.extend({
autoOpen: false, autoOpen: false,
@ -301,18 +293,18 @@ var ss_MainLayout;
// TODO i18n // TODO i18n
title: 'Edit Profile' title: 'Edit Profile'
}, cookieVal)).css('overflow', 'hidden'); }, cookieVal)).css('overflow', 'hidden');
$('#ss-ui-dialog-iframe').bind('load', function(e) {self._resize();}); $('#ss-ui-dialog-iframe').bind('load', function(e) {self._resize();});
}, },
_openPopup: function(e) { _openPopup: function(e) {
$('#ss-ui-dialog-iframe').attr('src', this.attr('href')); $('#ss-ui-dialog-iframe').attr('src', this.attr('href'));
$("#ss-ui-dialog").dialog('open'); $("#ss-ui-dialog").dialog('open');
return false; return false;
}, },
_resize: function() { _resize: function() {
var iframe = $('#ss-ui-dialog-iframe'); var iframe = $('#ss-ui-dialog-iframe');
var container = $('#ss-ui-dialog'); var container = $('#ss-ui-dialog');
@ -327,13 +319,13 @@ var ss_MainLayout;
- parseFloat(container.css('paddingTop')) - parseFloat(container.css('paddingTop'))
- parseFloat(container.css('paddingBottom')) - parseFloat(container.css('paddingBottom'))
); );
this._saveState(); this._saveState();
}, },
_saveState: function() { _saveState: function() {
var container = $('#ss-ui-dialog'); var container = $('#ss-ui-dialog');
// save size in cookie (optional) // save size in cookie (optional)
if(jQuery.cookie && container.width() && container.height()) { if(jQuery.cookie && container.width() && container.height()) {
jQuery.cookie( jQuery.cookie(
@ -350,60 +342,55 @@ var ss_MainLayout;
); );
} }
} }
}; });
});
/**
/** * @class Links for viewing the currently loaded page
* @class Links for viewing the currently loaded page * in different modes: 'live', 'stage' or 'archived'.
* in different modes: 'live', 'stage' or 'archived'. * Automatically updates on loading a new page.
* Automatically updates on loading a new page. * @name ss.switchViewLinks
* @name ss.switchViewLinks * @requires jquery.metadata
* @requires jquery.metadata */
*/ $('#switchView a').concrete(/** @lends ss.switchViewLinks */{
$('#switchView a').concrete('ss', function($){
return/** @lends ss.switchViewLinks */{
/** /**
* @type DOMElement * @type DOMElement
*/ */
Form: null, Form: null,
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this.setForm($('#Form_EditForm')); this.setForm($('#Form_EditForm'));
jQuery('#Form_EditForm').bind('loadnewpage delete', function(e) {self.refresh();}); jQuery('#Form_EditForm').bind('loadnewpage delete', function(e) {self.refresh();});
self.refresh(); self.refresh();
}, },
/** /**
* Parse new links based on the underlying form URLSegment, * Parse new links based on the underlying form URLSegment,
* preserving the ?stage URL parameters if necessary. * preserving the ?stage URL parameters if necessary.
*/ */
refresh: function() { refresh: function() {
// TODO Compatible with nested urls? // TODO Compatible with nested urls?
var urlSegment = this.Form().find(':input[name=URLSegment]').val(); var urlSegment = this.getForm().find(':input[name=URLSegment]').val();
if(urlSegment) { if(urlSegment) {
var locale = this.Form().find(':input[name=Locale]').val(); var locale = this.getForm().find(':input[name=Locale]').val();
var url = urlSegment; var url = urlSegment;
if(this.metadata().params) url += '?' + this.metadata().params; if(this.metadata().params) url += '?' + this.metadata().params;
if(locale) url += ((url.indexOf('?') > 0) ? '&' : '?') + "locale=" + locale; if(locale) url += ((url.indexOf('?') > 0) ? '&' : '?') + "locale=" + locale;
this.attr('href', url); this.attr('href', url);
} }
// hide fields if no URLSegment is present // hide fields if no URLSegment is present
this.toggle((urlSegment)); this.toggle((urlSegment));
}, },
onclick: function(e) { onclick: function(e) {
// Open in popup // Open in popup
window.open($(e.target).attr('href')); window.open($(e.target).attr('href'));
return false; return false;
} }
}; });
}); });
}(jQuery)); }(jQuery));
// Backwards compatibility // Backwards compatibility

View File

@ -1,37 +1,34 @@
(function($) { (function($) {
$.concrete('ss', function($){
/** /**
* A simple ajax browser history implementation tailored towards * A simple ajax browser history implementation tailored towards
* navigating through search results and different forms loaded into * navigating through search results and different forms loaded into
* the ModelAdmin right panels. The logic listens to search and form loading * the ModelAdmin right panels. The logic listens to search and form loading
* events, keeps track of the loaded URLs, and will display graphical back/forward * events, keeps track of the loaded URLs, and will display graphical back/forward
* buttons where appropriate. A search action will cause the history to be reset. * buttons where appropriate. A search action will cause the history to be reset.
* *
* Note: The logic does not replay save operations or hook into any form actions. * Note: The logic does not replay save operations or hook into any form actions.
* *
* Available Events: * Available Events:
* - historyAdd * - historyAdd
* - historyStart * - historyStart
* - historyGoFoward * - historyGoFoward
* - historyGoBack * - historyGoBack
* *
* @todo Switch tab state when re-displaying search forms * @todo Switch tab state when re-displaying search forms
* @todo Reload search parameters into forms * @todo Reload search parameters into forms
* *
* @name ss.ModelAdmin * @name ss.ModelAdmin
*/ */
$('.ModelAdmin').concrete('ss', function($){ $('.ModelAdmin').concrete(/** @lends ss.ModelAdmin */ {
return/** @lends ss.ModelAdmin */ {
History: [], History: [],
Future: [], Future: [],
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this._super(); this._super();
// generate markup // generate markup
this.find('#right').prepend( this.find('#right').prepend(
'<div class="historyNav">' '<div class="historyNav">'
@ -39,7 +36,7 @@
+ '<a href="#" class="forward">' + ss.i18n._t('ModelAdmin.HISTORYFORWARD', 'forward') + ' &gt;</a>' + '<a href="#" class="forward">' + ss.i18n._t('ModelAdmin.HISTORYFORWARD', 'forward') + ' &gt;</a>'
+ '</div>' + '</div>'
).find('.back,.forward').hide(); ).find('.back,.forward').hide();
this.find('.historyNav .back').live('click', function() { this.find('.historyNav .back').live('click', function() {
self.goBack(); self.goBack();
return false; return false;
@ -50,15 +47,15 @@
return false; return false;
}); });
}, },
redraw: function() { redraw: function() {
this.find('.historyNav .forward').toggle(Boolean(this.Future().length > 0)); this.find('.historyNav .forward').toggle(Boolean(this.getFuture().length > 0));
this.find('.historyNav .back').toggle(Boolean(this.History().length > 1)); this.find('.historyNav .back').toggle(Boolean(this.getHistory().length > 1));
}, },
startHistory: function(url, data) { startHistory: function(url, data) {
this.trigger('historyStart', {url: url, data: data}); this.trigger('historyStart', {url: url, data: data});
this.setHistory([]); this.setHistory([]);
this.addHistory(url, data); this.addHistory(url, data);
}, },
@ -68,89 +65,82 @@
*/ */
addHistory: function(url, data) { addHistory: function(url, data) {
this.trigger('historyAdd', {url: url, data: data}); this.trigger('historyAdd', {url: url, data: data});
// Combine data into URL // Combine data into URL
if(data) { if(data) {
if(url.indexOf('?') == -1) url += '?' + $.param(data); if(url.indexOf('?') == -1) url += '?' + $.param(data);
else url += '&' + $.param(data); else url += '&' + $.param(data);
} }
// Add to history // Add to history
this.History().push(url); this.getHistory().push(url);
// Reset future // Reset future
this.setFuture([]); this.setFuture([]);
this.redraw(); this.redraw();
}, },
goBack: function() { goBack: function() {
if(this.History() && this.History().length) { if(this.getHistory() && this.getHistory().length) {
if(this.Future() == null) this.setFuture([]); if(this.getFuture() == null) this.setFuture([]);
var currentPage = this.History().pop(); var currentPage = this.getHistory().pop();
var previousPage = this.History()[this.History().length-1]; var previousPage = this.getHistory()[this.getHistory().length-1];
this.Future().push(currentPage); this.getFuture().push(currentPage);
this.trigger('historyGoBack', {url:previousPage}); this.trigger('historyGoBack', {url:previousPage});
// load new location // load new location
$('#Form_EditForm').concrete('ss').loadForm(previousPage); $('#Form_EditForm').loadForm(previousPage);
this.redraw(); this.redraw();
} }
}, },
goForward: function() { goForward: function() {
if(this.Future() && this.Future().length) { if(this.getFuture() && this.getFuture().length) {
if(this.Future() == null) this.setFuture([]); if(this.getFuture() == null) this.setFuture([]);
var nextPage = this.Future().pop(); var nextPage = this.getFuture().pop();
this.History().push(nextPage); this.getHistory().push(nextPage);
this.trigger('historyGoForward', {url:nextPage}); this.trigger('historyGoForward', {url:nextPage});
// load new location // load new location
$('#Form_EditForm').concrete('ss').loadForm(nextPage); $('#Form_EditForm').loadForm(nextPage);
this.redraw(); this.redraw();
} }
} }
}; });
});
/** /**
* A search action will cause the history to be reset. * A search action will cause the history to be reset.
*/ */
$('#SearchForm_holder form').concrete('ss', function($) { $('#SearchForm_holder form').concrete({
return{
onmatch: function() { onmatch: function() {
var self = this; var self = this;
this.bind('beforeSubmit', function(e) { this.bind('beforeSubmit', function(e) {
$('.ModelAdmin').concrete('ss').startHistory( $('.ModelAdmin').startHistory(
self.attr('action'), self.attr('action'),
self.serializeArray() self.serializeArray()
); );
}); });
this._super();
} }
}; });
});
/** /**
* We have to apply this to the result table buttons instead of the * We have to apply this to the result table buttons instead of the
* more generic form loading. * more generic form loading.
*/ */
$('form[name=Form_ResultsForm] tbody td a').concrete('ss', function($) { $('form[name=Form_ResultsForm] tbody td a').concrete({
return{ onclick: function(e) {
onmatch: function() { $('.ModelAdmin').addHistory(this.attr('href'));
var self = this;
this.bind('click', function(e) {
$('.ModelAdmin').addHistory(self.attr('href'));
});
} }
}; });
});
});
})(jQuery); })(jQuery);

View File

@ -9,152 +9,148 @@
* @todo alias the $ function instead of literal jQuery * @todo alias the $ function instead of literal jQuery
*/ */
(function($) { (function($) {
$.concrete('ss', function($){
//////////////////////////////////////////////////////////////////
// Search form //////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////// // Search form
//////////////////////////////////////////////////////////////////
/** /**
* If a dropdown is used to choose between the classes, it is handled by this code * If a dropdown is used to choose between the classes, it is handled by this code
*/ */
$('#ModelClassSelector select').concrete({ $('#ModelClassSelector select').concrete({
onmatch: function() { onmatch: function() {
var self = this; // Initialise the form by calling this onchange event straight away
// Set up an onchange function to show the applicable form and hide all others this.change();
this.bind('change', function(e) {
self.find('option').each(function() { this._super();
var $form = $('#'+$(this).val()); },
if(self.val() == $(this).val()) $form.show();
/**
* Set up an onchange function to show the applicable form and hide all others
*/
onchange: function(e) {
this.find('option').each(function() {
var $form = $('#'+this.val());
if(this.val() == this.val()) $form.show();
else $form.hide(); else $form.hide();
}); });
}); }
});
// Initialise the form by calling this onchange event straight away /**
this.change(); * Submits a search filter query and attaches event handlers
} * to the response table, excluding the import form because
}); * file ($_FILES) submission doesn't work using AJAX
/** *
* Submits a search filter query and attaches event handlers * Note: This is used for Form_CreateForm and all Form_SearchForm_* variations
* to the response table, excluding the import form because */
* file ($_FILES) submission doesn't work using AJAX $('#SearchForm_holder form').concrete({
* onsubmit: function(e) {
* Note: This is used for Form_CreateForm and all Form_SearchForm_* variations
*/
$('#SearchForm_holder form').concrete({
onmatch: function() {
var self = this;
this.bind('submit', function(e) {
// Import forms are processed without ajax // Import forms are processed without ajax
if(self.is('#Form_ImportForm')) return true; if(this.is('#Form_ImportForm')) return true;
self.trigger('beforeSubmit'); this.trigger('beforeSubmit');
var btn = $(self[0].clickedButton); var btn = $(this[0].clickedButton);
btn.addClass('loading'); btn.addClass('loading');
$('#Form_EditForm').concrete('ss').loadForm( $('#Form_EditForm').loadForm(
self.attr('action'), this.attr('action'),
function() { function() {
btn.removeClass('loading'); btn.removeClass('loading');
}, },
{data: self.serialize()} {data: this.serialize()}
); );
return false; return false;
}); }
} });
});
/** /**
* Column selection in search form * Column selection in search form
*/ */
$('a.form_frontend_function.toggle_result_assembly').concrete({ $('a.form_frontend_function.toggle_result_assembly').concrete({
onclick: function(e) { onclick: function(e) {
var toggleElement = $(this).next(); var toggleElement = $(this).next();
toggleElement.toggle(); toggleElement.toggle();
return false;
}
});
$('a.form_frontend_function.tick_all_result_assembly').concrete({
onclick: function(e) {
var resultAssembly = $(this).prevAll('div#ResultAssembly').find('ul li input');
resultAssembly.attr('checked', 'checked');
return false;
}
});
$('a.form_frontend_function.untick_all_result_assembly').concrete({
onclick: function(e) {
var resultAssembly = $(this).prevAll('div#ResultAssembly').find('ul li input');
resultAssembly.removeAttr('checked');
return false;
}
});
/**
* Table record handler for search result record
*/
$('.resultsTable tbody td').concrete({
onmatch: function() {
// TODO Replace with concrete event handler
this.bind('click', function(e) {
var firstLink = $(this).find('a[href]');
if(!firstLink) return;
$('#Form_EditForm').concrete('ss').loadForm(firstLink.attr('href'));
return false; return false;
}); }
} });
});
$('a.form_frontend_function.tick_all_result_assembly').concrete({
onclick: function(e) {
var resultAssembly = $(this).prevAll('div#ResultAssembly').find('ul li input');
resultAssembly.attr('checked', 'checked');
return false;
}
});
$('a.form_frontend_function.untick_all_result_assembly').concrete({
onclick: function(e) {
var resultAssembly = $(this).prevAll('div#ResultAssembly').find('ul li input');
resultAssembly.removeAttr('checked');
return false;
}
});
/** /**
* Add object button * Table record handler for search result record
*/ */
$('#Form_ManagedModelsSelect').concrete({ $('.resultsTable tbody td').concrete({
onmatch: function() { onclick: function(e) {
this.bind('submit', function(){ var firstLink = this.find('a[href]');
if(!firstLink) return;
$('#Form_EditForm').loadForm(firstLink.attr('href'));
return false;
}
});
/**
* Add object button
*/
$('#Form_ManagedModelsSelect').concrete({
onsubmit: function(e) {
className = $('select option:selected', this).val(); className = $('select option:selected', this).val();
requestPath = $(this).attr('action').replace('ManagedModelsSelect', className + '/add'); requestPath = this.attr('action').replace('ManagedModelsSelect', className + '/add');
var $button = $(':submit', this); var $button = $(':submit', this);
$('#Form_EditForm').concrete('ss').loadForm( $('#Form_EditForm').loadForm(
requestPath, requestPath,
function() { function() {
$button.removeClass('loading'); $button.removeClass('loading');
$button = null; $button = null;
} }
); );
return false; return false;
}); }
} });
});
/** /**
* RHS panel Delete button * RHS panel Delete button
*/ */
$('#Form_EditForm input[name=action_doDelete]').concrete({ $('#Form_EditForm input[name=action_doDelete]').concrete({
onmatch: function() { onclick: function(e) {
this.bind('click', function() { if(!confirm(ss.i18n._t('ModelAdmin.REALLYDELETE', 'Really delete?'))) {
var confirmed = confirm(ss.i18n._t('ModelAdmin.REALLYDELETE', 'Really delete?')); this.removeClass('loading');
if(!confirmed) {
$(this).removeClass('loading');
return false; return false;
} }
}); }
} });
});
/** /**
* Toggle import specifications * Toggle import specifications
*/ */
$('.importSpec').concrete({ $('.importSpec').concrete({
onmatch: function() { onmatch: function() {
this.hide(); this.hide();
this.find('a.detailsLink').click(function() { this.find('a.detailsLink').click(function() {
$('#' + $(this).attr('href').replace(/.*#/,'')).toggle(); $('#' + $(this).attr('href').replace(/.*#/,'')).toggle();
return false; return false;
}); });
}
this._super();
}
});
}); });
})(jQuery); })(jQuery);

View File

@ -1,15 +1,17 @@
jQuery(function($) { (function($) {
/** $.concrete('ss', function($){
* @class Tree panel. /**
* @name ss.sitetree * @class Tree panel.
*/ * @name ss.sitetree
$('#sitetree').concrete('ss', function($){ */
return/** @lends ss.sitetree */{ $('#sitetree').concrete(/** @lends ss.sitetree */{
onmatch: function() { onmatch: function() {
// make sure current ID of loaded form is actually selected in tree // make sure current ID of loaded form is actually selected in tree
var id = $('#Form_EditForm :input[name=ID]').val(); var id = $('#Form_EditForm :input[name=ID]').val();
if (id) this[0].setCurrentByIdx(id); if (id) this[0].setCurrentByIdx(id);
this._super();
} }
}; });
}); });
}); }(jQuery));