mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT: Change to TreeDropdownField, giving it filtering behaviour as described in ticket http://open.silverstripe.org/ticket/3007 . Its disabled by default for legacy compatibility, but enabled for HtmlEditorField so that link editor is filterable for local links, via an extra boolean parameter on TreeDowndownField.
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@93932 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
c640c5c5a9
commit
69818fad17
@ -225,10 +225,10 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
||||
'file' => _t('HtmlEditorField.LINKFILE', 'Download a file'),
|
||||
)
|
||||
),
|
||||
new TreeDropdownField('internal', _t('HtmlEditorField.PAGE', "Page"), 'SiteTree', 'URLSegment', 'MenuTitle'),
|
||||
new TreeDropdownField('internal', _t('HtmlEditorField.PAGE', "Page"), 'SiteTree', 'URLSegment', 'MenuTitle', true),
|
||||
new TextField('external', _t('HtmlEditorField.URL', 'URL'), 'http://'),
|
||||
new EmailField('email', _t('HtmlEditorField.EMAIL', 'Email address')),
|
||||
new TreeDropdownField('file', _t('HtmlEditorField.FILE', 'File'), 'File', 'Filename'),
|
||||
new TreeDropdownField('file', _t('HtmlEditorField.FILE', 'File'), 'File', 'Filename', 'Title', true),
|
||||
new TextField('Anchor', _t('HtmlEditorField.ANCHORVALUE', 'Anchor')),
|
||||
new TextField('LinkText', _t('HtmlEditorField.LINKTEXT', 'Link text')),
|
||||
new TextField('Description', _t('HtmlEditorField.LINKDESCR', 'Link description')),
|
||||
|
@ -27,10 +27,11 @@ class TreeDropdownField extends FormField {
|
||||
* @param string $keyField to field on the source class to save as the field value (default ID).
|
||||
* @param string $labelField the field name to show as the human-readable value on the tree (default Title).
|
||||
*/
|
||||
public function __construct($name, $title = null, $sourceObject = 'Group', $keyField = 'ID', $labelField = 'Title') {
|
||||
public function __construct($name, $title = null, $sourceObject = 'Group', $keyField = 'ID', $labelField = 'Title', $showFilter = false) {
|
||||
$this->sourceObject = $sourceObject;
|
||||
$this->keyField = $keyField;
|
||||
$this->labelField = $labelField;
|
||||
$this->showFilter = $showFilter;
|
||||
|
||||
if(!Object::has_extension($this->sourceObject, 'Hierarchy')) {
|
||||
throw new Exception (
|
||||
@ -95,12 +96,21 @@ class TreeDropdownField extends FormField {
|
||||
'name' => $this->name,
|
||||
'value' => $this->value
|
||||
)
|
||||
) . $this->createTag (
|
||||
) . ($this->showFilter ?
|
||||
$this->createTag(
|
||||
'input',
|
||||
array(
|
||||
'class' => 'items',
|
||||
'value' => '(Choose or type filter)'
|
||||
)
|
||||
) :
|
||||
$this->createTag (
|
||||
'span',
|
||||
array (
|
||||
'class' => 'items'
|
||||
),
|
||||
$title
|
||||
)
|
||||
) . $this->createTag (
|
||||
'a',
|
||||
array (
|
||||
@ -122,6 +132,8 @@ class TreeDropdownField extends FormField {
|
||||
public function tree(SS_HTTPRequest $request) {
|
||||
$isSubTree = false;
|
||||
|
||||
$this->filter = Convert::Raw2SQL($request->getVar('filter'));
|
||||
|
||||
if($ID = (int) $request->latestparam('ID')) {
|
||||
$obj = DataObject::get_by_id($this->sourceObject, $ID);
|
||||
$isSubTree = true;
|
||||
@ -139,11 +151,8 @@ class TreeDropdownField extends FormField {
|
||||
if(!$this->baseID || !$obj) $obj = singleton($this->sourceObject);
|
||||
}
|
||||
|
||||
if($this->filterCallback) {
|
||||
$obj->setMarkingFilterFunction($this->filterCallback);
|
||||
} elseif($this->sourceObject == 'Folder') {
|
||||
$obj->setMarkingFilter('ClassName', 'Folder');
|
||||
}
|
||||
if ($this->filterCallback || $this->sourceObject == 'Folder' || $this->filter != "")
|
||||
$obj->setMarkingFilterFunction(array($this, "filterMarking"));
|
||||
|
||||
$obj->markPartialTree();
|
||||
|
||||
@ -163,6 +172,23 @@ class TreeDropdownField extends FormField {
|
||||
return $obj->getChildrenAsUL('class="tree"', $eval, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marking function for the tree, which combines different filters sensibly. If a filter function has been set,
|
||||
* that will be called. If the source is a folder, automatically filter folder. And if filter text is set, filter on that
|
||||
* too. Return true if all applicable conditions are true, false otherwise.
|
||||
* @param $node
|
||||
* @return unknown_type
|
||||
*/
|
||||
function filterMarking($node) {
|
||||
if ($this->filterCallback && !call_user_func($this->filterCallback, $node)) return false;
|
||||
if ($this->sourceObject == "Folder" && $node->ClassName != 'Folder') return false;
|
||||
if ($this->filter != "") {
|
||||
$f = $this->labelField;
|
||||
return (strpos(strtoupper($node->$f), strtoupper($this->filter)) === FALSE) ? false : true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object where the $keyField is equal to a certain value
|
||||
*
|
||||
|
@ -6,14 +6,23 @@ TreeDropdownField.prototype = {
|
||||
initialize: function() {
|
||||
// Hook up all the fieldy bits
|
||||
this.editLink = this.getElementsByTagName('a')[0];
|
||||
if (this.getElementsByTagName('span').length > 0) {
|
||||
// no filter, humanItems is a span
|
||||
this.humanItems = this.getElementsByTagName('span')[0];
|
||||
this.inputTag = this.getElementsByTagName('input')[0];
|
||||
}
|
||||
else {
|
||||
// filter is present, humanItems is an input
|
||||
this.inputTag = this.getElementsByTagName('input')[0];
|
||||
this.humanItems = this.getElementsByTagName('input')[1];
|
||||
this.humanItems.onkeyup = this.filter_onkeyup;
|
||||
}
|
||||
this.editLink.treeDropdownField = this;
|
||||
this.humanItems.treeDropdownField = this;
|
||||
this.inputTag.treeDropdownField = this;
|
||||
|
||||
this.editLink.onclick = this.edit_click;
|
||||
this.humanItems.onclick = this.edit_click;
|
||||
this.humanItems.onclick = this.human_click;
|
||||
this.inputTag.setValue = this.setValue.bind(this);
|
||||
},
|
||||
|
||||
@ -76,7 +85,15 @@ TreeDropdownField.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
deleteTreeNode: function() {
|
||||
if (!this.itemTree) return;
|
||||
var parent = this.itemTree.parentNode;
|
||||
parent.removeChild(this.itemTree);
|
||||
this.itemTree = null;
|
||||
},
|
||||
|
||||
showTree: function () {
|
||||
if (!this.treeShown) this.saveCurrentState();
|
||||
this.treeShown = true;
|
||||
|
||||
if(this.itemTree) {
|
||||
@ -95,6 +112,16 @@ TreeDropdownField.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
saveCurrentState: function() {
|
||||
this.origHumanText = this.getHumanText();
|
||||
this.defaultCleared = false;
|
||||
this.filtered = false;
|
||||
},
|
||||
|
||||
restoreOriginalState: function() {
|
||||
this.setHumanText(this.origHumanText);
|
||||
},
|
||||
|
||||
/**
|
||||
* If this control is inside an iframe, stretch the iframe out to fit the tree.
|
||||
*/
|
||||
@ -149,6 +176,7 @@ TreeDropdownField.prototype = {
|
||||
var ajaxURL = this.helperURLBase() + 'tree/';
|
||||
ajaxURL += $('SecurityID') ? '&SecurityID=' + $('SecurityID').value : '';
|
||||
if($('Form_EditForm_Locale')) ajaxURL += "&locale=" + $('Form_EditForm_Locale').value;
|
||||
if (this.filter() != null) ajaxURL += "&filter=" + this.filter();
|
||||
new Ajax.Request(ajaxURL, {
|
||||
method : 'get',
|
||||
onSuccess : after,
|
||||
@ -156,6 +184,11 @@ TreeDropdownField.prototype = {
|
||||
})
|
||||
},
|
||||
|
||||
filter: function() {
|
||||
if (this.humanItems.nodeName != 'INPUT' || !this.filtered) return null;
|
||||
return this.humanItems.value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called once the tree has been delivered from ajax
|
||||
*/
|
||||
@ -196,6 +229,7 @@ TreeDropdownField.prototype = {
|
||||
var ajaxURL = this.options.dropdownField.helperURLBase() + 'tree/' + this.getIdx();
|
||||
ajaxURL += $('SecurityID') ? '&SecurityID=' + $('SecurityID').value : '';
|
||||
if($('Form_EditForm_Locale')) ajaxURL += "&locale=" + $('Form_EditForm_Locale').value;
|
||||
if (this.filter() != null) ajaxURL += "&filter=" + this.filter();
|
||||
|
||||
new Ajax.Request(ajaxURL, {
|
||||
onSuccess : this.installSubtree.bind(this),
|
||||
@ -225,21 +259,35 @@ TreeDropdownField.prototype = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updateTreeLabel: function() {
|
||||
if (this.humanItems.nodeName == 'INPUT') return; // don't update the filter
|
||||
var treeNode;
|
||||
if(treeNode = $('selector-' + this.getName() + '-' + this.inputTag.value)) {
|
||||
this.humanItems.innerHTML = treeNode.getTitle();
|
||||
this.setHumanText(treeNode.getTitle());
|
||||
|
||||
if(treeNode.tree.selected && treeNode.tree.selected.removeNodeClass) treeNode.tree.selected.removeNodeClass('current');
|
||||
treeNode.addNodeClass('current');
|
||||
this.tree.selected = treeNode;
|
||||
|
||||
} else {
|
||||
this.humanItems.innerHTML = this.inputTag.value ? this.inputTag.value : '(Choose)';
|
||||
this.setHumanText(this.inputTag.value ? this.inputTag.value : '(Choose)');
|
||||
}
|
||||
},
|
||||
|
||||
getHumanText: function() {
|
||||
return this.humanItems.nodeName == 'INPUT' ? this.humanItems.value : this.humanItems.innerHTML;
|
||||
},
|
||||
|
||||
setHumanText: function (s) {
|
||||
if (this.humanItems.nodeName == 'INPUT')
|
||||
this.humanItems.value = s;
|
||||
else
|
||||
this.humanItems.innerHTML = s;
|
||||
},
|
||||
|
||||
setValueFromTree: function(treeID, title) {
|
||||
this.humanItems.innerHTML = title;
|
||||
this.setHumanText(title);
|
||||
this.inputTag.value = treeID.replace('selector-' + this.getName() + '-','');
|
||||
jQuery(this).trigger('ss.TreeDropdownField.change', {val: this.inputTag.value});
|
||||
this.notify('Change', this.inputTag.value);
|
||||
@ -248,9 +296,40 @@ TreeDropdownField.prototype = {
|
||||
},
|
||||
|
||||
edit_click : function() {
|
||||
if (this.treeDropdownField.treeShown) this.treeDropdownField.restoreOriginalState();
|
||||
this.treeDropdownField.toggleTree();
|
||||
return false;
|
||||
},
|
||||
|
||||
filter_onkeyup: function(e) {
|
||||
if(typeof window.event!="undefined") e=window.event; //code for IE
|
||||
if (e.keyCode == 27) { // esc, cancel the selection and hide the tree.
|
||||
this.treeDropdownField.restoreOriginalState();
|
||||
this.treeDropdownField.hideTree();
|
||||
}
|
||||
else {
|
||||
this.treeDropdownField.filtered = true;
|
||||
this.treeDropdownField.deleteTreeNode();
|
||||
this.treeDropdownField.showTree();
|
||||
}
|
||||
},
|
||||
|
||||
human_click: function() {
|
||||
if (this.treeDropdownField.humanItems.nodeName != 'INPUT') {
|
||||
if (this.treeDropdownField.treeShown) this.treeDropdownField.restoreOriginalState();
|
||||
this.treeDropdownField.toggleTree();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.treeDropdownField.treeShown) this.treeDropdownField.toggleTree();
|
||||
if (!this.treeDropdownField.defaultCleared) {
|
||||
this.treeDropdownField.defaultCleared = true;
|
||||
this.treeDropdownField.setHumanText('');
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
tree_click : function() {
|
||||
this.options.dropdownField.setValueFromTree(this.id, this.getTitle());
|
||||
|
||||
@ -303,7 +382,7 @@ TreeMultiselectField.prototype = {
|
||||
}
|
||||
|
||||
this.inputTag.value = internalVal;
|
||||
this.humanItems.innerHTML = humanVal;
|
||||
this.setHumanText(humanVal);
|
||||
},
|
||||
|
||||
updateTreeLabel: function() {
|
||||
@ -319,9 +398,9 @@ TreeMultiselectField.prototype = {
|
||||
innerHTML += selectedItems[i];
|
||||
}
|
||||
}
|
||||
this.humanItems.innerHTML = innerHTML;
|
||||
this.setHumanText(innerHTML);
|
||||
} else {
|
||||
this.humanItems.innerHTML = '(Choose)';
|
||||
this.setHumanText('(Choose)');
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user