mirror of
https://github.com/silverstripe/silverstripe-reports
synced 2024-10-22 11:05:53 +02:00
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:
parent
1036329e86
commit
4d60aa5c83
@ -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));
|
@ -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));
|
@ -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));
|
@ -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('<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
|
||||
this.find('.field').each(function() {
|
||||
$('<option />').appendTo(self.SelectEl())
|
||||
$('<option />').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);
|
@ -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));
|
@ -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() {
|
||||
|
@ -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
|
||||
*
|
||||
* <h3>Events</h3>
|
||||
* - ajaxsubmit: Form is about to be submitted through ajax
|
||||
* - validate: Contains validation result
|
||||
* - removeform: A form is about to be removed from the DOM
|
||||
* - load: Form is about to be loaded through ajax
|
||||
*/
|
||||
$('#Form_EditForm').concrete('ss',function($){
|
||||
return/** @lends ss.Form_EditForm */{
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
* <h3>Events</h3>
|
||||
* - ajaxsubmit: Form is about to be submitted through ajax
|
||||
* - validate: Contains validation result
|
||||
* - removeform: A form is about to be removed from the DOM
|
||||
* - load: Form is about to be loaded through ajax
|
||||
*/
|
||||
$('#Form_EditForm').concrete(/** @lends ss.Form_EditForm */{
|
||||
/**
|
||||
* @type String HTML text to show when no form content is chosen.
|
||||
* Will show inside the <form> tag.
|
||||
*/
|
||||
PlaceholderHtml: '',
|
||||
|
||||
|
||||
/**
|
||||
* @type Object
|
||||
*/
|
||||
ChangeTrackerOptions: {},
|
||||
|
||||
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
|
||||
|
||||
this._setupChangeTracker();
|
||||
|
||||
this.bind('submit', function(e) {
|
||||
return self._submit(e);
|
||||
});
|
||||
|
||||
// Can't bind this through jQuery
|
||||
window.onbeforeunload = function(e) {return self._checkChangeTracker(false);};
|
||||
|
||||
|
||||
this._super();
|
||||
},
|
||||
|
||||
|
||||
_setupChangeTracker: function() {
|
||||
// Don't bind any events here, as we dont replace the
|
||||
// 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.
|
||||
* Usually bound to window.onbeforeunload.
|
||||
@ -58,10 +53,10 @@
|
||||
*/
|
||||
_checkChangeTracker: function(isUnloadEvent) {
|
||||
var self = this;
|
||||
|
||||
|
||||
// @todo TinyMCE coupling
|
||||
if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
|
||||
|
||||
|
||||
// check for form changes
|
||||
if(self.is('.changed')) {
|
||||
// returned string will trigger a confirm() dialog,
|
||||
@ -73,17 +68,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Suppress submission unless it is handled through ajaxSubmit().
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
_submit: function(e) {
|
||||
onsubmit: function(e) {
|
||||
this.ajaxSubmit();
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @param {DOMElement} button The pressed button (optional)
|
||||
* @param {Function} callback Called in complete() handler of jQuery.ajax()
|
||||
@ -92,20 +88,20 @@
|
||||
*/
|
||||
ajaxSubmit: function(button, callback, ajaxOptions, loadResponse) {
|
||||
var self = this;
|
||||
|
||||
|
||||
// look for save button
|
||||
if(!button) button = this.find('.Actions :submit[name=action_save]');
|
||||
// default to first button if none given - simulates browser behaviour
|
||||
if(!button) button = this.find('.Actions :submit:first');
|
||||
|
||||
|
||||
this.trigger('ajaxsubmit', {button: button});
|
||||
|
||||
|
||||
// set button to "submitting" state
|
||||
$(button).addClass('loading');
|
||||
|
||||
|
||||
// @todo TinyMCE coupling
|
||||
if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
|
||||
|
||||
|
||||
// validate if required
|
||||
if(!this.validate()) {
|
||||
// TODO Automatically switch to the tab/position of the first error
|
||||
@ -126,12 +122,12 @@
|
||||
type: 'POST',
|
||||
complete: function(xmlhttp, status) {
|
||||
$(button).removeClass('loading');
|
||||
|
||||
|
||||
// TODO This should be using the plugin API
|
||||
self.removeClass('changed');
|
||||
|
||||
|
||||
if(callback) callback(xmlhttp, status);
|
||||
|
||||
|
||||
// pass along original form data to enable old/new comparisons
|
||||
if(loadResponse !== false) {
|
||||
self._loadResponse(xmlhttp.responseText, status, xmlhttp, formData);
|
||||
@ -139,10 +135,10 @@
|
||||
},
|
||||
dataType: 'html'
|
||||
}, ajaxOptions));
|
||||
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Hook in (optional) validation routines.
|
||||
* Currently clientside validation is not supported out of the box in the CMS.
|
||||
@ -154,10 +150,10 @@
|
||||
validate: function() {
|
||||
var isValid = true;
|
||||
this.trigger('validate', {isValid: isValid});
|
||||
|
||||
|
||||
return isValid;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @param {String} url
|
||||
* @param {Function} callback (Optional) Called after the form content as been loaded
|
||||
@ -168,12 +164,12 @@
|
||||
|
||||
// Alert when unsaved changes are present
|
||||
if(this._checkChangeTracker(true) == false) return false;
|
||||
|
||||
|
||||
// hide existing form - shown again through _loadResponse()
|
||||
this.addClass('loading');
|
||||
|
||||
this.trigger('load', {url: url});
|
||||
|
||||
|
||||
this.cleanup();
|
||||
|
||||
return jQuery.ajax(jQuery.extend({
|
||||
@ -183,7 +179,7 @@
|
||||
self.removeClass('changed');
|
||||
|
||||
self._loadResponse(xmlhttp.responseText, status, xmlhttp);
|
||||
|
||||
|
||||
self.removeClass('loading');
|
||||
|
||||
if(callback) callback.apply(self, arguments);
|
||||
@ -191,7 +187,7 @@
|
||||
dataType: 'html'
|
||||
}, ajaxOptions));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove everying inside the <form> tag
|
||||
* 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)
|
||||
*/
|
||||
removeForm: function(placeholderHtml) {
|
||||
if(!placeholderHtml) placeholderHtml = this.PlaceholderHtml();
|
||||
|
||||
if(!placeholderHtml) placeholderHtml = this.getPlaceholderHtml();
|
||||
// Alert when unsaved changes are present
|
||||
if(this._checkChangeTracker(true) == false) return false;
|
||||
|
||||
if(this._checkChangeTracker(true) == false) return;
|
||||
this.trigger('removeform');
|
||||
|
||||
this.html(placeholderHtml);
|
||||
|
||||
// TODO This should be using the plugin API
|
||||
this.removeClass('changed');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove all the currently active TinyMCE editors.
|
||||
* Note: Everything that calls this externally has an inappropriate coupling to TinyMCE.
|
||||
@ -227,7 +219,7 @@
|
||||
tinymce.EditorManager.editors = {};
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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,
|
||||
@ -241,7 +233,7 @@
|
||||
_loadResponse: function(data, status, xmlhttp, origData) {
|
||||
if(status == 'success') {
|
||||
this.cleanup();
|
||||
|
||||
|
||||
var html = data;
|
||||
|
||||
// Rewrite # links
|
||||
@ -262,12 +254,12 @@
|
||||
} else {
|
||||
this.removeForm();
|
||||
}
|
||||
|
||||
|
||||
// @todo Coupling to avoid FOUC (concrete applies to late)
|
||||
this.find('.ss-tabset').tabs();
|
||||
|
||||
this._setupChangeTracker();
|
||||
|
||||
this._setupChangeTracker();
|
||||
|
||||
// Optionally get the form attributes from embedded fields, see Form->formHtmlContent()
|
||||
for(var overrideAttr in {'action':true,'method':true,'enctype':true,'name':true}) {
|
||||
var el = this.find(':input[name='+ '_form_' + overrideAttr + ']');
|
||||
@ -276,7 +268,7 @@
|
||||
el.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Behaviour.apply(); // refreshes ComplexTableField
|
||||
|
||||
// focus input on first form element
|
||||
@ -294,45 +286,36 @@
|
||||
statusMessage(_statusMessage, (xmlhttp.status >= 400) ? 'bad' : 'good');
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @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
|
||||
* clicked button from a form.onsubmit event.
|
||||
* @name ss.Form_EditForm.Actions.submit
|
||||
*/
|
||||
$('#Form_EditForm .Actions :submit').concrete('ss', function($){
|
||||
return/** @lends ss.Form_EditForm.Actions.submit */{
|
||||
onmatch: function() {
|
||||
this.bind('click', this._onclick);
|
||||
|
||||
this._super();
|
||||
},
|
||||
_onclick: function() {
|
||||
/**
|
||||
* @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
|
||||
* clicked button from a form.onsubmit event.
|
||||
* @name ss.Form_EditForm.Actions.submit
|
||||
*/
|
||||
$('#Form_EditForm .Actions :submit').concrete(/** @lends ss.Form_EditForm.Actions.submit */{
|
||||
onclick: function(e) {
|
||||
jQuery('#Form_EditForm').concrete('ss').ajaxSubmit(this);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Add tinymce to HtmlEditorFields within the CMS.
|
||||
* @name ss.Form_EditForm.textarea.htmleditor
|
||||
*/
|
||||
$('#Form_EditForm textarea.htmleditor').concrete('ss', function($){
|
||||
return/** @lends ss.Form_EditForm.Actions.submit */{
|
||||
/**
|
||||
* @class Add tinymce to HtmlEditorFields within the CMS.
|
||||
* @name ss.Form_EditForm.textarea.htmleditor
|
||||
*/
|
||||
$('#Form_EditForm textarea.htmleditor').concrete(/** @lends ss.Form_EditForm.Actions.submit */{
|
||||
onmatch : function() {
|
||||
tinyMCE.execCommand("mceAddControl", true, this.attr('id'));
|
||||
this.isChanged = function() {
|
||||
return tinyMCE.getInstanceById(this.attr('id')).isDirty();
|
||||
}
|
||||
};
|
||||
this.resetChanged = function() {
|
||||
var inst = tinyMCE.getInstanceById(this.attr('id'));
|
||||
if (inst) inst.startContent = tinymce.trim(inst.getContent({format : 'raw', no_events : 1}));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
}(jQuery));
|
@ -5,59 +5,58 @@
|
||||
var ss_MainLayout;
|
||||
|
||||
(function($) {
|
||||
$.concrete('ss', function($){
|
||||
|
||||
// setup jquery.concrete
|
||||
$.concrete.warningLevel = $.concrete.WARN_LEVEL_BESTPRACTISE;
|
||||
// setup jquery.concrete
|
||||
$.concrete.warningLevel = $.concrete.WARN_LEVEL_BESTPRACTISE;
|
||||
|
||||
// global ajax error handlers
|
||||
$.ajaxSetup({
|
||||
error: function(xmlhttp, status, error) {
|
||||
var msg = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText;
|
||||
statusMessage(msg, 'bad');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Available Custom Events:
|
||||
* <ul>
|
||||
* <li>ajaxsubmit</li>
|
||||
* <li>validate</li>
|
||||
* <li>loadnewpage</li>
|
||||
*
|
||||
* @class Main LeftAndMain interface with some control
|
||||
* panel and an edit form.
|
||||
* @name ss.LeftAndMain
|
||||
*/
|
||||
$('.LeftAndMain').concrete('ss', function($){
|
||||
return/** @lends ss.EditMemberProfile */ {
|
||||
|
||||
// global ajax error handlers
|
||||
$.ajaxSetup({
|
||||
error: function(xmlhttp, status, error) {
|
||||
var msg = (xmlhttp.getResponseHeader('X-Status')) ? xmlhttp.getResponseHeader('X-Status') : xmlhttp.statusText;
|
||||
statusMessage(msg, 'bad');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Available Custom Events:
|
||||
* <ul>
|
||||
* <li>ajaxsubmit</li>
|
||||
* <li>validate</li>
|
||||
* <li>loadnewpage</li>
|
||||
*
|
||||
* @class Main LeftAndMain interface with some control
|
||||
* panel and an edit form.
|
||||
* @name ss.LeftAndMain
|
||||
*/
|
||||
$('.LeftAndMain').concrete(/** @lends ss.EditMemberProfile */{
|
||||
/**
|
||||
* Reference to jQuery.layout element
|
||||
* @type Object
|
||||
*/
|
||||
MainLayout: null,
|
||||
|
||||
|
||||
/**
|
||||
* @type Number Interval in which /Security/ping will be checked for a valid login session.
|
||||
*/
|
||||
PingIntervalSeconds: 5*60,
|
||||
|
||||
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
|
||||
|
||||
// Remove loading screen
|
||||
$('.ss-loading-screen').hide();
|
||||
$('body').removeClass('stillLoading');
|
||||
|
||||
|
||||
// Layout
|
||||
ss_MainLayout = this._setupLayout();
|
||||
this.setMainLayout(ss_MainLayout);
|
||||
layoutState.options.keys = "west.size,west.isClosed";
|
||||
$(window).unload(function(){ layoutState.save('ss_MainLayout');});
|
||||
|
||||
|
||||
this._setupPinging();
|
||||
this._resizeChildren();
|
||||
|
||||
|
||||
// HACK Delay resizing to give jquery-ui tabs a change their dimensions
|
||||
// through dynamically added css classes
|
||||
$(window).resize(function () {
|
||||
@ -67,10 +66,10 @@ var ss_MainLayout;
|
||||
self._resizeChildren();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
|
||||
// If tab has no nested tabs, set overflow to 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)
|
||||
$('#Form_EditForm').bind('loadnewpage', function() {
|
||||
// HACK Delay resizing to give jquery-ui tabs a change their dimensions
|
||||
@ -81,10 +80,10 @@ var ss_MainLayout;
|
||||
self._resizeChildren();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
|
||||
this._super();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Initialize jQuery layout manager with the following panes:
|
||||
* - east: Tree, Page Version History, Site Reports
|
||||
@ -95,10 +94,10 @@ var ss_MainLayout;
|
||||
*/
|
||||
_setupLayout: function() {
|
||||
var self = this;
|
||||
|
||||
|
||||
var widthEast = this.find('.ui-layout-east').width();
|
||||
var widthWest = this.find('.ui-layout-west').width();
|
||||
|
||||
|
||||
// layout containing the tree, CMS menu, the main form etc.
|
||||
var savedLayoutSettings = layoutState.load('ss_MainLayout');
|
||||
|
||||
@ -139,14 +138,14 @@ var ss_MainLayout;
|
||||
center: {}
|
||||
}, savedLayoutSettings);
|
||||
var layout = $('body').layout(layoutSettings);
|
||||
|
||||
|
||||
// Adjust tree accordion etc. in left panel to work correctly
|
||||
// with jQuery.layout (see http://layout.jquery-dev.net/tips.html#Widget_Accordion)
|
||||
this.find("#treepanes").accordion({
|
||||
fillSpace: true,
|
||||
animated: false
|
||||
});
|
||||
|
||||
|
||||
return layout;
|
||||
},
|
||||
|
||||
@ -166,7 +165,7 @@ var ss_MainLayout;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// setup pinging for login expiry
|
||||
setInterval(function() {
|
||||
jQuery.ajax({
|
||||
@ -174,12 +173,13 @@ var ss_MainLayout;
|
||||
global: false,
|
||||
complete: onSessionLost
|
||||
});
|
||||
}, this.PingIntervalSeconds() * 1000);
|
||||
}, this.getPingIntervalSeconds() * 1000);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
$("#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 > .tab', this).fitHeightToParent();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Make all buttons "hoverable" with jQuery theming.
|
||||
* Also sets the clicked button on a form submission, making it available through
|
||||
* a new 'clickedButton' property on the form DOM element.
|
||||
*
|
||||
* @name ss.LeftAndMain.Buttons
|
||||
*/
|
||||
$('.LeftAndMain :submit, .LeftAndMain button, .LeftAndMain :reset').concrete('ss', function($){
|
||||
return/** @lends ss.LeftAndMain.Buttons */{
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Make all buttons "hoverable" with jQuery theming.
|
||||
* Also sets the clicked button on a form submission, making it available through
|
||||
* a new 'clickedButton' property on the form DOM element.
|
||||
*
|
||||
* @name ss.LeftAndMain.Buttons
|
||||
*/
|
||||
$('.LeftAndMain :submit, .LeftAndMain button, .LeftAndMain :reset').concrete(/** @lends ss.LeftAndMain.Buttons */{
|
||||
onmatch: function() {
|
||||
this.addClass(
|
||||
'ui-state-default ' +
|
||||
@ -235,19 +233,16 @@ var ss_MainLayout;
|
||||
// have fired on the form
|
||||
setTimeout(function() {form.clickedButton = null;}, 10);
|
||||
});
|
||||
|
||||
|
||||
this._super();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Container for tree actions like "create", "search", etc.
|
||||
* @name ss.TreeActions
|
||||
*/
|
||||
$('#TreeActions').concrete('ss', function($){
|
||||
return/** @lends ss.TreeActions */{
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Container for tree actions like "create", "search", etc.
|
||||
* @name ss.TreeActions
|
||||
*/
|
||||
$('#TreeActions').concrete(/** @lends ss.TreeActions */{
|
||||
/**
|
||||
* Setup "create", "search", "batch actions" layers above tree.
|
||||
* All tab contents are closed by default.
|
||||
@ -259,22 +254,19 @@ var ss_MainLayout;
|
||||
cookie: { expires: 30, path: '/', name: 'ui-tabs-TreeActions' }
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Link for editing the profile for a logged-in member
|
||||
* through a modal dialog.
|
||||
* @name ss.EditMemberProfile
|
||||
*/
|
||||
$('a#EditMemberProfile').concrete('ss', function($){
|
||||
return/** @lends ss.EditMemberProfile */{
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Link for editing the profile for a logged-in member
|
||||
* through a modal dialog.
|
||||
* @name ss.EditMemberProfile
|
||||
*/
|
||||
$('a#EditMemberProfile').concrete(/** @lends ss.EditMemberProfile */{
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
|
||||
|
||||
this.bind('click', function(e) {return self._openPopup();});
|
||||
|
||||
|
||||
$('body').append(
|
||||
'<div id="ss-ui-dialog">'
|
||||
+ '<iframe id="ss-ui-dialog-iframe" '
|
||||
@ -282,7 +274,7 @@ var ss_MainLayout;
|
||||
+ '</iframe>'
|
||||
+ '</div>'
|
||||
);
|
||||
|
||||
|
||||
var cookieVal = (jQuery.cookie) ? JSON.parse(jQuery.cookie('ss-ui-dialog')) : false;
|
||||
$("#ss-ui-dialog").dialog(jQuery.extend({
|
||||
autoOpen: false,
|
||||
@ -301,18 +293,18 @@ var ss_MainLayout;
|
||||
// TODO i18n
|
||||
title: 'Edit Profile'
|
||||
}, cookieVal)).css('overflow', 'hidden');
|
||||
|
||||
|
||||
$('#ss-ui-dialog-iframe').bind('load', function(e) {self._resize();});
|
||||
},
|
||||
|
||||
|
||||
_openPopup: function(e) {
|
||||
$('#ss-ui-dialog-iframe').attr('src', this.attr('href'));
|
||||
|
||||
|
||||
$("#ss-ui-dialog").dialog('open');
|
||||
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
_resize: function() {
|
||||
var iframe = $('#ss-ui-dialog-iframe');
|
||||
var container = $('#ss-ui-dialog');
|
||||
@ -327,13 +319,13 @@ var ss_MainLayout;
|
||||
- parseFloat(container.css('paddingTop'))
|
||||
- parseFloat(container.css('paddingBottom'))
|
||||
);
|
||||
|
||||
|
||||
this._saveState();
|
||||
},
|
||||
|
||||
|
||||
_saveState: function() {
|
||||
var container = $('#ss-ui-dialog');
|
||||
|
||||
|
||||
// save size in cookie (optional)
|
||||
if(jQuery.cookie && container.width() && container.height()) {
|
||||
jQuery.cookie(
|
||||
@ -350,60 +342,55 @@ var ss_MainLayout;
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Links for viewing the currently loaded page
|
||||
* in different modes: 'live', 'stage' or 'archived'.
|
||||
* Automatically updates on loading a new page.
|
||||
* @name ss.switchViewLinks
|
||||
* @requires jquery.metadata
|
||||
*/
|
||||
$('#switchView a').concrete('ss', function($){
|
||||
|
||||
return/** @lends ss.switchViewLinks */{
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* @class Links for viewing the currently loaded page
|
||||
* in different modes: 'live', 'stage' or 'archived'.
|
||||
* Automatically updates on loading a new page.
|
||||
* @name ss.switchViewLinks
|
||||
* @requires jquery.metadata
|
||||
*/
|
||||
$('#switchView a').concrete(/** @lends ss.switchViewLinks */{
|
||||
/**
|
||||
* @type DOMElement
|
||||
*/
|
||||
Form: null,
|
||||
|
||||
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
this.setForm($('#Form_EditForm'));
|
||||
|
||||
|
||||
jQuery('#Form_EditForm').bind('loadnewpage delete', function(e) {self.refresh();});
|
||||
self.refresh();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse new links based on the underlying form URLSegment,
|
||||
* preserving the ?stage URL parameters if necessary.
|
||||
*/
|
||||
refresh: function() {
|
||||
// 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) {
|
||||
var locale = this.Form().find(':input[name=Locale]').val();
|
||||
var locale = this.getForm().find(':input[name=Locale]').val();
|
||||
var url = urlSegment;
|
||||
if(this.metadata().params) url += '?' + this.metadata().params;
|
||||
if(locale) url += ((url.indexOf('?') > 0) ? '&' : '?') + "locale=" + locale;
|
||||
this.attr('href', url);
|
||||
}
|
||||
|
||||
|
||||
// hide fields if no URLSegment is present
|
||||
this.toggle((urlSegment));
|
||||
},
|
||||
|
||||
|
||||
onclick: function(e) {
|
||||
// Open in popup
|
||||
window.open($(e.target).attr('href'));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
}(jQuery));
|
||||
|
||||
// Backwards compatibility
|
||||
|
@ -1,37 +1,34 @@
|
||||
(function($) {
|
||||
|
||||
/**
|
||||
* A simple ajax browser history implementation tailored towards
|
||||
* navigating through search results and different forms loaded into
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* Available Events:
|
||||
* - historyAdd
|
||||
* - historyStart
|
||||
* - historyGoFoward
|
||||
* - historyGoBack
|
||||
*
|
||||
* @todo Switch tab state when re-displaying search forms
|
||||
* @todo Reload search parameters into forms
|
||||
*
|
||||
* @name ss.ModelAdmin
|
||||
*/
|
||||
$('.ModelAdmin').concrete('ss', function($){
|
||||
return/** @lends ss.ModelAdmin */ {
|
||||
|
||||
$.concrete('ss', function($){
|
||||
/**
|
||||
* A simple ajax browser history implementation tailored towards
|
||||
* navigating through search results and different forms loaded into
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* Available Events:
|
||||
* - historyAdd
|
||||
* - historyStart
|
||||
* - historyGoFoward
|
||||
* - historyGoBack
|
||||
*
|
||||
* @todo Switch tab state when re-displaying search forms
|
||||
* @todo Reload search parameters into forms
|
||||
*
|
||||
* @name ss.ModelAdmin
|
||||
*/
|
||||
$('.ModelAdmin').concrete(/** @lends ss.ModelAdmin */ {
|
||||
History: [],
|
||||
|
||||
Future: [],
|
||||
|
||||
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
|
||||
|
||||
this._super();
|
||||
|
||||
|
||||
// generate markup
|
||||
this.find('#right').prepend(
|
||||
'<div class="historyNav">'
|
||||
@ -39,7 +36,7 @@
|
||||
+ '<a href="#" class="forward">' + ss.i18n._t('ModelAdmin.HISTORYFORWARD', 'forward') + ' ></a>'
|
||||
+ '</div>'
|
||||
).find('.back,.forward').hide();
|
||||
|
||||
|
||||
this.find('.historyNav .back').live('click', function() {
|
||||
self.goBack();
|
||||
return false;
|
||||
@ -50,15 +47,15 @@
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
redraw: function() {
|
||||
this.find('.historyNav .forward').toggle(Boolean(this.Future().length > 0));
|
||||
this.find('.historyNav .back').toggle(Boolean(this.History().length > 1));
|
||||
this.find('.historyNav .forward').toggle(Boolean(this.getFuture().length > 0));
|
||||
this.find('.historyNav .back').toggle(Boolean(this.getHistory().length > 1));
|
||||
},
|
||||
|
||||
|
||||
startHistory: function(url, data) {
|
||||
this.trigger('historyStart', {url: url, data: data});
|
||||
|
||||
|
||||
this.setHistory([]);
|
||||
this.addHistory(url, data);
|
||||
},
|
||||
@ -68,89 +65,82 @@
|
||||
*/
|
||||
addHistory: function(url, data) {
|
||||
this.trigger('historyAdd', {url: url, data: data});
|
||||
|
||||
|
||||
// Combine data into URL
|
||||
if(data) {
|
||||
if(url.indexOf('?') == -1) url += '?' + $.param(data);
|
||||
else url += '&' + $.param(data);
|
||||
}
|
||||
|
||||
// Add to history
|
||||
this.History().push(url);
|
||||
|
||||
this.getHistory().push(url);
|
||||
// Reset future
|
||||
this.setFuture([]);
|
||||
|
||||
|
||||
this.redraw();
|
||||
},
|
||||
|
||||
goBack: function() {
|
||||
if(this.History() && this.History().length) {
|
||||
if(this.Future() == null) this.setFuture([]);
|
||||
if(this.getHistory() && this.getHistory().length) {
|
||||
if(this.getFuture() == null) this.setFuture([]);
|
||||
|
||||
var currentPage = this.History().pop();
|
||||
var previousPage = this.History()[this.History().length-1];
|
||||
var currentPage = this.getHistory().pop();
|
||||
var previousPage = this.getHistory()[this.getHistory().length-1];
|
||||
|
||||
this.Future().push(currentPage);
|
||||
|
||||
this.getFuture().push(currentPage);
|
||||
|
||||
this.trigger('historyGoBack', {url:previousPage});
|
||||
|
||||
|
||||
// load new location
|
||||
$('#Form_EditForm').concrete('ss').loadForm(previousPage);
|
||||
|
||||
$('#Form_EditForm').loadForm(previousPage);
|
||||
|
||||
this.redraw();
|
||||
}
|
||||
},
|
||||
|
||||
goForward: function() {
|
||||
if(this.Future() && this.Future().length) {
|
||||
if(this.Future() == null) this.setFuture([]);
|
||||
if(this.getFuture() && this.getFuture().length) {
|
||||
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});
|
||||
|
||||
|
||||
// load new location
|
||||
$('#Form_EditForm').concrete('ss').loadForm(nextPage);
|
||||
|
||||
$('#Form_EditForm').loadForm(nextPage);
|
||||
|
||||
this.redraw();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* A search action will cause the history to be reset.
|
||||
*/
|
||||
$('#SearchForm_holder form').concrete('ss', function($) {
|
||||
return{
|
||||
/**
|
||||
* A search action will cause the history to be reset.
|
||||
*/
|
||||
$('#SearchForm_holder form').concrete({
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
this.bind('beforeSubmit', function(e) {
|
||||
$('.ModelAdmin').concrete('ss').startHistory(
|
||||
$('.ModelAdmin').startHistory(
|
||||
self.attr('action'),
|
||||
self.serializeArray()
|
||||
);
|
||||
});
|
||||
|
||||
this._super();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* We have to apply this to the result table buttons instead of the
|
||||
* more generic form loading.
|
||||
*/
|
||||
$('form[name=Form_ResultsForm] tbody td a').concrete('ss', function($) {
|
||||
return{
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
this.bind('click', function(e) {
|
||||
$('.ModelAdmin').addHistory(self.attr('href'));
|
||||
});
|
||||
/**
|
||||
* We have to apply this to the result table buttons instead of the
|
||||
* more generic form loading.
|
||||
*/
|
||||
$('form[name=Form_ResultsForm] tbody td a').concrete({
|
||||
onclick: function(e) {
|
||||
$('.ModelAdmin').addHistory(this.attr('href'));
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
})(jQuery);
|
@ -9,152 +9,148 @@
|
||||
* @todo alias the $ function instead of literal jQuery
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Search form
|
||||
//////////////////////////////////////////////////////////////////
|
||||
$.concrete('ss', function($){
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Search form
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* If a dropdown is used to choose between the classes, it is handled by this code
|
||||
*/
|
||||
$('#ModelClassSelector select').concrete({
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
// Set up an onchange function to show the applicable form and hide all others
|
||||
this.bind('change', function(e) {
|
||||
self.find('option').each(function() {
|
||||
var $form = $('#'+$(this).val());
|
||||
if(self.val() == $(this).val()) $form.show();
|
||||
/**
|
||||
* If a dropdown is used to choose between the classes, it is handled by this code
|
||||
*/
|
||||
$('#ModelClassSelector select').concrete({
|
||||
onmatch: function() {
|
||||
// Initialise the form by calling this onchange event straight away
|
||||
this.change();
|
||||
|
||||
this._super();
|
||||
},
|
||||
|
||||
/**
|
||||
* 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();
|
||||
});
|
||||
});
|
||||
|
||||
// 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
|
||||
*
|
||||
* 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) {
|
||||
}
|
||||
});
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Note: This is used for Form_CreateForm and all Form_SearchForm_* variations
|
||||
*/
|
||||
$('#SearchForm_holder form').concrete({
|
||||
onsubmit: function(e) {
|
||||
// Import forms are processed without ajax
|
||||
if(self.is('#Form_ImportForm')) return true;
|
||||
|
||||
self.trigger('beforeSubmit');
|
||||
if(this.is('#Form_ImportForm')) return true;
|
||||
|
||||
this.trigger('beforeSubmit');
|
||||
|
||||
var btn = $(self[0].clickedButton);
|
||||
var btn = $(this[0].clickedButton);
|
||||
btn.addClass('loading');
|
||||
|
||||
$('#Form_EditForm').concrete('ss').loadForm(
|
||||
self.attr('action'),
|
||||
$('#Form_EditForm').loadForm(
|
||||
this.attr('action'),
|
||||
function() {
|
||||
btn.removeClass('loading');
|
||||
},
|
||||
{data: self.serialize()}
|
||||
{data: this.serialize()}
|
||||
);
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Column selection in search form
|
||||
*/
|
||||
$('a.form_frontend_function.toggle_result_assembly').concrete({
|
||||
onclick: function(e) {
|
||||
var toggleElement = $(this).next();
|
||||
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'));
|
||||
/**
|
||||
* Column selection in search form
|
||||
*/
|
||||
$('a.form_frontend_function.toggle_result_assembly').concrete({
|
||||
onclick: function(e) {
|
||||
var toggleElement = $(this).next();
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Add object button
|
||||
*/
|
||||
$('#Form_ManagedModelsSelect').concrete({
|
||||
onmatch: function() {
|
||||
this.bind('submit', function(){
|
||||
/**
|
||||
* Table record handler for search result record
|
||||
*/
|
||||
$('.resultsTable tbody td').concrete({
|
||||
onclick: function(e) {
|
||||
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();
|
||||
requestPath = $(this).attr('action').replace('ManagedModelsSelect', className + '/add');
|
||||
requestPath = this.attr('action').replace('ManagedModelsSelect', className + '/add');
|
||||
var $button = $(':submit', this);
|
||||
$('#Form_EditForm').concrete('ss').loadForm(
|
||||
$('#Form_EditForm').loadForm(
|
||||
requestPath,
|
||||
function() {
|
||||
$button.removeClass('loading');
|
||||
$button = null;
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* RHS panel Delete button
|
||||
*/
|
||||
$('#Form_EditForm input[name=action_doDelete]').concrete({
|
||||
onmatch: function() {
|
||||
this.bind('click', function() {
|
||||
var confirmed = confirm(ss.i18n._t('ModelAdmin.REALLYDELETE', 'Really delete?'));
|
||||
if(!confirmed) {
|
||||
$(this).removeClass('loading');
|
||||
/**
|
||||
* RHS panel Delete button
|
||||
*/
|
||||
$('#Form_EditForm input[name=action_doDelete]').concrete({
|
||||
onclick: function(e) {
|
||||
if(!confirm(ss.i18n._t('ModelAdmin.REALLYDELETE', 'Really delete?'))) {
|
||||
this.removeClass('loading');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Toggle import specifications
|
||||
*/
|
||||
$('.importSpec').concrete({
|
||||
onmatch: function() {
|
||||
this.hide();
|
||||
this.find('a.detailsLink').click(function() {
|
||||
$('#' + $(this).attr('href').replace(/.*#/,'')).toggle();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Toggle import specifications
|
||||
*/
|
||||
$('.importSpec').concrete({
|
||||
onmatch: function() {
|
||||
this.hide();
|
||||
this.find('a.detailsLink').click(function() {
|
||||
$('#' + $(this).attr('href').replace(/.*#/,'')).toggle();
|
||||
return false;
|
||||
});
|
||||
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
@ -1,15 +1,17 @@
|
||||
jQuery(function($) {
|
||||
/**
|
||||
* @class Tree panel.
|
||||
* @name ss.sitetree
|
||||
*/
|
||||
$('#sitetree').concrete('ss', function($){
|
||||
return/** @lends ss.sitetree */{
|
||||
(function($) {
|
||||
$.concrete('ss', function($){
|
||||
/**
|
||||
* @class Tree panel.
|
||||
* @name ss.sitetree
|
||||
*/
|
||||
$('#sitetree').concrete(/** @lends ss.sitetree */{
|
||||
onmatch: function() {
|
||||
// make sure current ID of loaded form is actually selected in tree
|
||||
var id = $('#Form_EditForm :input[name=ID]').val();
|
||||
if (id) this[0].setCurrentByIdx(id);
|
||||
|
||||
this._super();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
}(jQuery));
|
Loading…
Reference in New Issue
Block a user