diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-11-29 20:06:16 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-11-29 20:06:16 +0100 |
| commit | ce4cc24621bf6430d7d3a2d469b375b59120c200 (patch) | |
| tree | 3837b5fe41ff88b24136ab53c871bc01f965cab1 /addons/web/static/src | |
| parent | 4d7aa97da38e497fef31a06543bfa5d2c8785708 (diff) | |
| parent | 82a1e1dcc33d7c123e50d3e1aacb5e127f57c521 (diff) | |
[MERGE] forward port branch 12.0 up to 82a1e1dcc33
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/js/core/dom.js | 91 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/basic_fields.js | 12 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/relational_fields.js | 1 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/abstract_view.js | 1 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_model.js | 4 | ||||
| -rw-r--r-- | addons/web/static/src/js/widgets/date_picker.js | 13 | ||||
| -rw-r--r-- | addons/web/static/src/js/widgets/dropdown_menu.js | 10 | ||||
| -rw-r--r-- | addons/web/static/src/scss/ui.scss | 5 |
8 files changed, 134 insertions, 3 deletions
diff --git a/addons/web/static/src/js/core/dom.js b/addons/web/static/src/js/core/dom.js index 2a961596862..848e406c4b2 100644 --- a/addons/web/static/src/js/core/dom.js +++ b/addons/web/static/src/js/core/dom.js @@ -20,6 +20,7 @@ odoo.define('web.dom', function (require) { * something happens in the DOM. */ +var concurrency = require('web.concurrency'); var config = require('web.config'); var core = require('web.core'); var _t = core._t; @@ -40,7 +41,9 @@ function _notify(content, callbacks) { core.bus.trigger('DOM_updated', content); } -return { +var dom = { + DEBOUNCE: 400, + /** * Appends content in a jQuery object and optionnally triggers an event * @@ -209,6 +212,91 @@ return { return position; }, /** + * Protects a function which is to be used as a handler by preventing its + * execution for the duration of a previous call to it (including async + * parts of that call). + * + * Limitation: as the handler is ignored during async actions, + * the 'preventDefault' or 'stopPropagation' calls it may want to do + * will be ignored too. Using the 'preventDefault' and 'stopPropagation' + * arguments solves that problem. + * + * @param {function} fct + * The function which is to be used as a handler. If a promise + * is returned, it is used to determine when the handler's action is + * finished. Otherwise, the return is used as jQuery uses it. + * @param {function|boolean} preventDefault + * @param {function|boolean} stopPropagation + */ + makeAsyncHandler: function (fct, preventDefault, stopPropagation) { + // Create a deferred indicating if a previous call to this handler is + // still pending. + var def = $.when(); + + return function (ev) { + if (preventDefault === true || preventDefault && preventDefault()) { + ev.preventDefault(); + } + if (stopPropagation === true || stopPropagation && stopPropagation()) { + ev.stopPropagation(); + } + + if (def.state() === 'pending') { + // If a previous call to this handler is still pending, ignore + // the new call. + return; + } + var result = fct.apply(this, arguments); + def = $.when(result); + return result; + }; + }, + /** + * Creates a debounced version of a function to be used as a button click + * handler. Also improves the handler to disable the button for the time of + * the debounce and/or the time of the async actions it performs. + * + * Limitation: if two handlers are put on the same button, the button will + * become enabled again once any handler's action finishes (multiple click + * handlers should however not be binded to the same button). + * + * @param {function} fct + * The function which is to be used as a button click handler. If a + * promise is returned, it is used to determine when the button can be + * re-enabled. Otherwise, the return is used as jQuery uses it. + */ + makeButtonHandler: function (fct) { + // Fallback: if the final handler is not binded to a button, at least + // make it an async handler (also handles the case where some events + // might ignore the disabled state of the button). + fct = dom.makeAsyncHandler(fct); + + return function (ev) { + var result = fct.apply(this, arguments); + + var $button = $(ev.target).closest('.btn'); + if (!$button.length) { + return result; + } + + // Disable the button for the duration of the handler's action + // or at least for the duration of the click debounce. This makes + // a 'real' debounce creation useless. Also, during the debouncing + // part, the button is disabled without any visual effect. + $button.addClass('o_debounce_disabled'); + $.when(dom.DEBOUNCE && concurrency.delay(dom.DEBOUNCE)).then(function () { + $button.addClass('disabled').prop('disabled', true); + $button.removeClass('o_debounce_disabled'); + + return $.when(result).always(function () { + $button.removeClass('disabled').prop('disabled', false); + }); + }); + + return result; + }; + }, + /** * Prepends content in a jQuery object and optionnally triggers an event * * @param {jQuery} [$target] the node where content will be prepended @@ -460,4 +548,5 @@ return { } }, }; +return dom; }); diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 53fbf99a8cd..aac91081c3c 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -2409,6 +2409,18 @@ var FieldProgressBar = AbstractField.extend({ this.$('.o_progressbar_value').focus().select(); } }, + /** + * The progress bar has more than one field/value to deal with + * i.e. max_value + * + * @override + * @private + */ + _reset: function () { + this._super.apply(this, arguments); + var new_max_value = this.recordData[this.nodeOptions.max_value]; + this.max_value = new_max_value !== undefined ? new_max_value : this.max_value; + }, isSet: function () { return true; }, diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index d9e15dab302..60b0275c8c8 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -564,6 +564,7 @@ var FieldMany2One = AbstractField.extend({ initial_ids: ids ? _.map(ids, function (x) { return x[0]; }) : undefined, initial_view: view, disable_multiple_selection: true, + no_create: !self.can_create, on_selected: function (records) { self.reinitialize(records[0]); self.activate(); diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js index 8f9f167c69f..024216b5619 100644 --- a/addons/web/static/src/js/views/abstract_view.js +++ b/addons/web/static/src/js/views/abstract_view.js @@ -181,6 +181,7 @@ var AbstractView = Class.extend({ modelName: params.modelName, res_id: params.currentId, res_ids: params.ids, + orderedBy: params.context ? params.context.orderedBy : [], }; if (params.modelName) { this.loadParams.modelName = params.modelName; diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 345b76856b6..53aa2e56c5a 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -3674,7 +3674,7 @@ var BasicModel = AbstractModel.extend({ model: params.modelName, offset: params.offset || (type === 'record' ? _.indexOf(res_ids, res_id) : 0), openGroupByDefault: params.openGroupByDefault, - orderedBy: params.orderedBy || (params.context && params.context.orderedBy) || [], + orderedBy: params.orderedBy || [], orderedResIDs: params.orderedResIDs, parentID: params.parentID, rawContext: params.rawContext, @@ -4608,7 +4608,7 @@ var BasicModel = AbstractModel.extend({ if (orderData1 > orderData2) { return order.asc ? 1 : -1; } - return compareRecords(record1ID, record2ID, level + 1); + return compareRecords(resId1, resId2, level + 1); }; utils.stableSort(list.res_ids, compareRecords); } diff --git a/addons/web/static/src/js/widgets/date_picker.js b/addons/web/static/src/js/widgets/date_picker.js index 7ba3010a3b5..b677abe377a 100644 --- a/addons/web/static/src/js/widgets/date_picker.js +++ b/addons/web/static/src/js/widgets/date_picker.js @@ -15,6 +15,7 @@ var DateWidget = Widget.extend({ 'change.datetimepicker': 'changeDatetime', 'change .o_datepicker_input': 'changeDatetime', 'input input': '_onInput', + 'show.datetimepicker': '_onDateTimePickerShow', }, /** * @override @@ -226,6 +227,18 @@ var DateWidget = Widget.extend({ //-------------------------------------------------------------------------- /** + * Reacts to the datetimepicker being shown + * Could set/verify our widget value + * And subsequently update the datetimepicker + * + * @private + */ + _onDateTimePickerShow: function () { + if (this.$input.val().length !== 0 && this.isValid()) { + this.$input.select(); + } + }, + /** * Prevents 'input' events triggered by the library to bubble up, as they * might have unwanted effects (like triggering 'field_changed' events in * the context of field widgets) diff --git a/addons/web/static/src/js/widgets/dropdown_menu.js b/addons/web/static/src/js/widgets/dropdown_menu.js index fdab9b82ebf..e92c714d838 100644 --- a/addons/web/static/src/js/widgets/dropdown_menu.js +++ b/addons/web/static/src/js/widgets/dropdown_menu.js @@ -15,6 +15,7 @@ var DropdownMenu = Widget.extend({ 'click .o_item_option': '_onOptionClick', 'click span.o_trash_button': '_onTrashClick', 'hidden.bs.dropdown': '_onBootstrapClose', + 'click .dropdown-item-text': '_onDropDownItemTextClick', }, /** @@ -200,6 +201,15 @@ var DropdownMenu = Widget.extend({ this._renderMenuItems(); }, /** + * Reacts to click on bootstrap's dropdown-item-text + * Protects against Bootstrap dropdown close from inside click + * + * @private + */ + _onDropDownItemTextClick: function (ev) { + ev.stopPropagation(); + }, + /** * @private * @param {MouseEvent} event */ diff --git a/addons/web/static/src/scss/ui.scss b/addons/web/static/src/scss/ui.scss index 46995aa9ba1..44d639805be 100644 --- a/addons/web/static/src/scss/ui.scss +++ b/addons/web/static/src/scss/ui.scss @@ -78,3 +78,8 @@ outline: 20px solid fade-out($o-brand-primary, 1.0); } } + +// Declare a similar class as 'disabled' but with no visual effect +.o_debounce_disabled { + pointer-events: none; +} |
