From ab8de1d83f3c7aa11588d5e60c0aca8ed5e1f885 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 3 Nov 2017 14:57:56 +0530 Subject: [PATCH] New Control: MultiSelect (#4425) * New Control: MultiSelect * fix codacy --- frappe/public/build.json | 3 +- frappe/public/css/list.css | 3 ++ .../js/frappe/form/controls/autocomplete.js | 38 ++++++++++--------- .../js/frappe/form/controls/multiselect.js | 29 ++++++++++++++ 4 files changed, 54 insertions(+), 19 deletions(-) create mode 100644 frappe/public/js/frappe/form/controls/multiselect.js diff --git a/frappe/public/build.json b/frappe/public/build.json index 097a6f043a..8c30328c19 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -54,7 +54,8 @@ "public/js/frappe/form/controls/heading.js", "public/js/frappe/form/controls/autocomplete.js", "public/js/frappe/form/controls/barcode.js", - "public/js/frappe/form/controls/geolocation.js" + "public/js/frappe/form/controls/geolocation.js", + "public/js/frappe/form/controls/multiselect.js" ], "js/dialog.min.js": [ "public/js/frappe/dom.js", diff --git a/frappe/public/css/list.css b/frappe/public/css/list.css index ece1c80a82..b3e8862e2a 100644 --- a/frappe/public/css/list.css +++ b/frappe/public/css/list.css @@ -34,11 +34,14 @@ } .set-filters .btn-group { margin-right: 10px; + white-space: nowrap; + font-size: 0; } .set-filters .btn-group .btn-default { background-color: transparent; border: 1px solid #d1d8dd; color: #8D99A6; + float: none; } .filter-box { border-bottom: 1px solid #d1d8dd; diff --git a/frappe/public/js/frappe/form/controls/autocomplete.js b/frappe/public/js/frappe/form/controls/autocomplete.js index b898860f23..9a4c5ca5b5 100644 --- a/frappe/public/js/frappe/form/controls/autocomplete.js +++ b/frappe/public/js/frappe/form/controls/autocomplete.js @@ -2,30 +2,32 @@ frappe.ui.form.ControlAutocomplete = frappe.ui.form.ControlData.extend({ make_input() { this._super(); this.setup_awesomplete(); + this.set_options(); }, - setup_awesomplete() { - var me = this; + set_options() { + if (this.df.options) { + let options = this.df.options || []; + if(typeof options === 'string') { + options = options.split('\n'); + } + this._data = options; + } + }, - this.awesomplete = new Awesomplete(this.input, { + get_awesomplete_settings() { + return { minChars: 0, maxItems: 99, autoFirst: true, - list: this.get_data(), - data: function (item) { - if (typeof item === 'string') { - item = { - label: item, - value: item - }; - } - - return { - label: item.label || item.value, - value: item.value - }; - } - }); + list: this.get_data() + }; + }, + + setup_awesomplete() { + var me = this; + + this.awesomplete = new Awesomplete(this.input, this.get_awesomplete_settings()); $(this.input_area).find('.awesomplete ul').css('min-width', '100%'); diff --git a/frappe/public/js/frappe/form/controls/multiselect.js b/frappe/public/js/frappe/form/controls/multiselect.js new file mode 100644 index 0000000000..4b6984595e --- /dev/null +++ b/frappe/public/js/frappe/form/controls/multiselect.js @@ -0,0 +1,29 @@ +frappe.ui.form.ControlMultiSelect = frappe.ui.form.ControlAutocomplete.extend({ + get_awesomplete_settings() { + const settings = this._super(); + + return Object.assign(settings, { + filter: function(text, input) { + return Awesomplete.FILTER_CONTAINS(text, input.match(/[^,]*$/)[0]); + }, + + item: function(text, input) { + return Awesomplete.ITEM(text, input.match(/[^,]*$/)[0]); + }, + + replace: function(text) { + const before = this.input.value.match(/^.+,\s*|/)[0]; + this.input.value = before + text + ", "; + } + }); + }, + + get_data() { + const value = this.get_value() || ''; + const values = value.split(', ').filter(d => d); + const data = this._super(); + + // return values which are not already selected + return data.filter(d => !values.includes(d)); + } +});