diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index da67fd60196..26ee5613dc5 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -74,7 +74,6 @@ "static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css", "static/lib/jquery.ui.notify/css/ui.notify.css", "static/lib/jquery.tipsy/tipsy.css", - "static/lib/jquery.textext/jquery.textext.css", "static/lib/visualsearch/lib/css/reset.css", "static/lib/visualsearch/lib/css/workspace.css", "static/lib/visualsearch/lib/css/icons.css", diff --git a/addons/web/static/lib/jquery.textext/jquery.textext.css b/addons/web/static/lib/jquery.textext/jquery.textext.css deleted file mode 100644 index e4f2dbc193a..00000000000 --- a/addons/web/static/lib/jquery.textext/jquery.textext.css +++ /dev/null @@ -1,186 +0,0 @@ -.text-core { - position: relative; -} - -.text-core .text-wrap { - position: absolute; - width: 100% !important; -} -.text-core .text-wrap textarea { - resize: none !important; -} - -.text-core .text-wrap textarea, .text-core .text-wrap input { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-border-radius: 0px; - -moz-border-radius: 0px; - border-radius: 0px; - outline: none; - resize: none; - position: absolute; - background: none; - overflow: hidden; - margin: 0; - padding: 3px 5px 4px 5px; - white-space: nowrap; - line-height: 13px; - width: 100% !important; -} - -.extra_suggestions { - border-top: 1px solid #9daccc !important; -} - -.text-core .text-wrap .text-arrow { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - position: absolute; - top: 0; - right: 0; - width: 22px; - height: 22px; - background: url("/web/static/src/img/down-arrow.png") 50% 50% no-repeat; - cursor: pointer; - z-index: 2; -} - -.text-core .text-wrap .text-dropdown { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; - position: absolute; - z-index: 3; - background: #fff; - border: 1px solid #9daccc; - width: 100%; - padding: 1px; - display: none; - overflow-x: hidden; - overflow-y: auto; -} - -.text-core .text-wrap .text-dropdown.text-position-below { - margin-top: 1px; -} - -.text-core .text-wrap .text-dropdown.text-position-above { - margin-bottom: 1px; -} - -.text-core .text-wrap .text-dropdown .text-list .text-suggestion { - padding: 3px 5px; - cursor: pointer; -} - -.text-core .text-wrap .text-dropdown .text-list .text-suggestion em { - font-style: normal; - text-decoration: underline; -} - -.text-core .text-wrap .text-dropdown .text-list .text-suggestion.text-selected { - color: #fff; - background: #0064CD; -} - -.text-core .text-wrap .text-focus { - -webkit-box-shadow: 0px 0px 6px #6d84b4; - -moz-box-shadow: 0px 0px 6px #6d84b4; - box-shadow: 0px 0px 6px #6d84b4; - position: absolute; - display: none; -} - -.text-core .text-wrap .text-focus.text-show-focus { - display: block; -} - -.text-core .text-wrap .text-prompt { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - position: absolute; - width: 100%; - height: 100%; - margin: 1px 0 0 2px; - color: #c0c0c0; - overflow: hidden; - white-space: pre; -} - -.text-core .text-wrap .text-prompt.text-hide-prompt { - display: none; -} - -.text-core .text-wrap .text-tags { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - position: absolute; - width: 100%; - height: 100%; - padding: 3px 35px 3px 3px; - cursor: text; -} - -.text-core .text-wrap .text-tags.text-tags-on-top { - z-index: 2; -} - -.text-core .text-wrap .text-tags .text-tag { - float: left; -} - -.text-core .text-wrap .text-tags .text-tag .text-button { - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - position: relative; - float: left; - border: 1px solid #9daccc; - background: #e2e6f0; - color: #000; - padding: 0px 17px 0px 3px; - margin: 0 2px 2px 0; - cursor: pointer; - height: 18px; -} - -.text-core .text-wrap .text-tags .text-tag .text-button a.text-remove { - position: absolute; - right: 3px; - top: 2px; - display: block; - width: 11px; - height: 11px; - background: url("remove.png") 0 0 no-repeat; -} - -.text-core .text-wrap .text-tags .text-tag .text-button a.text-remove:hover { - background-position: 0 -11px; -} - -.text-core .text-wrap .text-tags .text-tag .text-button a.text-remove:active { - background-position: 0 -22px; -} -.oe_form_field_many2many span { - display: block; - width: auto; - margin: 0 3px 3px 0; - padding: 3px 8px 4px 8px; - position: relative; - float: left; - text-indent: 0; - background-color: #EEE; - border: 1px solid #AAA; - -moz-border-radius: 7px; - -webkit-border-radius: 7px; - border-radius: 7px; - color: #333; -} diff --git a/addons/web/static/lib/jquery.textext/jquery.textext.js b/addons/web/static/lib/jquery.textext/jquery.textext.js index 2a66d33108f..294ceea8c73 100644 --- a/addons/web/static/lib/jquery.textext/jquery.textext.js +++ b/addons/web/static/lib/jquery.textext/jquery.textext.js @@ -1811,7 +1811,7 @@ var self = this; self.baseInit(core, DEFAULT_OPTS); - console.log('on>>>>>', self, core, DEFAULT_OPTS); + self.on({ getSuggestions : self.onGetSuggestions }); @@ -2375,6 +2375,7 @@ }); container + .css('maxHeight', self.opts(OPT_MAX_HEIGHT)) .addClass('text-position-' + self.opts(OPT_POSITION)) ; @@ -3155,9 +3156,7 @@ var self = this, suggestion = self.selectedSuggestionElement().data(CSS_SUGGESTION) ; - if(typeof suggestion == 'object') { - suggestion = suggestion['name']; - } + if(suggestion) { self.val(self.itemManager().itemToString(suggestion)); @@ -4480,8 +4479,7 @@ self.input().css({ paddingLeft : pos.left, - paddingTop : pos.top, - paddingBottom: 4 + paddingTop : pos.top }); }; @@ -4770,8 +4768,163 @@ var self = this, node = $(self.opts(OPT_HTML_TAG)) ; + node.find('.text-label').text(self.itemManager().itemToString(tag)); node.data(CSS_TAG, tag); return node; }; -})(jQuery); \ No newline at end of file +})(jQuery); +;(function(a){var b=document,c="getElementsByTagName",d=b[c]("head")[0]||b[c]("body")[0],e=b.createElement("style");e.innerHTML=a,d.appendChild(e)})('\n.text-core {\ + position: relative;\ +}\ +.text-core .text-wrap {\ + background: #fff;\ + position: absolute;\ +}\ +.text-core .text-wrap textarea, .text-core .text-wrap input {\ + -webkit-box-sizing: border-box;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + -webkit-border-radius: 0px;\ + -moz-border-radius: 0px;\ + border-radius: 0px;\ + border: 1px solid #9daccc;\ + outline: none;\ + resize: none;\ + position: absolute;\ + z-index: 1;\ + background: none;\ + overflow: hidden;\ + margin: 0;\ + padding: 3px 5px 4px 5px;\ + white-space: nowrap;\ + font: 11px "lucida grande", tahoma, verdana, arial, sans-serif;\ + line-height: 13px;\ + height: auto;\ +}\ +\n.text-core .text-wrap .text-arrow {\ + -webkit-box-sizing: border-box;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + position: absolute;\ + top: 0;\ + right: 0;\ + width: 22px;\ + height: 22px;\ + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAOAQMAAADHWqTrAAAAA3NCSVQICAjb4U/gAAAABlBMVEX///8yXJnt8Ns4AAAACXBIWXMAAAsSAAALEgHS3X78AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1MzmNZGAwAAABpJREFUCJljYEAF/xsY6hkY7BgYZBgYOFBkADkdAmFDagYFAAAAAElFTkSuQmCC") 50% 50% no-repeat;\ + cursor: pointer;\ + z-index: 2;\ +}\ +\n.text-core .text-wrap .text-dropdown {\ + -webkit-box-sizing: border-box;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + padding: 0;\ + position: absolute;\ + z-index: 3;\ + background: #fff;\ + border: 1px solid #9daccc;\ + width: 100%;\ + max-height: 100px;\ + padding: 1px;\ + font: 11px "lucida grande", tahoma, verdana, arial, sans-serif;\ + display: none;\ + overflow-x: hidden;\ + overflow-y: auto;\ +}\ +.text-core .text-wrap .text-dropdown.text-position-below {\ + margin-top: 1px;\ +}\ +.text-core .text-wrap .text-dropdown.text-position-above {\ + margin-bottom: 1px;\ +}\ +.text-core .text-wrap .text-dropdown .text-list .text-suggestion {\ + padding: 3px 5px;\ + cursor: pointer;\ +}\ +.text-core .text-wrap .text-dropdown .text-list .text-suggestion em {\ + font-style: normal;\ + text-decoration: underline;\ +}\ +.text-core .text-wrap .text-dropdown .text-list .text-suggestion.text-selected {\ + color: #fff;\ + background: #6d84b4;\ +}\ +\n.text-core .text-wrap .text-focus {\ + -webkit-box-shadow: 0px 0px 6px #6d84b4;\ + -moz-box-shadow: 0px 0px 6px #6d84b4;\ + box-shadow: 0px 0px 6px #6d84b4;\ + position: absolute;\ + width: 100%;\ + height: 100%;\ + display: none;\ +}\ +.text-core .text-wrap .text-focus.text-show-focus {\ + display: block;\ +}\ +\n.text-core .text-wrap .text-prompt {\ + -webkit-box-sizing: border-box;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + position: absolute;\ + width: 100%;\ + height: 100%;\ + margin: 1px 0 0 2px;\ + font: 11px "lucida grande", tahoma, verdana, arial, sans-serif;\ + color: #c0c0c0;\ + overflow: hidden;\ + white-space: pre;\ +}\ +.text-core .text-wrap .text-prompt.text-hide-prompt {\ + display: none;\ +}\ +\n.text-core .text-wrap .text-tags {\ + -webkit-box-sizing: border-box;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + position: absolute;\ + width: 100%;\ + height: 100%;\ + padding: 3px 35px 3px 3px;\ + cursor: text;\ +}\ +.text-core .text-wrap .text-tags.text-tags-on-top {\ + z-index: 2;\ +}\ +.text-core .text-wrap .text-tags .text-tag {\ + float: left;\ +}\ +.text-core .text-wrap .text-tags .text-tag .text-button {\ + -webkit-border-radius: 2px;\ + -moz-border-radius: 2px;\ + border-radius: 2px;\ + -webkit-box-sizing: border-box;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + position: relative;\ + float: left;\ + border: 1px solid #9daccc;\ + background: #e2e6f0;\ + color: #000;\ + padding: 0px 17px 0px 3px;\ + margin: 0 2px 2px 0;\ + cursor: pointer;\ + height: 16px;\ + font: 11px "lucida grande", tahoma, verdana, arial, sans-serif;\ +}\ +.text-core .text-wrap .text-tags .text-tag .text-button a.text-remove {\ + position: absolute;\ + right: 3px;\ + top: 2px;\ + display: block;\ + width: 11px;\ + height: 11px;\ + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAhCAYAAAAPm1F2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAB50RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNS4xqx9I6wAAAQ5JREFUOI2dlD0WwiAQhCc8L6HHgAPoASwtSYvX8BrQxtIyveYA8RppLO1jE+LwE8lzms2yH8MCj1QoaBzH+VuUYNYMS213UlvDRamtUbXb5ZyPHuDoxwGgip3ipfvGuGzPz+vZ/coDONdzFuYCO6ramQQG0DJIE1oPBBvM6e9LqaS2FwD7FWwnVoIAsOc2Xn1jDlyd8pfPBRVOBHA8cc/3yCmQqt0jcY4LuTyAF3pOYS6wI48LAm4MUrx5JthgSQJAt5LtNgAUgEMBBIC3AL2xgo58dEPfhE9wygef89FtCeC49UwltR1pQrK2qr9vNr7uRTCBF3pOYS6wI4/zdQ8MUpxPI9hgSQL0Xyio/QBt54DzsHQx6gAAAABJRU5ErkJggg==") 0 0 no-repeat;\ +}\ +.text-core .text-wrap .text-tags .text-tag .text-button a.text-remove:hover {\ + background-position: 0 -11px;\ +}\ +.text-core .text-wrap .text-tags .text-tag .text-button a.text-remove:active {\ + background-position: 0 -22px;\ +}\ +'); \ No newline at end of file diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 675b01b4dee..3d6fc9c9525 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2305,17 +2305,114 @@ instance.web.form.dialog = function(content, options) { return dialog.$element; }; -instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin, { +/** + * A mixin containing some useful methods to handle completion inputs. + */ +instance.web.form.CompletionFieldMixin = { + init: function() { + this.limit = 7; + this.orderer = new instance.web.DropMisordered(); + }, + /** + * Call this method to search using a string. + */ + get_search_result: function(request, response) { + var search_val = request.term; + var self = this; + + var dataset = new instance.web.DataSet(this, this.field.relation, self.build_context()); + + this.orderer.add(dataset.name_search( + search_val, self.build_domain(), 'ilike', this.limit + 1)).then(function(data) { + self.last_search = data; + // possible selections for the m2o + var values = _.map(data, function(x) { + return { + label: _.str.escapeHTML(x[1]), + value:x[1], + name:x[1], + id:x[0] + }; + }); + + // search more... if more results that max + if (values.length > self.limit) { + values = values.slice(0, self.limit); + values.push({label: _t("   Search More..."), action: function() { + dataset.name_search(search_val, self.build_domain(), 'ilike' + , false, function(data) { + self._search_create_popup("search", data); + }); + }}); + } + // quick create + var raw_result = _(data.result).map(function(x) {return x[1];}); + if (search_val.length > 0 && + !_.include(raw_result, search_val) && + (!self.get("value") || self.floating)) { + values.push({label: _.str.sprintf(_t('   Create "%s"'), + $('').text(search_val).html()), action: function() { + self._quick_create(search_val); + }}); + } + // create... + values.push({label: _t("   Create and Edit..."), action: function() { + self._search_create_popup("form", undefined, {"default_name": search_val}); + }}); + + response(values); + }); + }, + _quick_create: function(name) { + var self = this; + var slow_create = function () { + self._search_create_popup("form", undefined, {"default_name": name}); + }; + if (self.get_definition_options().quick_create === undefined || self.get_definition_options().quick_create) { + new instance.web.DataSet(this, this.field.relation, self.build_context()) + .name_create(name, function(data) { + self.display_value = {}; + self.display_value["" + data[0]] = data[1]; + self.set({value: data[0]}); + }).fail(function(error, event) { + event.preventDefault(); + slow_create(); + }); + } else + slow_create(); + }, + // all search/create popup handling + _search_create_popup: function(view, ids, context) { + var self = this; + var pop = new instance.web.form.SelectCreatePopup(this); + pop.select_element( + self.field.relation, + { + title: (view === 'search' ? _t("Search: ") : _t("Create: ")) + (this.string || this.name), + initial_ids: ids ? _.map(ids, function(x) {return x[0]}) : undefined, + initial_view: view, + disable_multiple_selection: true + }, + self.build_domain(), + new instance.web.CompoundContext(self.build_context(), context || {}) + ); + pop.on_select_elements.add(function(element_ids) { + self.set({value: element_ids[0]}); + }); + }, +}; + +instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin, + instance.web.form.CompletionFieldMixin, { template: "FieldMany2One", init: function(field_manager, node) { this._super(field_manager, node); - this.limit = 7; + instance.web.form.CompletionFieldMixin.init.call(this); this.set({'value': false}); this.display_value = {}; this.last_search = []; this.floating = false; this.inhibit_on_change = false; - this.orderer = new instance.web.DropMisordered(); }, start: function() { this._super(); @@ -2459,91 +2556,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(_.exten isSelecting = false; }); }, - // autocomplete component content handling - get_search_result: function(request, response) { - var search_val = request.term; - var self = this; - var dataset = new instance.web.DataSet(this, this.field.relation, self.build_context()); - - this.orderer.add(dataset.name_search( - search_val, self.build_domain(), 'ilike', this.limit + 1)).then(function(data) { - self.last_search = data; - // possible selections for the m2o - var values = _.map(data, function(x) { - return { - label: _.str.escapeHTML(x[1]), - value:x[1], - name:x[1], - id:x[0] - }; - }); - - // search more... if more results that max - if (values.length > self.limit) { - values = values.slice(0, self.limit); - values.push({label: _t("   Search More..."), action: function() { - dataset.name_search(search_val, self.build_domain(), 'ilike' - , false, function(data) { - self._search_create_popup("search", data); - }); - }}); - } - // quick create - var raw_result = _(data.result).map(function(x) {return x[1];}); - if (search_val.length > 0 && - !_.include(raw_result, search_val) && - (!self.get("value") || self.floating)) { - values.push({label: _.str.sprintf(_t('   Create "%s"'), - $('').text(search_val).html()), action: function() { - self._quick_create(search_val); - }}); - } - // create... - values.push({label: _t("   Create and Edit..."), action: function() { - self._search_create_popup("form", undefined, {"default_name": search_val}); - }}); - - response(values); - }); - }, - _quick_create: function(name) { - var self = this; - var slow_create = function () { - self._search_create_popup("form", undefined, {"default_name": name}); - }; - if (self.get_definition_options().quick_create === undefined || self.get_definition_options().quick_create) { - new instance.web.DataSet(this, this.field.relation, self.build_context()) - .name_create(name, function(data) { - self.display_value = {}; - self.display_value["" + data[0]] = data[1]; - self.set({value: data[0]}); - }).fail(function(error, event) { - event.preventDefault(); - slow_create(); - }); - } else - slow_create(); - }, - // all search/create popup handling - _search_create_popup: function(view, ids, context) { - var self = this; - var pop = new instance.web.form.SelectCreatePopup(this); - pop.select_element( - self.field.relation, - { - title: (view === 'search' ? _t("Search: ") : _t("Create: ")) + (this.string || this.name), - initial_ids: ids ? _.map(ids, function(x) {return x[0]}) : undefined, - initial_view: view, - disable_multiple_selection: true - }, - self.build_domain(), - new instance.web.CompoundContext(self.build_context(), context || {}) - ); - pop.on_select_elements.add(function(element_ids) { - self.set({value: element_ids[0]}); - }); - }, render_value: function(no_recurse) { var self = this; if (! this.get("value")) { @@ -3039,37 +3052,75 @@ instance.web.form.One2ManyKanbanView = instance.web_kanban.KanbanView.extend({ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend({ template: "FieldMany2Many", + init: function() { + this._super.apply(this, arguments); + this.limit = 7; + this.orderer = new instance.web.DropMisordered(); + }, start: function() { - $("textarea", this.$element).textext({ + var self = this; + var textarea = $("textarea", this.$element).textext({ plugins : 'arrow prompt autocomplete', prompt : "Add one...", autocomplete: { render: function(suggestion) { - return $('', {'data-id': suggestion['id']}).html(suggestion['label']); + return $('
', {'data-index': suggestion['index']}).html(suggestion['label']); } }, + ext: { + autocomplete: { + selectFromDropdown: function(a, b, c) { + var index = this.selectedSuggestionElement().children().children().data('index'); + debugger; + $(this).trigger('hideDropdown'); + }, + }, + }, }).bind('getSuggestions', function(e, data) { - var list = [ - 'Basic', - 'Closure', - 'Cobol', - 'Delphi', - 'Erlang', - 'Fortran', - 'Go', - 'Groovy', - 'Haskel', - 'Java', - 'JavaScript', - 'OCAML', - 'PHP', - 'Perl', - 'Python', - 'Ruby', - 'Scala' - ]; + var str = !!data ? data.query || '' : ''; + self.get_search_result(str); + }); + }, + get_search_result: function(str) { + var self = this; + var dataset = new instance.web.DataSet(this, this.field.relation, self.build_context()); + this.orderer.add(dataset.name_search( + str, self.build_domain(), 'ilike', this.limit + 1)).then(function(data) { + + // possible selections for the m2m + self.values = _.map(data, function(x) { + return { + type: 'data', + label: _.str.escapeHTML(x[1]), + data: x, + }; + }); - $(this).trigger('setSuggestions', {result : _.map(list, function(el) {return {id:1, label:el};})}); + // search more... if more results than max + if (values.length > self.limit) { + values = values.slice(0, self.limit); + values.push({type: 'action', label: _t("   Search More..."), action: function() { + dataset.name_search(search_val, self.build_domain(), 'ilike' + , false, function(data) { + self._search_create_popup("search", data); + }); + }}); + } + // quick create + var raw_result = _(data.result).map(function(x) {return x[1];}); + if (search_val.length > 0 && + !_.include(raw_result, search_val)) { + values.push({label: _.str.sprintf(_t('   Create "%s"'), + $('').text(search_val).html()), action: function() { + self._quick_create(search_val); + }}); + } + // create... + values.push({label: _t("   Create and Edit..."), action: function() { + self._search_create_popup("form", undefined, {"default_name": search_val}); + }}); + + $(this).trigger('setSuggestions', {result : _.map(list, function(el, i) {return {index:i, label:el};})}); }); }, });