mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
ENHANCEMENT Checking allowed parents/children in tree dragging. Using 'data' attributes to encode metadata on the tree element (fixes #6578)
This commit is contained in:
parent
028bc23959
commit
0b8f8a3c8a
@ -107,49 +107,46 @@
|
||||
|
||||
/**
|
||||
* Function: refresh
|
||||
* This is called after each change event of PageType dropdown
|
||||
*
|
||||
* Parameters:
|
||||
* (DOMElement) selectedNode
|
||||
*/
|
||||
refresh: function(selectedNode) {
|
||||
// Note: Uses siteTreeHints global
|
||||
|
||||
var tree = this.getTree(),
|
||||
selectedNode = selectedNode || $(tree).jstree('get_selected')
|
||||
origOptions = this.getOrigOptions(),
|
||||
dropdown = this.find('select[name=PageType]');
|
||||
dropdown = this.find('select[name=PageType]'),
|
||||
disallowed = [],
|
||||
className = (selectedNode) ? selectedNode.getClassname() : null,
|
||||
siteTreeHints = $.parseJSON($('#sitetree_ul').attr('data-hints')),
|
||||
disableDropDown = true,
|
||||
selectedOption = dropdown.val();
|
||||
|
||||
// Clear all existing <option> elements
|
||||
// (IE doesn't allow setting display:none on these elements)
|
||||
dropdown.find('option').remove();
|
||||
|
||||
// Find allowed children through preferences on node or globally
|
||||
var allowed = [];
|
||||
if(selectedNode) {
|
||||
if(selectedNode.hints && selectedNode.hints.allowedChildren) {
|
||||
allowed = selectedNode.hints.allowedChildren;
|
||||
} else {
|
||||
// Fallback to globals
|
||||
allowed = (typeof siteTreeHints !== 'undefined') ? siteTreeHints['Root'].allowedChildren : [];
|
||||
}
|
||||
|
||||
// Re-add all allowed <option> to the dropdown
|
||||
for(i=0;i<allowed.length;i++) {
|
||||
var optProps = origOptions[allowed[i]];
|
||||
if(optProps) dropdown.append($('<option value="' + optProps.value + '">' + optProps.html + '</option>'));
|
||||
}
|
||||
} else {
|
||||
// No tree node selected, reset to original elements
|
||||
$.each(origOptions, function(i, optProps) {
|
||||
if(optProps) dropdown.append($('<option value="' + optProps.value + '">' + optProps.html + '</option>'));
|
||||
});
|
||||
//Use tree hints to find allowed children for this node
|
||||
if (className && typeof siteTreeHints !== 'undefined') {
|
||||
disallowed = siteTreeHints[className].disallowedChildren;
|
||||
}
|
||||
|
||||
// TODO Re-select the currently selected element
|
||||
$.each(origOptions, function(i, optProps) {
|
||||
if ($.inArray(i, disallowed) === -1 && optProps) {
|
||||
dropdown.append($('<option value="' + optProps.value + '">' + optProps.html + '</option>'));
|
||||
disableDropDown = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Disable dropdown if no elements are selectable
|
||||
if(allowed) dropdown.removeAttr('disabled');
|
||||
if (!disableDropDown) dropdown.removeAttr('disabled');
|
||||
else dropdown.attr('disabled', 'disabled');
|
||||
|
||||
|
||||
//Re-select the currently selected element
|
||||
if (selectedOption) dropdown.val(selectedOption);
|
||||
|
||||
// Set default child (optional)
|
||||
if(selectedNode.hints && selectedNode.hints.defaultChild) {
|
||||
dropdown.val(selectedNode.hints.defaultChild);
|
||||
|
@ -3,20 +3,24 @@
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
|
||||
$.entwine('ss', function($){
|
||||
|
||||
$('.cms-tree').entwine({
|
||||
|
||||
Hints: null,
|
||||
|
||||
onmatch: function() {
|
||||
this._super();
|
||||
|
||||
this.setHints($.parseJSON(this.attr('data-hints')));
|
||||
|
||||
/**
|
||||
* @todo Icon and page type hover support
|
||||
* @todo Sorting of sub nodes (originally placed in context menu)
|
||||
* @todo Refresh after language <select> change (with Translatable enabled)
|
||||
* @todo Automatic load of full subtree via ajax on node checkbox selection (minNodeCount = 0)
|
||||
* to avoid doing partial selection with "hidden nodes" (unloaded markup)
|
||||
* @todo Add siteTreeHints to field (as "data-hints" attribute with serialized JSON instead of javascript global variable)
|
||||
* @todo Disallow drag'n'drop when node has "noChildren" set (see siteTreeHints)
|
||||
* @todo Disallow moving of pages marked as deleted
|
||||
* most likely by server response codes rather than clientside
|
||||
@ -52,13 +56,14 @@
|
||||
// Check if a node is allowed to be moved.
|
||||
// Caution: Runs on every drag over a new node
|
||||
'check_move': function(data) {
|
||||
|
||||
var movedNode = $(data.o), newParent = $(data.np),
|
||||
isMovedOntoContainer = data.ot.get_container()[0] == data.np[0],
|
||||
movedNodeClass = movedNode.getClassname(),
|
||||
newParentClass = newParent.getClassname(),
|
||||
// Check allowedChildren of newParent or against root node rules
|
||||
allowedChildren = siteTreeHints[newParentClass ? newParentClass : 'Root'].allowedChildren || [];
|
||||
|
||||
hints = self.getHints(),
|
||||
disallowedChildren = hints[newParentClass ? newParentClass : 'Root'].disallowedChildren || [];
|
||||
var isAllowed = (
|
||||
// Don't allow moving the root node
|
||||
movedNode.data('id') != 0
|
||||
@ -67,7 +72,7 @@
|
||||
// Children are generally allowed on parent
|
||||
&& !newParent.hasClass('nochildren')
|
||||
// movedNode is allowed as a child
|
||||
&& ($.inArray(movedNodeClass, allowedChildren) != -1)
|
||||
&& ($.inArray(movedNodeClass, disallowedChildren) == -1)
|
||||
);
|
||||
|
||||
return isAllowed;
|
||||
|
Loading…
x
Reference in New Issue
Block a user