From 8b5f89f3b95dd69cd1c0d05322dff0dbbccbee88 Mon Sep 17 00:00:00 2001 From: Naomi Guyer Date: Thu, 29 Aug 2013 16:21:04 +1200 Subject: [PATCH] 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) --- css/TreeDropdownField.css | 16 +++++++-- docs/en/changelogs/3.1.1.md | 26 ++++++++++++++ forms/TreeDropdownField.php | 8 +++-- javascript/TreeDropdownField.js | 48 ++++++++++++------------- scss/TreeDropdownField.scss | 63 ++++++++++++++++++++++++++++++--- 5 files changed, 125 insertions(+), 36 deletions(-) create mode 100644 docs/en/changelogs/3.1.1.md diff --git a/css/TreeDropdownField.css b/css/TreeDropdownField.css index dfd84351e..0bb1aeb1f 100644 --- a/css/TreeDropdownField.css +++ b/css/TreeDropdownField.css @@ -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 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-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-panel.loading { min-height: 30px; background: white url("../images/network-save.gif") 7px 7px no-repeat; } +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-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.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 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; } diff --git a/docs/en/changelogs/3.1.1.md b/docs/en/changelogs/3.1.1.md new file mode 100644 index 000000000..5d87589d2 --- /dev/null +++ b/docs/en/changelogs/3.1.1.md @@ -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(); + diff --git a/forms/TreeDropdownField.php b/forms/TreeDropdownField.php index c793b9549..121735e9b 100644 --- a/forms/TreeDropdownField.php +++ b/forms/TreeDropdownField.php @@ -86,7 +86,7 @@ class TreeDropdownField extends FormField { * entering the text in the input field. */ public function __construct($name, $title = null, $sourceObject = 'Group', $keyField = 'ID', - $labelField = 'TreeTitle', $showSearch = false + $labelField = 'TreeTitle', $showSearch = true ) { $this->sourceObject = $sourceObject; @@ -181,7 +181,11 @@ class TreeDropdownField extends FormField { if($record) { $title = $record->{$this->labelField}; } 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 diff --git a/javascript/TreeDropdownField.js b/javascript/TreeDropdownField.js index 1b46d96c6..340fc1098 100644 --- a/javascript/TreeDropdownField.js +++ b/javascript/TreeDropdownField.js @@ -24,8 +24,8 @@ var strings = { 'openlink': 'Open', - 'fieldTitle': '(choose)', - 'searchFieldTitle': '(choose or search)' + 'fieldTitle': '(Choose)', + 'searchFieldTitle': '(Choose or Search)' }; var _clickTestFn = function(e) { @@ -280,24 +280,14 @@ $('.TreeDropdownField.searchable').entwine({ onadd: function() { this._super(); - - var title = decodeURIComponent(this.data('title')); - this.find('.treedropdownfield-title').replaceWith( - $('') + var title = ss.i18n._t( + 'DropdownField.ENTERTOSEARCH', + 'Press enter to search' + ); + + this.find('.treedropdownfield-panel').prepend( + $('') ); - - 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) { this.openPanel(); @@ -306,18 +296,24 @@ cancelSearch: function() { this.closePanel(); 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({ - onfocusin: function(e) { - var field = this.getField(); - field.setTitle(''); + onfocusin: function(){ + //IE placeholder support + this.val(''); }, - onfocusout: function(e) { - var field = this.getField(); - field.resetTitle(); + onfocusout: function(){ + //IE placeholder support + var value = this.closest('.TreeDropdownField').getValue(this.attr('placeholder')); + if(this.val() === ''){ + this.val(value); + } }, onkeydown: function(e) { var field = this.getField(); diff --git a/scss/TreeDropdownField.scss b/scss/TreeDropdownField.scss index 576854a06..b278eeab2 100755 --- a/scss/TreeDropdownField.scss +++ b/scss/TreeDropdownField.scss @@ -1,3 +1,6 @@ +@import 'compass'; +@import "../admin/scss/_mixins"; + div.TreeDropdownField { width: 400px; background: #fff; @@ -20,20 +23,49 @@ div.TreeDropdownField { line-height: 16px; overflow:hidden; 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 { 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; + z-index: 70; -webkit-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); @@ -41,12 +73,33 @@ div.TreeDropdownField { &.loading { 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 { margin: 0; - a { font-size: 12px; }