diff --git a/src/main/java/at/ac/uibk/course/CreateCourseRepositoryEntryController.java b/src/main/java/at/ac/uibk/course/CreateCourseRepositoryEntryController.java index f47d6d153d3de752f7257992a492f6c2a43d53fc..adaceb9acbb5c8c64b1d198bcbf0db911f16409f 100644 --- a/src/main/java/at/ac/uibk/course/CreateCourseRepositoryEntryController.java +++ b/src/main/java/at/ac/uibk/course/CreateCourseRepositoryEntryController.java @@ -245,7 +245,7 @@ public class CreateCourseRepositoryEntryController extends FormBasicController autocompleterC = new FlexiAutoCompleterController(ureq, getWindowControl(), provider, translator.translate("form.autocomplete.not.found"), false, - true, 60, 3, null, mainForm); + true, 60, 0, null, mainForm, true, true, true, 10); autocompleterC.setFormElement(false); listenTo(autocompleterC); diff --git a/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/AutoCompleterController.java b/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/AutoCompleterController.java index d1c85ebcbc2966bc28d895355b3ad8289774ed72..97dbd8aedd2069e8f01c7a662a83f05991c191a2 100644 --- a/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/AutoCompleterController.java +++ b/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/AutoCompleterController.java @@ -115,7 +115,10 @@ public class AutoCompleterController extends BasicController { myContent.contextPut("minChars", Integer.valueOf(minChars)); myContent.contextPut("inputValue", ""); myContent.contextPut("inputClear", Boolean.FALSE); + myContent.contextPut("inputDropdown", Boolean.FALSE); myContent.contextPut("inputReadonly", Boolean.FALSE); + myContent.contextPut("highlight", Boolean.FALSE); + myContent.contextPut("limit", 5); // Create a mapper for the server responses for a given input mapper = new AutoCompleterMapper(noResults, showDisplayKey, gprovider); diff --git a/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/FlexiAutoCompleterController.java b/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/FlexiAutoCompleterController.java index 9e8d7d5652e540e8211c0966512bb6724b8827d6..80cf77eb692e4c2595228ee96d862d96b617b9c3 100644 --- a/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/FlexiAutoCompleterController.java +++ b/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/FlexiAutoCompleterController.java @@ -74,8 +74,13 @@ public class FlexiAutoCompleterController extends FormBasicController { private boolean allowNewValues; private boolean formElement; + private boolean showClear = false; + private boolean showDropdown = false; + private boolean highlight = false; + private int limit = 5; + /** - * Constructor to create an auto completer controller + * Constructor to create an auto completer controller (deprecated) * * @param ureq * The user request object @@ -97,6 +102,8 @@ public class FlexiAutoCompleterController extends FormBasicController { * The minimum number of characters the user has to enter to * perform a search * @param label + * The label of the form element + * @deprecated */ public FlexiAutoCompleterController(UserRequest ureq, WindowControl wControl, ListProvider provider, String noresults, final boolean showDisplayKey, int inputWidth, int minChars, String label) { @@ -106,12 +113,57 @@ public class FlexiAutoCompleterController extends FormBasicController { setupAutoCompleter(ureq, flc, noresults, showDisplayKey, inputWidth, minChars, label); setFormElement(true); } - + + /** + * Constructor to create an auto completer controller + * + * @param ureq + * The user request object + * @param wControl + * The window control object + * @param provider + * The provider that can be called to return the search-results + * for a given search query + * @param noResults + * The translated value to display when no results are found, + * e.g. "no matches found" or "-no users found-". When a NULL + * value is provided, the controller will use a generic message. + * @param showDisplayKey + * true: show the key for each record; false: don't show the key, + * only the value + * @param allowNewValues + * true: allow values not in the suggested items list + * @param inputWidth + * The input field width in characters + * @param minChars + * The minimum number of characters the user has to enter to + * perform a search + * @param label + * The label of the form element + * @param externalMainForm + * The form this AutoCompleter controller is embedded into + */ public FlexiAutoCompleterController(UserRequest ureq, WindowControl wControl, ListProvider provider, String noresults, final boolean showDisplayKey, final boolean allowNewValues, int inputWidth, int minChars, String label, Form externalMainForm) { super(ureq, wControl, LAYOUT_CUSTOM, "autocomplete", externalMainForm); + setup(ureq, provider, noresults, showDisplayKey, allowNewValues, inputWidth, minChars, label, false, false, false, 5); + } + + public FlexiAutoCompleterController(UserRequest ureq, WindowControl wControl, ListProvider provider, String noresults, + final boolean showDisplayKey, final boolean allowNewValues, int inputWidth, int minChars, String label, Form externalMainForm, + final boolean showClear, final boolean showDropdown, final boolean highlight, int limit) { + super(ureq, wControl, LAYOUT_CUSTOM, "autocomplete", externalMainForm); + setup(ureq, provider, noresults, showDisplayKey, allowNewValues, inputWidth, minChars, label, showClear, showDropdown, highlight, limit); + } + + protected void setup(UserRequest ureq, ListProvider provider, String noresults, boolean showDisplayKey, boolean allowNewValues, + int inputWidth, int minChars, String label, boolean showClear, boolean showDropdown, boolean highlight, int limit) { this.gprovider = provider; this.allowNewValues = allowNewValues; + this.showClear = showClear; + this.showDropdown = showDropdown; + this.highlight = highlight; + this.limit = limit; setupAutoCompleter(ureq, flc, noresults, showDisplayKey, inputWidth, minChars, label); setFormElement(true); } @@ -158,7 +210,10 @@ public class FlexiAutoCompleterController extends FormBasicController { layoutCont.contextPut("flexi", Boolean.TRUE); layoutCont.contextPut("inputValue", ""); layoutCont.contextPut("inputClear", Boolean.FALSE); - layoutCont.contextPut("inputReadonly", Boolean.FALSE); + layoutCont.contextPut("inputDropdown", showDropdown); + layoutCont.contextPut("inputReadonly", Boolean.FALSE); + layoutCont.contextPut("highlight", highlight); + layoutCont.contextPut("limit", limit); layoutCont.getComponent().addListener(this); // Create a mapper for the server responses for a given input @@ -190,6 +245,7 @@ public class FlexiAutoCompleterController extends FormBasicController { } else if (event.getCommand().equals(COMMAND_CHANGE)) { flc.contextPut("inputReadonly", Boolean.FALSE); flc.contextPut("inputClear", Boolean.FALSE); + flc.contextPut("inputDropdown", showDropdown); if(allowNewValues) { fireEvent(ureq, new NewValueChosenEvent(value)); } else { @@ -240,10 +296,12 @@ public class FlexiAutoCompleterController extends FormBasicController { // Normal case, add entry selectedEntries.add(key); flc.contextPut("inputReadonly", Boolean.TRUE); - flc.contextPut("inputClear", Boolean.TRUE); + flc.contextPut("inputClear", showClear); + flc.contextPut("inputDropdown", (!showClear) && showDropdown); } else if (key.equals(AUTOCOMPLETER_NO_RESULT)) { flc.contextPut("inputReadonly", Boolean.FALSE); flc.contextPut("inputClear", Boolean.FALSE); + flc.contextPut("inputDropdown", showDropdown); return; } doFireSelection(ureq, selectedEntries); diff --git a/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/_content/autocomplete.html b/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/_content/autocomplete.html index 80ef5539e381bf5add61a1e36834ff736aa8b688..80a19ff2ce287a879a33a27909397c59abcf4c74 100644 --- a/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/_content/autocomplete.html +++ b/src/main/java/org/olat/core/gui/control/generic/ajax/autocompletion/_content/autocomplete.html @@ -1,4 +1,4 @@ -<div class="o_form_auto_completer"> +<div class="o_form_auto_completer form-inline"> #if($flexi) <div id='$r.getId("aj_ac_f")'> #else @@ -7,10 +7,15 @@ #if ($autocompleter_label) $autocompleter_label #end - <div class="$formElementClass"> + <div class="#if($inputClear || $inputDropdown)input-group#{end} $formElementClass"> <input type="text" size="$inputWidth" #if($inputReadonly)readonly="true"#{end} value="$inputValue" class="form-control" name='$r.getId("o_autocomplete_input")' id='$r.getId("o_autocomplete_input")' /> - <i id='$r.getId("o_autocomplete_input")_remove' class="#if(!$inputClear)hidden #{end}o_icon o_icon-fw o_icon_remove"></i> - </div> + #if($inputClear || $inputDropdown) + <span class="input-group-addon"> + <i id='$r.getId("o_autocomplete_input")_remove' class="#if(!$inputClear)hidden #{end}o_icon o_icon-fw o_icon_remove"></i> + <i id='$r.getId("o_autocomplete_input")_dropdown' class="#if(!$inputDropdown)hidden #{end}o_icon o_icon-fw o_icon_bottom"></i> + </span> + #end + </div> #if($flexi) </div> #else @@ -20,6 +25,7 @@ <script type="text/javascript"> /* <![CDATA[ */ jQuery(function(){ + var current_result_length; var fullNameTypeahead = new Bloodhound({ datumTokenizer: function (d) { return Bloodhound.tokenizers.whitespace(d.value); @@ -29,6 +35,7 @@ jQuery(function(){ url: '${mapuri}?term=%QUERY', wildcard: '%QUERY', filter: function ( response ) { + current_result_length = response.length; return jQuery.map(response, function (object) { return { cssClass: object.cssClass, @@ -46,19 +53,29 @@ jQuery(function(){ fullNameTypeahead.initialize(); jQuery('#$r.getId("o_autocomplete_input")').typeahead({ hint: false, - highlight: false, - minLength: 3 + highlight: ${highlight}, + minLength: ${minChars} },{ - minLength: 3, + minLength: ${minChars}, displayKey: 'fullName', source: fullNameTypeahead.ttAdapter(), + limit: ${limit}, templates: { #if ($autocompleter_emptymessage) empty: [ '<div>','$autocompleter_emptymessage','</div>' ].join('\n'), #end - suggestion: function(obj) {return "<div class='"+obj.cssClass+"'>"+obj.fullName+"</div>"} + suggestion: function(obj) {return "<div class='"+obj.cssClass+"'>"+obj.fullName+"</div>"}, + footer: function(obj,test) { + console.log(obj); + if (current_result_length > obj.suggestions.length) { + return "<div class='tt-suggestion o_disabled'> ... " + + ((current_result_length - obj.suggestions.length > 9) ? "mehr als 9" : (current_result_length - obj.suggestions.length)) + + " weitere Kurse" + + " ... </div>"; + } + } } }).on('typeahead:render', function (e) { // disabled and error items should not be selectable @@ -87,6 +104,10 @@ jQuery(function(){ $r.openJavaScriptCommand("change"),'key','', '$r.getId("o_autocomplete_input")',''); }); + jQuery('#$r.getId("o_autocomplete_input")_dropdown').on('click', function(e) { + jQuery('#$r.getId("o_autocomplete_input")').typeahead('val','*'); + jQuery('#$r.getId("o_autocomplete_input")').typeahead('open'); + }); }); /* ]]> */ </script> \ No newline at end of file diff --git a/src/main/webapp/static/themes/light/modules/_autocomplete.scss b/src/main/webapp/static/themes/light/modules/_autocomplete.scss index 9b0c64972bced2722b32faf7636a97db78cde9d7..d6387cedb92e295f155bae4719f89789a32e7772 100644 --- a/src/main/webapp/static/themes/light/modules/_autocomplete.scss +++ b/src/main/webapp/static/themes/light/modules/_autocomplete.scss @@ -3,7 +3,7 @@ } .tt-menu { - width: $o-autocomplete-width; + width: 100%; margin-top: $padding-base-vertical; padding: 0 0 0; color: $o-autocomplete-color; @@ -33,3 +33,13 @@ .tt-menu div.o_icon_error:before { content:''; } + +// bootstrap fix for typeahead wrapper +.twitter-typeahead { + width: 100%; + float: left; + .input-group & { + //overwrite `display:inline-block` style + display: table-cell!important; + } +} diff --git a/src/main/webapp/static/themes/light/modules/_icons.scss b/src/main/webapp/static/themes/light/modules/_icons.scss index 22bd885d4a445e37f5bb1b3120c7fcc5e9f18aef..56103d64a99657a96af08ace15fa47389eeba9d0 100644 --- a/src/main/webapp/static/themes/light/modules/_icons.scss +++ b/src/main/webapp/static/themes/light/modules/_icons.scss @@ -236,6 +236,7 @@ $fa-css-prefix: "o_icon" !default; .o_icon_tool:before { content: $fa-var-gear; } .o_icon_tools:before { content: $fa-var-wrench; } .o_icon_top:before { content: $fa-var-chevron-up; } +.o_icon_bottom:before { content: $fa-var-chevron-down; } .o_icon_translation_item:before { content: $fa-var-file-code-o; } .o_icon_translation_package:before { content: $fa-var-folder-open-o; } .o_icon_user:before { content: $fa-var-user; } @@ -505,4 +506,4 @@ a.o_icon { text-decoration: none; } } - \ No newline at end of file +