API: Treedropdownfield showsearch default true, provide better ui

Set search option true on treedropdown fields by default, to provide a
fallback solution when trees fail to render (too many children errors)

Provide better indication/more meaningful styling to search (match
chosen styles for consistency)
This commit is contained in:
Naomi Guyer 2013-08-29 16:21:04 +12:00
parent 4af619e5a0
commit 8b5f89f3b9
5 changed files with 125 additions and 36 deletions

View File

@ -1,8 +1,18 @@
/*Mixin used to generate slightly smaller text and forms
Used in side panels and action tabs
*/
div.TreeDropdownField { width: 400px; background: #fff; border: 1px solid #aaa; cursor: pointer; overflow: visible; position: relative; } div.TreeDropdownField { width: 400px; background: #fff; border: 1px solid #aaa; cursor: pointer; overflow: visible; position: relative; }
div.TreeDropdownField input { border: none; background: none; padding: 0; margin: 0; } div.TreeDropdownField input { border: none; background: none; padding: 0; margin: 0; }
div.TreeDropdownField .treedropdownfield-title { float: left; padding: 7px; width: 90%; line-height: 16px; overflow: hidden; outline: none; } div.TreeDropdownField .treedropdownfield-title, div.TreeDropdownField .treedropdownfield-search { float: left; padding: 7px; width: 90%; line-height: 16px; overflow: hidden; outline: none; z-index: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; }
div.TreeDropdownField .treedropdownfield-panel { clear: left; position: absolute; overflow: auto; display: none; cursor: default; border: 1px solid #aaa; border-top: none; margin: 1px 0 0 -1px; /* account for border on container div */ max-height: 200px; background-color: #fff; z-index: 50; -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); -o-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); } div.TreeDropdownField .treedropdownfield-search { background: url("../admin/thirdparty/chosen/chosen/chosen-sprite.png") no-repeat 100% -22px; background: url("../admin/thirdparty/chosen/chosen/chosen-sprite.png") no-repeat 100% -22px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); background: url("../admin/thirdparty/chosen/chosen/chosen-sprite.png") no-repeat 100% -22px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%); background: url("../admin/thirdparty/chosen/chosen/chosen-sprite.png") no-repeat 100% -22px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%); background: url("../admin/thirdparty/chosen/chosen/chosen-sprite.png") no-repeat 100% -22px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%); background: url("../admin/thirdparty/chosen/chosen/chosen-sprite.png") no-repeat 100% -22px, linear-gradient(top, #eeeeee 1%, #ffffff 15%); -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; position: relative; z-index: 1100; border: 1px solid #aaa; display: inline-block; font-family: sans-serif; font-size: 1em; margin: 1.5%; outline: 0; padding: 4px 20px 4px 5px; width: 97%; }
div.TreeDropdownField .treedropdownfield-panel.loading { min-height: 30px; background: white url("../images/network-save.gif") 7px 7px no-repeat; } div.TreeDropdownField.searchable .treedropdownfield-panel.loading { min-height: 64px; background-position: 98% 39px; }
div.TreeDropdownField .treedropdownfield-panel { clear: left; position: absolute; display: none; cursor: default; border: 1px solid #aaa; border-top: none; margin: 1px 0 0 -1px; /* account for border on container div */ background-color: #fff; z-index: 70; -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); -o-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); }
div.TreeDropdownField .treedropdownfield-panel.loading { min-height: 30px; background: white url("../images/network-save.gif") 98% 7px no-repeat; }
div.TreeDropdownField .treedropdownfield-panel .tree-holder { position: relative; z-index: 1; }
div.TreeDropdownField .treedropdownfield-panel .tree-holder > ul { position: relative; max-height: 200px; overflow-y: auto; }
div.TreeDropdownField .treedropdownfield-panel ul { overflow-x: hidden; float: left; width: 100%; }
div.TreeDropdownField .treedropdownfield-panel ul .jstree-icon { margin-left: 5px; }
div.TreeDropdownField .treedropdownfield-panel ul .jstree-open > ins { background-position: -18px 0; }
div.TreeDropdownField .treedropdownfield-panel ul.tree { margin: 0; } div.TreeDropdownField .treedropdownfield-panel ul.tree { margin: 0; }
div.TreeDropdownField .treedropdownfield-panel ul.tree a { font-size: 12px; } div.TreeDropdownField .treedropdownfield-panel ul.tree a { font-size: 12px; }
div.TreeDropdownField .treedropdownfield-toggle-panel-link { border: none; margin: 0; z-index: 0; padding: 7px 3px; overflow: hidden; -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } div.TreeDropdownField .treedropdownfield-toggle-panel-link { border: none; margin: 0; z-index: 0; padding: 7px 3px; overflow: hidden; -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; }

View File

@ -0,0 +1,26 @@
# 3.1.1 (unreleased)
## Overview ##
### CMS
### Framework
* Treedropdownfield showsearch defaults to true
## Details
## Upgrading
### Treedropdownfield showsearch defaults to true
The showSearch option of TreedropdownField is now set to true by default. This is to provide a fallback ui for when children of a tree node fail to render (due to too many children). You may set search as false when initializing a TreedropdownField, or afterwards:
:::php
$treedropdownfield->setShowSearch(false);
If your data requires a specialized search function, you may specify it within:
:::php
$treedropdownfield->setSearchFunction();

View File

@ -86,7 +86,7 @@ class TreeDropdownField extends FormField {
* entering the text in the input field. * entering the text in the input field.
*/ */
public function __construct($name, $title = null, $sourceObject = 'Group', $keyField = 'ID', public function __construct($name, $title = null, $sourceObject = 'Group', $keyField = 'ID',
$labelField = 'TreeTitle', $showSearch = false $labelField = 'TreeTitle', $showSearch = true
) { ) {
$this->sourceObject = $sourceObject; $this->sourceObject = $sourceObject;
@ -181,7 +181,11 @@ class TreeDropdownField extends FormField {
if($record) { if($record) {
$title = $record->{$this->labelField}; $title = $record->{$this->labelField};
} else { } else {
$title = _t('DropdownField.CHOOSE', '(Choose)', 'start value of a dropdown'); if($this->showSearch){
$title = _t('DropdownField.CHOOSESEARCH', '(Choose or Search)', 'start value of a dropdown');
}else{
$title = _t('DropdownField.CHOOSE', '(Choose)', 'start value of a dropdown');
}
} }
// TODO Implement for TreeMultiSelectField // TODO Implement for TreeMultiSelectField

View File

@ -24,8 +24,8 @@
var strings = { var strings = {
'openlink': 'Open', 'openlink': 'Open',
'fieldTitle': '(choose)', 'fieldTitle': '(Choose)',
'searchFieldTitle': '(choose or search)' 'searchFieldTitle': '(Choose or Search)'
}; };
var _clickTestFn = function(e) { var _clickTestFn = function(e) {
@ -280,24 +280,14 @@
$('.TreeDropdownField.searchable').entwine({ $('.TreeDropdownField.searchable').entwine({
onadd: function() { onadd: function() {
this._super(); this._super();
var title = ss.i18n._t(
'DropdownField.ENTERTOSEARCH',
'Press enter to search'
);
var title = decodeURIComponent(this.data('title')); this.find('.treedropdownfield-panel').prepend(
this.find('.treedropdownfield-title').replaceWith( $('<input type="text" class="search treedropdownfield-search" data-skip-autofocus="true" placeholder="' + title + '" value="' + this.getValue(title) + '" />')
$('<input type="text" class="treedropdownfield-title search" data-skip-autofocus="true" />')
); );
this.setTitle(title ? title : strings.searchFieldTitle);
},
setTitle: function(title) {
if(!title && title !== '') title = strings.fieldTitle;
this.find('.treedropdownfield-title').val(title);
},
getTitle: function() {
return this.find('.treedropdownfield-title').val();
},
resetTitle: function() {
this.setTitle(decodeURIComponent(this.data('title')));
}, },
search: function(str, callback) { search: function(str, callback) {
this.openPanel(); this.openPanel();
@ -306,18 +296,24 @@
cancelSearch: function() { cancelSearch: function() {
this.closePanel(); this.closePanel();
this.loadTree(); this.loadTree();
this.resetTitle(); },
getValue: function(title){
//Provide value for IE8 and 9 as they don't support placeholders
return ($.browser.msie && parseInt($.browser.version, 10) <= 9) ? title:'';
} }
}); });
$('.TreeDropdownField.searchable input.search').entwine({ $('.TreeDropdownField.searchable input.search').entwine({
onfocusin: function(e) { onfocusin: function(){
var field = this.getField(); //IE placeholder support
field.setTitle(''); this.val('');
}, },
onfocusout: function(e) { onfocusout: function(){
var field = this.getField(); //IE placeholder support
field.resetTitle(); var value = this.closest('.TreeDropdownField').getValue(this.attr('placeholder'));
if(this.val() === ''){
this.val(value);
}
}, },
onkeydown: function(e) { onkeydown: function(e) {
var field = this.getField(); var field = this.getField();

View File

@ -1,3 +1,6 @@
@import 'compass';
@import "../admin/scss/_mixins";
div.TreeDropdownField { div.TreeDropdownField {
width: 400px; width: 400px;
background: #fff; background: #fff;
@ -20,20 +23,49 @@ div.TreeDropdownField {
line-height: 16px; line-height: 16px;
overflow:hidden; overflow:hidden;
outline: none; outline: none;
z-index:1;
@include hide-text-overflow;
}
.treedropdownfield-search{
@extend .treedropdownfield-title;
//Style search box to match chosen search
$bgImage: '../admin/thirdparty/chosen/chosen/chosen-sprite.png';
background:url($bgImage) no-repeat 100% -22px; //For browers that only support 1 background
@include background(
url($bgImage) no-repeat 100% -22px,
linear-gradient(top, #eeeeee 1%, #ffffff 15%)
);
@include box-sizing(border-box);
position:relative;
z-index:1100; //Needed to work within modales in chrome
border: 1px solid #aaa;
display:inline-block;
font-family: sans-serif;
font-size: 1em;
margin:1.5%;
outline: 0;
padding: 4px 20px 4px 5px;
width:97%; //optimized for most common tree width
}
&.searchable .treedropdownfield-panel.loading{
min-height: 16px /* icon */ + 14px /* padding */ + 34px /* approx height search input */; // Ensure there's room for loading indicator
background-position: 98% 39px;
} }
.treedropdownfield-panel { .treedropdownfield-panel {
clear: left; clear: left;
position: absolute; position: absolute;
overflow: auto;
display: none; display: none;
cursor: default; cursor: default;
border: 1px solid #aaa; border: 1px solid #aaa;
border-top: none; border-top: none;
margin: 1px 0 0 -1px; /* account for border on container div */ margin: 1px 0 0 -1px; /* account for border on container div */
max-height:200px;
background-color: #fff; background-color: #fff;
z-index: 50; z-index: 70;
-webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15); -webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15);
-moz-box-shadow : 0 4px 5px rgba(0,0,0,.15); -moz-box-shadow : 0 4px 5px rgba(0,0,0,.15);
-o-box-shadow : 0 4px 5px rgba(0,0,0,.15); -o-box-shadow : 0 4px 5px rgba(0,0,0,.15);
@ -41,12 +73,33 @@ div.TreeDropdownField {
&.loading { &.loading {
min-height: 16px /* icon */ + 14px /* padding */; // Ensure there's room for loading indicator min-height: 16px /* icon */ + 14px /* padding */; // Ensure there's room for loading indicator
background: #fff url("../images/network-save.gif") 7px 7px no-repeat; background: #fff url("../images/network-save.gif") 98% 7px no-repeat;
}
.tree-holder{
position:relative;
z-index:1;
> ul{
position:relative;
max-height:200px;
overflow-y: auto;
}
}
ul{
overflow-x:hidden;
float:left;
width:100%;
.jstree-icon{
margin-left:5px; //move to align with possible search box
}
.jstree-open > ins{
background-position:-18px 0; //move to align with possible search box
}
} }
ul.tree { ul.tree {
margin: 0; margin: 0;
a { a {
font-size: 12px; font-size: 12px;
} }