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:
Frank Mullenger 2011-05-08 16:02:28 +12:00 committed by Ingo Schommer
parent 028bc23959
commit 0b8f8a3c8a
2 changed files with 32 additions and 30 deletions

View File

@ -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);

View File

@ -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;