mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
41aec54e88
Regression caused by a security fix in 9bf3ae9a190
444 lines
13 KiB
JavaScript
Executable File
444 lines
13 KiB
JavaScript
Executable File
|
|
CMSForm = Class.extend('ChangeTracker').extend('Observable');
|
|
CMSForm.prototype = {
|
|
initialize : function(fn) {
|
|
this.ChangeTracker.initialize();
|
|
this.formName = fn;
|
|
this.prepareForm();
|
|
},
|
|
|
|
/**
|
|
* Trigger normal save event, helpful e.g. when enter key is pressed in
|
|
* single line input fields.
|
|
*/
|
|
onsubmit: function(e) {
|
|
this.save();
|
|
|
|
Event.stop(e);
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Processing called whenever a page is loaded in the right - including the initial one
|
|
*/
|
|
prepareForm : function() {
|
|
ajaxActionsAtTop(this.id, 'form_actions_' + this.formName, this.formName);
|
|
|
|
// Update the nav items down the bottom
|
|
if($('SwitchView') && $('AjaxSwitchView')) {
|
|
$('SwitchView').innerHTML = $('AjaxSwitchView').innerHTML;
|
|
$('AjaxSwitchView').innerHTML = '';
|
|
Behaviour.apply('SwitchView'); // This is needed so calendar still works
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Load actions from a string containing the HTML content
|
|
*/
|
|
loadActionsFromString : function(actionHTML) {
|
|
var actionHolder = $('form_actions_' + this.formName);
|
|
actionHolder.innerHTML = actionHTML;
|
|
prepareAjaxActions(actionHolder, this.id, this.formName);
|
|
},
|
|
|
|
/**
|
|
* Close the form down without any corrective action, after its been deleted.
|
|
*/
|
|
closeIfSetTo: function(id) {
|
|
if(this.elements.ID && this.elements.ID.value == id) {
|
|
// Note: TinyMCE coupling
|
|
tinymce_removeAll();
|
|
this.innerHTML = "<p>" + ss.i18n._t('LeftAndMain.PAGEWASDELETED') + "</p>";
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Reload lose the form if the current page is open.
|
|
*/
|
|
reloadIfSetTo: function(id) {
|
|
if(this.elements.ID && this.elements.ID.value == id) {
|
|
this.getPageFromServer(id);
|
|
}
|
|
},
|
|
|
|
close: function() {
|
|
this.innerHTML = "<p> </p>";
|
|
var actions;
|
|
if(actions = $('form_actions_' + this.formName)) {
|
|
actions.parentNode.removeChild(actions);
|
|
}
|
|
},
|
|
|
|
updateStatus: function( newStatus ) {
|
|
|
|
if( $('Form_EditForm_Status') )
|
|
$('Form_EditForm_Status').innerHTML = "STATUS: " + newStatus;
|
|
},
|
|
|
|
/**
|
|
* Load a new page into the right-hand form.
|
|
*
|
|
* @param formContent string
|
|
* @param response object (optional)
|
|
* @param evalResponse boolean (optional)
|
|
*/
|
|
loadNewPage : function(formContent, response, evalResponse) {
|
|
//alert('here: ' + formContent);
|
|
var rightHTML = formContent;
|
|
|
|
// Rewrite # links
|
|
rightHTML = rightHTML.replace(/(<a[^>]+href *= *")#/g, '$1' + window.location.href.replace(/#.*$/,'') + '#');
|
|
|
|
// Rewrite iframe links (for IE)
|
|
rightHTML = rightHTML.replace(/(<iframe[^>]*src=")([^"]+)("[^>]*>)/g, '$1' + baseHref() + '$2$3');
|
|
|
|
// Note: TinyMCE coupling
|
|
tinymce_removeAll();
|
|
|
|
// Prepare iframes for removal, otherwise we get loading bugs
|
|
var i, allIframes = this.getElementsByTagName('iframe');
|
|
if(allIframes) for(i=0;i<allIframes.length;i++) {
|
|
allIframes[i].contentWindow.location.href = 'about:blank';
|
|
allIframes[i].parentNode.removeChild(allIframes[i]);
|
|
}
|
|
|
|
if(response && evalResponse) {
|
|
// no-op, has already been evaluated by prototype.js
|
|
} else {
|
|
this.innerHTML = rightHTML;
|
|
}
|
|
|
|
// Get the form attributes from embedded fields
|
|
var attr;
|
|
|
|
for(attr in {'action':true ,'method':true,'enctype':true,'name':true}) {
|
|
if(this.elements['_form_' + attr]) {
|
|
this[attr] = this.elements['_form_' + attr].value;
|
|
this.elements['_form_' + attr].parentNode.removeChild(this.elements['_form_' + attr]);
|
|
}
|
|
}
|
|
|
|
allIframes = this.getElementsByTagName('iframe');
|
|
if(allIframes) for(i=0;i<allIframes.length;i++) {
|
|
try {
|
|
allIframes[i].contentWindow.location.href = allIframes[i].src;
|
|
} catch(er) { alert('Error in LeftAndMain_right.js CMSForm.loadNewPage: ' + er.message); }
|
|
}
|
|
|
|
_TAB_DIVS_ON_PAGE = [];
|
|
|
|
//initTabstripe() become livequery in tabstrip.js, so we don't need to call it for each tab strip here.
|
|
|
|
|
|
// We assume that an evaluated response is generated by FormResponse
|
|
// which takes care of calling these method it
|
|
if (!evalResponse) {
|
|
if (this.prepareForm) this.prepareForm();
|
|
Behaviour.apply(this);
|
|
}
|
|
|
|
if(this.resetElements) this.resetElements();
|
|
|
|
window.ontabschanged();
|
|
|
|
// If there's a title field and it's got a "new XX" value, focus/select that first
|
|
// This is really a little too CMS-specific (as opposed to LeftAndMain), but the cleanup can happen after jQuery refactoring
|
|
if($('input#Form_EditForm_Title') && $('input#Form_EditForm_Title').value.match(/^new/i)) {
|
|
$('input#Form_EditForm_Title').select();
|
|
}
|
|
},
|
|
/**
|
|
* Save the contens of the form, by submitting it and resetting is changed checker
|
|
* on success.
|
|
*
|
|
* @param ifChanged boolean if true, only save changed fields
|
|
* @param callAfter function (optional) callback function to run after the AJAX request.
|
|
* @param action string (optional, default is 'save') action to call via AJAX.
|
|
* @param publish boolean (optional) whether to publish in addition to saving
|
|
*/
|
|
save: function(ifChanged, callAfter, action, publish) {
|
|
_AJAX_LOADING = true;
|
|
// Note: TinyMCE coupling
|
|
if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
|
|
if(!action) action = "save";
|
|
|
|
var __callAfter = callAfter;
|
|
var __form = this;
|
|
|
|
if(__form.notify && __form.elements.ID != undefined) __form.notify('BeforeSave', __form.elements.ID.value);
|
|
|
|
// validate if required
|
|
if(this.validate && !this.validate()) {
|
|
// TODO Automatically switch to the tab/position of the first error
|
|
statusMessage("Validation failed.", "bad");
|
|
|
|
if($('Form_EditForm_action_save') && $('Form_EditForm_action_save').stopLoading) $('Form_EditForm_action_save').stopLoading();
|
|
|
|
return false;
|
|
}
|
|
|
|
var success = function(response) {
|
|
__form.resetElements();
|
|
if(__callAfter) __callAfter();
|
|
if(__form.notify && __form.elements.ID != undefined) __form.notify('PageSaved', __form.elements.ID.value);
|
|
if($('Form_EditForm_action_save') && $('Form_EditForm_action_save').stopLoading) $('Form_EditForm_action_save').stopLoading();
|
|
_AJAX_LOADING = false;
|
|
}
|
|
|
|
if(ifChanged) {
|
|
var data = this.serializeChangedFields('ID') + '&ajax=1&action_' + action + '=1';
|
|
} else {
|
|
var data = this.serializeAllFields() + '&ajax=1&action_' + action + '=1';
|
|
}
|
|
if(publish)
|
|
{
|
|
data += '&publish=1';
|
|
}
|
|
|
|
statusMessage(ss.i18n._t('CMSMAIN.SAVING'), null, true);
|
|
|
|
new Ajax.Request(this.action, {
|
|
method : this.method,
|
|
postBody: data,
|
|
onSuccess : success,
|
|
onFailure : function(response) {
|
|
errorMessage('Error saving content', response);
|
|
if($('Form_EditForm_action_save') && $('Form_EditForm_action_save').stopLoading) $('Form_EditForm_action_save').stopLoading();
|
|
_AJAX_LOADING = false;
|
|
}
|
|
});
|
|
},
|
|
|
|
loadPage_url : 'admin/getpage'
|
|
}
|
|
|
|
CMSRightForm = Class.extend('CMSForm');
|
|
CMSRightForm.prototype = {
|
|
intialize: function() {
|
|
this.CMSForm.initialize('right');
|
|
},
|
|
|
|
|
|
/**
|
|
* Load the given URL (with &ajax=1) into this form
|
|
*/
|
|
loadURLFromServer : function(url) {
|
|
var urlParts = url.match( /ID=(\d+)/ );
|
|
var id = urlParts ? urlParts[1] : null;
|
|
|
|
if( !url.match( /^https?:\/\/.*/ ) )
|
|
url = document.getElementsByTagName('base')[0].href + url;
|
|
|
|
new Ajax.Request( url + '&ajax=1', {
|
|
asynchronous : true,
|
|
onSuccess : function( response ) {
|
|
$('Form_EditForm').successfullyReceivedPage(response,id);
|
|
},
|
|
onFailure : function(response) {
|
|
alert(response.responseText);
|
|
errorMessage('error loading page',response);
|
|
}
|
|
});
|
|
},
|
|
|
|
successfullyReceivedPage : function(response,pageID) {
|
|
var loadingNode = $('sitetree').loadingNode;
|
|
|
|
if( loadingNode && pageID && parseInt( $('sitetree').getIdxOf( loadingNode ) ) != pageID ) {
|
|
return;
|
|
}
|
|
|
|
// must wait until the javascript has finished
|
|
document.body.style.cursor = 'wait';
|
|
|
|
this.loadNewPage(response.responseText);
|
|
|
|
var subform;
|
|
if(subform = $('Form_SubForm')) subform.close();
|
|
|
|
if(this.elements.ID) {
|
|
this.notify('PageLoaded', this.elements.ID.value);
|
|
}
|
|
|
|
if(this.receivingID) {
|
|
// Treenode might not exist if that part of the tree is closed
|
|
var treeNode = loadingNode ? loadingNode : $('sitetree').getTreeNodeByIdx(this.receivingID);
|
|
if(treeNode) {
|
|
$('sitetree').setCurrentByIdx(treeNode.getIdx());
|
|
treeNode.removeNodeClass('loading');
|
|
}
|
|
statusMessage('');
|
|
}
|
|
|
|
// must wait until the javascript has finished
|
|
document.body.style.cursor = 'default';
|
|
|
|
},
|
|
didntReceivePage : function(response) {
|
|
errorMessage('error loading page', response);
|
|
$('sitetree').getTreeNodeByIdx(this.elements.ID.value).removeNodeClass('loading');
|
|
},
|
|
|
|
|
|
/**
|
|
* Request a page from the server via Ajax
|
|
*/
|
|
getPageFromServer : function(id, treeNode) {
|
|
// if(id && id.match(/^[A-Za-z0-9_]+$/)) {
|
|
if(id && (id == 'root' || parseInt(id) == id || (id.substr && id.substr(0,3) == 'new') )) {
|
|
this.receivingID = id;
|
|
|
|
// Treenode might not exist if that part of the tree is closed
|
|
if(!treeNode) treeNode = $('sitetree').getTreeNodeByIdx(id);
|
|
|
|
if(treeNode) {
|
|
$('sitetree').loadingNode = treeNode;
|
|
treeNode.addNodeClass('loading');
|
|
url = treeNode.aTag.href + (treeNode.aTag.href.indexOf('?')==-1?'?':'&') + 'ajax=1';
|
|
}
|
|
if(SiteTreeHandlers.loadPage_url) {
|
|
var sep = (SiteTreeHandlers.loadPage_url.indexOf('?') == -1) ? '?' : '&';
|
|
url = SiteTreeHandlers.loadPage_url + sep + 'ID=' + id;
|
|
}
|
|
|
|
// used to set language in CMSMain->init()
|
|
var lang = $('LangSelector') ? $F('LangSelector') : null;
|
|
if(lang) {
|
|
url += '&locale='+lang;
|
|
}
|
|
|
|
statusMessage(ss.i18n._t('LOADING', 'loading...'));
|
|
this.loadURLFromServer(url);
|
|
} else {
|
|
throw("getPageFromServer: Bad page ID: " + id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the status field
|
|
*/
|
|
/*setStatus: function(newStatus) {
|
|
var statusLabel = document.getElementsBySelector('label.pageStatusMessage')[0];
|
|
if(statusLabel) statusLabel.innerHTML = "STATUS: " + newStatus;
|
|
}*/
|
|
}
|
|
|
|
CMSForm.applyTo('#Form_SubForm');
|
|
CMSRightForm.applyTo('#Form_EditForm', 'right');
|
|
|
|
function action_save_right() {
|
|
_AJAX_LOADING = true;
|
|
$('Form_EditForm_action_save').value = ss.i18n._t('CMSMAIN.SAVING');
|
|
$('Form_EditForm_action_save').className = 'action loading';
|
|
$('Form_EditForm_action_save').stopLoading = function() {
|
|
if($('Form_EditForm_action_save') && $('Form_EditForm_action_save').className.indexOf('loading') != -1) {
|
|
$('Form_EditForm_action_save').value = 'Save';
|
|
Element.removeClassName($('Form_EditForm_action_save'), 'loading');
|
|
}
|
|
}
|
|
|
|
$('Form_EditForm').save(false);
|
|
}
|
|
|
|
function action_save_siteconfig_right() {
|
|
_AJAX_LOADING = true;
|
|
if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
|
|
$('Form_EditForm_action_save_siteconfig').value = ss.i18n._t('CMSMAIN.SAVING');
|
|
$('Form_EditForm_action_save_siteconfig').className = 'action loading';
|
|
|
|
$('Form_EditForm').save(null, function() {
|
|
if($('Form_EditForm_action_save_siteconfig') && $('Form_EditForm_action_save_siteconfig').className.indexOf('loading') != -1) {
|
|
$('Form_EditForm_action_save_siteconfig').value = 'Save';
|
|
Element.removeClassName($('Form_EditForm_action_save_siteconfig'), 'loading');
|
|
}
|
|
}, 'save_siteconfig');
|
|
}
|
|
|
|
/**
|
|
* Handle auto-saving. Detects if changes have been made, and if so save everything on the page.
|
|
* If confirmation is true it will ask for confirmation.
|
|
*/
|
|
function autoSave(confirmation, callAfter) {
|
|
// Note: TinyMCE coupling
|
|
if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
|
|
|
|
var __forms = []
|
|
if($('Form_EditForm')) __forms.push($('Form_EditForm'));
|
|
if($('Form_SubForm')) __forms.push($('Form_SubForm'));
|
|
|
|
var __somethingHasChanged = false;
|
|
var __callAfter = callAfter;
|
|
|
|
__forms.each(function(form) {
|
|
if(form.isChanged && form.isChanged()) {
|
|
__somethingHasChanged = true;
|
|
}
|
|
});
|
|
|
|
if(__somethingHasChanged) {
|
|
// Note: discard and cancel options are no longer used since switching to confirm dialog.
|
|
// save is still used if confirmation = false
|
|
var options = {
|
|
save: function() {
|
|
statusMessage(ss.i18n._t('CMSMAIN.SAVING'), '', true);
|
|
var i;
|
|
for(i=0;i<__forms.length;i++) {
|
|
if(__forms[i].isChanged && __forms[i].isChanged()) {
|
|
if(i == 0) __forms[i].save(true, __callAfter);
|
|
else __forms[i].save(true);
|
|
}
|
|
}
|
|
},
|
|
discard: function() {
|
|
__forms.each(function(form) { form.resetElements(false); });
|
|
if(__callAfter) __callAfter();
|
|
},
|
|
cancel: function() {
|
|
}
|
|
}
|
|
|
|
if(confirmation ) {
|
|
if(confirm(ss.i18n._t('LeftAndMain.CONFIRMUNSAVED')))
|
|
{
|
|
// OK was pressed, call function for what was clicked on
|
|
if(__callAfter) __callAfter();
|
|
} else {
|
|
// Cancel was pressed, stay on the current page
|
|
return false;
|
|
}
|
|
} else {
|
|
options.save();
|
|
}
|
|
|
|
} else {
|
|
if(__callAfter) __callAfter();
|
|
}
|
|
}
|
|
|
|
window.name = windowName('cms');
|
|
|
|
/**
|
|
* Return a unique window name that contains the URL
|
|
*/
|
|
function windowName(suffix) {
|
|
var base = document.getElementsByTagName('base')[0].href.replace('~','').replace('http://','').replace(/\//g,'_').replace(/\./g,'_');
|
|
return base + suffix;
|
|
}
|
|
|
|
/**
|
|
* Remove all the currently active TinyMCE editors.
|
|
* Note: everything that calls this has an inappropriate coupling to TinyMCE.
|
|
* Perhaps an observer pattern could be used, where TinyMCE listens to a onBeforeCMSPageLoad
|
|
* event?
|
|
*/
|
|
function tinymce_removeAll() {
|
|
if((typeof tinymce != 'undefined') && tinymce.EditorManager) {
|
|
var id;
|
|
for(id in tinymce.EditorManager.editors) {
|
|
tinymce.EditorManager.editors[id].remove();
|
|
}
|
|
tinymce.EditorManager.editors = {};
|
|
}
|
|
|
|
}
|