API CHANGE Removed CMSBatchAction->getDoingText(), is now using button loading indicators in the UI

API CHANGE Removed LeftAndMain->BatchActionList(), no longer necessary as we're creating the batch actions form in the same class
ENHANCEMENT Changed CMSBatchAction logic to return JSON status changes rather than eval'ed JavaScript via FormResponse
ENHANCEMENT Ported batchactions in CMSMain_left.js to concrete javascript, and moved to new CMSMain.BatchActions.js file
ENHANCEMENT Using native CMSMain->BatchActionsForm() to render form instead of custom template markup in CMSMain_TreeTools.ss

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92722 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2009-11-21 03:15:40 +00:00
parent 26785076ba
commit 44e16b9620
6 changed files with 394 additions and 342 deletions

View File

@ -1,7 +1,9 @@
<?php
/**
* A class representing back actions
* A class representing back actions.
* See cms/javascript/CMSMain.BatchActions.js on how to add custom javascript
* functionality.
*
* <code>
* CMSMain::register_batch_action('publishitems', new CMSBatchAction('doPublish',
@ -17,12 +19,6 @@ abstract class CMSBatchAction extends Object {
*/
abstract function getActionTitle();
/**
* Get text to be shown while the action is being processed, of the form
* "publishing pages".
*/
abstract function getDoingText();
/**
* Run this action for the given set of pages.
* Return a set of status-updated JavaScript to return to the CMS.
@ -36,33 +32,45 @@ abstract class CMSBatchAction extends Object {
* @param $pages The DataObjectSet of SiteTree objects to perform this batch action
* on.
* @param $helperMethod The method to call on each of those objects.
* @para
* @return JSON encoded map in the following format:
* {
* 'modified': {
* 3: {'TreeTitle': 'Page3'},
* 5: {'TreeTitle': 'Page5'}
* },
* 'deleted': {
* // all deleted pages
* }
* }
*/
public function batchaction(DataObjectSet $pages, $helperMethod, $successMessage, $arguments = array()) {
public function batchaction(DataObjectSet $pages, $helperMethod, $successMessage) {
$failures = 0;
$status = array('modified' => array(), 'error' => array());
foreach($pages as $page) {
// Perform the action
if (!call_user_func_array(array($page, $helperMethod), $arguments)) {
$failures++;
$status['error'][$page->ID] = '';
}
// Now make sure the tree title is appropriately updated
$publishedRecord = DataObject::get_by_id('SiteTree', $page->ID);
if ($publishedRecord) {
$JS_title = Convert::raw2js($publishedRecord->TreeTitle);
FormResponse::add("\$('sitetree').setNodeTitle($page->ID, '$JS_title');");
$status['modified'][$publishedRecord->ID] = array(
'TreeTitle' => $publishedRecord->TreeTitle,
);
}
$page->destroy();
unset($page);
}
$message = sprintf($successMessage, $pages->Count()-$failures, $failures);
Controller::curr()->getResponse()->setStatusCode(
200,
sprintf($successMessage, $pages->Count())
);
FormResponse::add('statusMessage("'.$message.'","good");');
return FormResponse::respond();
return Convert::raw2json($status);
}
// if your batchaction has parameters, return a fieldset here
@ -81,9 +89,6 @@ class CMSBatchAction_Publish extends CMSBatchAction {
function getActionTitle() {
return _t('CMSBatchActions.PUBLISH_PAGES', 'Publish');
}
function getDoingText() {
return _t('CMSBatchActions.PUBLISHING_PAGES', 'Publishing pages');
}
function run(DataObjectSet $pages) {
return $this->batchaction($pages, 'doPublish',
@ -92,6 +97,24 @@ class CMSBatchAction_Publish extends CMSBatchAction {
}
}
/**
* Un-publish items batch action.
*
* @package cms
* @subpackage batchaction
*/
class CMSBatchAction_Unpublish extends CMSBatchAction {
function getActionTitle() {
return _t('CMSBatchActions.UNPUBLISH_PAGES', 'Un-publish');
}
function run(DataObjectSet $pages) {
return $this->batchaction($pages, 'doUnpublish',
_t('CMSBatchActions.UNPUBLISHED_PAGES', 'Un-published %d pages')
);
}
}
/**
* Delete items batch action.
*
@ -102,36 +125,34 @@ class CMSBatchAction_Delete extends CMSBatchAction {
function getActionTitle() {
return _t('CMSBatchActions.DELETE_DRAFT_PAGES', 'Delete from draft');
}
function getDoingText() {
return _t('CMSBatchActions.DELETING_DRAFT_PAGES', 'Deleting selected pages from draft');
}
function run(DataObjectSet $pages) {
$status = array(
'modified'=>array(),
'deleted'=>array()
);
foreach($pages as $page) {
$id = $page->ID;
// Perform the action
if($page->canDelete()) $page->delete();
// check to see if the record exists on the live site, if it doesn't remove the tree node
// check to see if the record exists on the live site,
// if it doesn't remove the tree node
$liveRecord = Versioned::get_one_by_stage( 'SiteTree', 'Live', "\"SiteTree\".\"ID\"=$id");
if($liveRecord) {
$liveRecord->IsDeletedFromStage = true;
$title = Convert::raw2js($liveRecord->TreeTitle);
FormResponse::add("$('sitetree').setNodeTitle($id, '$title');");
FormResponse::add("$('Form_EditForm').reloadIfSetTo($id);");
$status['modified'][$liveRecord->ID] = array(
'TreeTitle' => $liveRecord->TreeTitle,
);
} else {
FormResponse::add("var node = $('sitetree').getTreeNodeByIdx('$id');");
FormResponse::add("if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node);");
FormResponse::add("$('Form_EditForm').reloadIfSetTo($id);");
$status['deleted'][$id] = array();
}
}
$message = sprintf(_t('CMSBatchActions.DELETED_DRAFT_PAGES', 'Deleted %d pages from the draft site'), $pages->Count());
FormResponse::add('statusMessage("'.$message.'","good");');
return FormResponse::respond();
return Convert::raw2json($status);
}
}
@ -145,38 +166,33 @@ class CMSBatchAction_DeleteFromLive extends CMSBatchAction {
function getActionTitle() {
return _t('CMSBatchActions.DELETE_PAGES', 'Delete from published site');
}
function getDoingText() {
return _t('CMSBatchActions.DELETING_PAGES', 'Deleting selected pages from the published site');
}
function run(DataObjectSet $pages) {
$ids = $pages->column('ID');
$this->batchaction($pages, 'doUnpublish',
_t('CMSBatchActions.DELETED_PAGES', 'Deleted %d pages from the published site, %d failures')
$status = array(
'modified'=>array(),
'deleted'=>array()
);
foreach($ids as $pageID) {
$id = $pageID;
foreach($pages as $page) {
$id = $page->ID;
// Perform the action
if($page->canDelete()) $page->doDeleteFromLive();
// check to see if the record exists on the live site, if it doesn't remove the tree node
$stageRecord = Versioned::get_one_by_stage( 'SiteTree', 'Stage', "\"SiteTree\".\"ID\"=$id");
if($stageRecord) {
$stageRecord->IsAddedToStage = true;
$title = Convert::raw2js($stageRecord->TreeTitle);
FormResponse::add("$('sitetree').setNodeTitle($id, '$title');");
FormResponse::add("$('Form_EditForm').reloadIfSetTo($id);");
$status['modified'][$stageRecord->ID] = array(
'TreeTitle' => $stageRecord->TreeTitle,
);
} else {
FormResponse::add("var node = $('sitetree').getTreeNodeByIdx('$id');");
FormResponse::add("if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node);");
FormResponse::add("$('Form_EditForm').reloadIfSetTo($id);");
$status['deleted'][$stageRecord->ID] = array();
}
}
$message = sprintf(_t('CMSBatchActions.DELETED_PAGES', 'Deleted %d pages from the published site'), $pages->Count());
FormResponse::add('statusMessage("'.$message.'","good");');
return FormResponse::respond();
return Convert::raw2json($status);
}
}

View File

@ -96,8 +96,7 @@ class CMSBatchActionHandler extends RequestHandler {
$actionObj = new $actionClass();
$actionDef = new ArrayData(array(
"Link" => Controller::join_links($this->Link(), $urlSegment),
"Title" => $actionObj->getActionTitle(),
"DoingText" => $actionObj->getDoingText(),
"Title" => $actionObj->getActionTitle()
));
$actionList->push($actionDef);
}

View File

@ -83,6 +83,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
Requirements::javascript(CMS_DIR . '/javascript/CMSMain.js');
Requirements::javascript(CMS_DIR . '/javascript/CMSMain_left.js');
Requirements::javascript(CMS_DIR . '/javascript/CMSMain.BatchActions.js');
Requirements::javascript(CMS_DIR . '/javascript/CMSMain.Translatable.js');
Requirements::css(CMS_DIR . '/css/CMSMain.css');
@ -137,11 +138,16 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
*
* @return string
*/
public function getfilteredsubtree($data, $form) {
public function getfilteredsubtree($request) {
$params = $form->getData();
// Get the tree
$tree = $this->getSiteTreeFor($this->stat('tree_class'), $_REQUEST['ID'], null, array(new CMSMainMarkingFilter($params), 'mark'));
$tree = $this->getSiteTreeFor(
$this->stat('tree_class'),
$request->requestVar('ID'),
null,
array(new CMSMainMarkingFilter($params), 'mark')
);
// Trim off the outer tag
$tree = ereg_replace('^[ \t\r\n]*<ul[^>]*>','', $tree);
@ -1097,6 +1103,45 @@ JS;
return $form;
}
/**
* @return Form
*/
function BatchActionsForm() {
$actions = $this->batchactions()->batchActionList();
$actionsMap = array();
foreach($actions as $action) $actionsMap[$action->Link] = $action->Title;
$form = new Form(
$this,
'BatchActionsForm',
new FieldSet(
new LiteralField(
'Intro',
sprintf('<p><small>%s</small></p>',
_t(
'CMSMain_left.ss.SELECTPAGESACTIONS',
'Select the pages that you want to change &amp; then click an action:'
)
)
),
new HiddenField('csvIDs'),
new DropdownField(
'Action',
false,
$actionsMap
)
),
new FieldSet(
// TODO i18n
new FormAction('submit', "Go")
)
);
$form->addExtraClass('actionparams');
$form->unsetValidator();
return $form;
}
/**
* Helper function to get page count

View File

@ -0,0 +1,278 @@
(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('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) {
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');
} else {
self._multiselectTransform();
}
});
this.bind('submit', function(e) {return self._submit(e);});
},
/**
* @param {String} type
* @param {Function} callback
*/
register: function(type, callback) {
this.trigger('register', {type: type, callback: callback});
var actions = this.Actions();
actions[type] = callback;
this.setActions(actions);
},
/**
* Remove an existing action.
*
* @param {String} type
*/
unregister: function(type) {
this.trigger('unregister', {type: type});
var actions = this.Actions();
if(actions[type]) delete actions[type];
this.setActions(actions);
},
/**
* Determines if we should allow and track tree selections.
*
* @todo Too much coupling with tabset
* @return boolean
*/
_isActive: function() {
return $('#TreeActions-batchactions').is(':visible');
},
_submit: function(e) {
var ids = [];
var tree = this.Tree();
// find all explicitly selected IDs
$(tree).find('li.selected').each(function() {
ids.push(tree.getIdxOf(this));
// find implicitly selected children
$(this).find('li').each(function() {
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 no IDs are selected, stop here. This is an implict way for the
// callback to cancel the actions
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,
type: 'POST',
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');
},
success: function(data, status) {
// TODO This should use a more common serialization in a new tree library
if(data.modified) {
for(var id in data.modified) {
tree.setNodeTitle(id, data.modified[id]['TreeTitle']);
}
}
if(data.deleted) {
for(var id in data.deleted) {
var node = tree.getTreeNodeByIdx(id);
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();
if(selectedNode) {
var selectedNodeId = tree.getIdxOf(selectedNode);
if(data.modified[selectedNode.getIdx()]) {
// only if the current page was modified
selectedNode.selectTreeNode();
} else if(data.deleted[selectedNode.getIdx()]) {
$('#Form_EditForm').concrete('ss').removeForm();
}
} else {
$('#Form_EditForm').concrete('ss').removeForm();
}
// close panel
// TODO Coupling with tabs
$('#TreeActions').tabs('select', -1);
},
dataType: 'json'
});
return false;
},
/**
* @todo This is simulating MultiselectTree functionality, and shouldn't be necessary.
*/
_multiselectTransform : function() {
// make tree selectable
jQuery(this.Tree()).addClass('multiselect');
// auto-select the current node
var node = this.Tree().firstSelected();
if(node){
node.removeNodeClass('current');
node.addNodeClass('selected');
node.open();
// Open all existing children, which might trigger further
// ajaxExansion calls to ensure all nodes are selectable
var children = $(node).find('li').each(function() {
this.open();
});
}
},
/**
* Only triggers if the field is considered 'active'.
* @todo Most of this is basically simulating broken behaviour of the MultiselectTree mixin,
* and should be removed.
*/
_treeSelectionChanged: function(node) {
if(!this._isActive()) return;
if(node.selected) {
node.removeNodeClass('selected');
node.selected = false;
} else {
// Select node
node.addNodeClass('selected');
node.selected = true;
// Open node in order to allow proper selection of children
if($(node).hasClass('unexpanded')) {
node.open();
}
// Open all existing children, which might trigger further
// ajaxExansion calls to ensure all nodes are selectable
var children = $(node).find('li').each(function() {
this.open();
});
}
}
};
});
$(document).ready(function() {
/**
* Publish selected pages action
*/
$('#Form_BatchActionsForm').concrete('ss').register('admin/batchactions/publish', function(ids) {
var confirmed = confirm(
"You have " + ids.length + " pages selected.\n\n"
+ "Do your really want to publish?"
);
return (confirmed) ? ids : false;
});
/**
* Unpublish selected pages action
*/
$('#Form_BatchActionsForm').concrete('ss').register('admin/batchactions/unpublish', function(ids) {
var confirmed = confirm(
"You have " + ids.length + " pages selected.\n\n"
+ "Do your really want to unpublish?"
);
return (confirmed) ? ids : false;
});
/**
* Delete selected pages action
*/
$('#Form_BatchActionsForm').concrete('ss').register('admin/batchactions/delete', function(ids) {
var confirmed = confirm(
"You have " + ids.length + " pages selected.\n\n"
+ "Do your really want to delete?"
);
return (confirmed) ? ids : false;
});
/**
* Delete selected pages from live action
*/
$('#Form_BatchActionsForm').concrete('ss').register('admin/batchactions/deletefromlive', function(ids) {
var confirmed = confirm(
"You have " + ids.length + " pages selected.\n\n"
+ "Do your really want to delete these pages from live?"
);
return (confirmed) ? ids : false;
});
});
})(jQuery);

View File

@ -40,279 +40,6 @@ SiteTreeFilter.prototype = {
}
}
/**
* Batch Actions button click action
*/
batchactionsclass = Class.create();
batchactionsclass.applyTo('#batchactions');
batchactionsclass.prototype = {
initialize : function() {
Observable.applyTo($(_HANDLER_FORMS.batchactions));
},
onclick : function() {
if(treeactions.toggleSelection(this)) {
this.multiselectTransform();
}
return false;
},
actionChanged: function() {
var urlSegment = $('choose_batch_action').value.split('/').pop()
if ($('BatchActionParameters_'+urlSegment)) {
jQuery('#actionParams').empty();
jQuery('#BatchActionParameters_'+urlSegment).appendTo('#actionParams');
$('actionParams').style.display = 'block';
$('actionParams').style.padding = '4px';
} else {
$('actionParams').innerHTML = '';
$('actionParams').style.display = 'none';
}
},
multiselectTransform : function() {
batchActionGlobals.o1 = $('sitetree').observeMethod('SelectionChanged', batchActionGlobals.treeSelectionChanged);
batchActionGlobals.o2 = $(_HANDLER_FORMS.batchactions).observeMethod('Close', batchActionGlobals.popupClosed);
jQuery('#sitetree').addClass('multiselect');
batchActionGlobals.selectedNodes = { };
var selectedNode = $('sitetree').firstSelected();
if(selectedNode && selectedNode.className.indexOf('nodelete') == -1) {
var selIdx = $('sitetree').getIdxOf(selectedNode);
batchActionGlobals.selectedNodes[selIdx] = true;
selectedNode.removeNodeClass('current');
selectedNode.addNodeClass('selected');
selectedNode.open();
// Open all existing children, which might trigger further
// ajaxExansion calls to ensure all nodes are selectable
var children = selectedNode.getElementsByTagName('li');
for(var i=0; i<children.length; i++) {
children[i].open();
}
}
}
}
// batchActionGlobals is needed because calls to observeMethod doesn't seem to preserve instance variables so a Prototype can't be used
batchActionGlobals = {
selectedNodes: { },
// count Int - The number of nodes selected
count: { },
// TODO: Remove 'new-' code http://open.silverstripe.com/ticket/875
newNodes: { },
treeSelectionChanged : function(selectedNode) {
var idx = $('sitetree').getIdxOf(selectedNode);
if(selectedNode.className.indexOf('nodelete') == -1) {
if(selectedNode.selected) {
selectedNode.removeNodeClass('selected');
selectedNode.selected = false;
batchActionGlobals.selectedNodes[idx] = false;
} else {
// Open node in order to allow proper selection of children
if(Element.hasClassName(selectedNode, 'unexpanded')) {
selectedNode.open();
}
// Select node
selectedNode.addNodeClass('selected');
selectedNode.selected = true;
batchActionGlobals.selectedNodes[idx] = true;
// Open all existing children, which might trigger further
// ajaxExansion calls to ensure all nodes are selectable
var children = selectedNode.getElementsByTagName('li');
for(var i=0; i<children.length; i++) {
children[i].open();
}
}
}
return false;
},
popupClosed : function() {
jQuery('#sitetree').removeClass('multiselect');
$('sitetree').stopObserving(batchActionGlobals.o1);
$(_HANDLER_FORMS.batchactions).stopObserving(batchActionGlobals.o2);
for(var idx in batchActionGlobals.selectedNodes) {
if(batchActionGlobals.selectedNodes[idx]) {
node = $('sitetree').getTreeNodeByIdx(idx);
if(node) {
node.removeNodeClass('selected');
node.selected = false;
}
}
}
batchActionGlobals.selectedNodes = { };
},
getCsvIds : function() {
var csvIDs = new Array();
var st = $('sitetree');
batchActionGlobals.newNodes = new Array();
for(var idx in batchActionGlobals.selectedNodes) {
if(batchActionGlobals.selectedNodes[idx]) {
// Delete/Publish new nodes? (Leftover from delete code?) TODO: Remove 'new-' code http://open.silverstripe.com/ticket/875
if( idx.match(/^new-[a-z0-9A-Z\-]+$/) ) {
batchActionGlobals.newNodes.push( idx );
} else {
var i, item, childrenTopublish = st.getTreeNodeByIdx(idx).getElementsByTagName('li');
for(i=0;item=childrenTopublish[i];i++) {
if(csvIDs.indexOf(st.getIdxOf(childrenTopublish[i])) == -1) {
csvIDs.push(st.getIdxOf(childrenTopublish[i]));
}
}
if(csvIDs.indexOf(idx) == -1) {
csvIDs.push(idx);
}
}
}
}
batchActionGlobals.count=csvIDs.length;
return (csvIDs.toString());
},
unfilterSiteTree : function() {
// Reload the site tree if it has been filtered
if ($('SiteTreeIsFiltered').value == 1) {
// Show all items in Site Tree again
new Ajax.Request( 'admin/SiteTreeAsUL' + '&ajax=1', {
onSuccess: function( response ) {
$('sitetree_ul').innerHTML = response.responseText;
Behaviour.apply($('sitetree_ul'));
$('SiteTreeIsFiltered').value = 0;
$('batchactions').multiselectTransform();
statusMessage(ss.i18n._t('CMSMAIN.SUCCESSUNFILTER'),'good');
},
onFailure : function(response) {
errorMessage(ss.i18n.sprintf(
ss.i18n._t('CMSMAIN.ERRORUNFILTER'),
response.responseText
));
}
});
}
}
}
Behaviour.register({
'#choose_batch_action' : {
onchange : function() {
$('batchactions').actionChanged();
}
}
});
/**
* Publish selected pages action
*/
publishpage = Class.create();
publishpage.applyTo('#batchactions_options');
publishpage.prototype = {
onsubmit : function() {
csvIDs = batchActionGlobals.getCsvIds();
if(csvIDs) {
var optionEl = $('choose_batch_action').options[$('choose_batch_action').selectedIndex];
var actionText = optionEl.text;
var optionParams = eval(optionEl.className);
var ingText = optionParams.doingText;
// Confirmation
if(!confirm("You have " + batchActionGlobals.count + " pages selected.\n\nDo your really want to " + actionText.toLowerCase() + "?")) {
return false;
}
this.elements.csvIDs.value = csvIDs;
// Select form submission URL
this.action = $('choose_batch_action').value;
// Loading indicator
statusMessage(ingText);
$('batchactions_go').className = 'loading';
// Submit form
Ajax.SubmitForm(this, null, {
onSuccess : function(response) {
Ajax.Evaluator(response);
$('batchactions_go').className = '';
treeactions.closeSelection($('batchactions'));
},
onFailure : function(response) {
errorMessage('Error ' + ingText, response);
}
});
} else {
alert(ss.i18n._t('CMSMAIN.SELECTONEPAGE'));
}
return false;
}
}
/**
* Delete selected pages action
*/
deletepage = Class.create();
deletepage.applyTo('#Form_DeleteItemsForm');
deletepage.prototype = {
onsubmit : function() {
csvIDs = batchActionGlobals.getCsvIds();
if(csvIDs || batchActionGlobals.newNodes.length > 0) {
batchActionGlobals.count += batchActionGlobals.newNodes.length;
if(confirm(ss.i18n.sprintf(
ss.i18n._t('CMSMAIN.REALLYDELETEPAGES'),
batchActionGlobals.count
))) {
this.elements.csvIDs.value = csvIDs;
statusMessage(ss.i18n._t('CMSMAIN.DELETINGPAGES'));
// TODO: Remove 'new-' code http://open.silverstripe.com/ticket/875
for( var idx = 0; idx < batchActionGlobals.newNodes.length; idx++ ) {
var newNode = $('sitetree').getTreeNodeByIdx( batchActionGlobals.newNodes[idx] );
if( newNode.parentTreeNode )
newNode.parentTreeNode.removeTreeNode( newNode );
else
alert( newNode.id + ' has no parent node');
$('Form_EditForm').reloadIfSetTo(idx);
}
batchActionGlobals.newNodes = new Array();
// Put an AJAXY loading icon on the button
$('Form_DeleteItemsForm_action_deleteitems').className = 'loading';
Ajax.SubmitForm(this, null, {
onSuccess : function(response) {
Ajax.Evaluator(response);
$('Form_DeleteItemsForm_action_deleteitems').className = '';
treeactions.closeSelection($('batchactions'));
},
onFailure : function(response) {
errorMessage(ss.i18n._t('CMSMAIN.ERRORDELETINGPAGES'), response);
}
});
}
} else {
alert(ss.i18n._t('CMSMAIN.SELECTONEPAGE'));
}
return false;
}
}
/**
* Tree context menu
*/

View File

@ -27,20 +27,7 @@
</div>
<div id="TreeActions-batchactions">
<form class="actionparams" style="border:0" id="batchactions_options" action="">
<p><% _t('SELECTPAGESACTIONS','Select the pages that you want to change &amp; then click an action:') %></p>
<input type="hidden" name="csvIDs" />
<div>
<select id="choose_batch_action">
<% control BatchActionList %>
<option value="$Link" class="{doingText:'$DoingText'}">$Title</option>
<% end_control %>
</select>
<input id="batchactions_go" type="submit" class="action" value="Go" />
</div>
</form>
$BatchActionsForm
</div>
</div>