[REF] *: Replace underscore _.each() by native JS

Replaced _.each() functions (average 235 occurences)

Description of the refactoring this PR addresses:

Current behavior before PR:

There are underscore.js function enumerated above used in odoo.

Desired behavior after PR is merged:

These functions has been replaced by native javascript
prototypes/methods/functions.

TaskId : 3246238

closes odoo/odoo#118565

Signed-off-by: Georis François (fge) <fge@odoo.com>
This commit is contained in:
Pulinckx Pierre (PIPU)
2023-04-18 15:38:54 +02:00
parent 1a965a8045
commit 800223ae7c
65 changed files with 389 additions and 352 deletions
+5 -4
View File
@@ -18,7 +18,7 @@ QUnit.test("add_link utility function", function (assert) {
"https://tenor.com/view/chỗgiặt-dog-smile-gif-13860250": true,
"http://www.boîtenoire.be": true,
};
_.each(testInputs, function (willLinkify, content) {
for (const [content, willLinkify] of Object.entries(testInputs)) {
const output = utils.parseAndTransform(content, utils.addLink);
if (willLinkify) {
assert.strictEqual(output.indexOf("<a "), 0);
@@ -26,7 +26,7 @@ QUnit.test("add_link utility function", function (assert) {
} else {
assert.strictEqual(output.indexOf("<a "), -1);
}
});
}
});
QUnit.test("addLink: utility function and special entities", function (assert) {
@@ -51,10 +51,11 @@ QUnit.test("addLink: utility function and special entities", function (assert) {
// special character in smileys should be escaped
"&lt;3": "&lt;3",
};
_.each(testInputs, function (result, content) {
for (const [content, result] of Object.entries(testInputs)) {
const output = utils.parseAndTransform(content, utils.addLink);
assert.strictEqual(output, result);
});
}
});
QUnit.test("addLink: linkify inside text node (1 occurrence)", function (assert) {
@@ -485,7 +485,7 @@ export class MassMailingHtmlField extends HtmlField {
const $layout = this.wysiwyg.$iframeBody.find(".o_layout");
let selectedTheme = false;
if ($layout.length !== 0) {
_.each(themesParams, function (themeParams) {
themesParams.forEach((themeParams) => {
if ($layout.hasClass(themeParams.className)) {
selectedTheme = themeParams;
}
+2 -2
View File
@@ -1024,7 +1024,7 @@ export class PosGlobalState extends PosModel {
return orm
.call("pos.order", "create_from_ui", [orders, options.draft || false])
.then(function (server_ids) {
_.each(order_ids_to_sync, function (order_id) {
order_ids_to_sync.forEach((order_id) => {
self.db.remove_order(order_id);
});
self.failed = false;
@@ -3160,7 +3160,7 @@ export class Order extends PosModel {
this.pricelist = pricelist;
var lines_to_recompute = this.get_orderlines().filter((line) => !line.price_manually_set);
_.each(lines_to_recompute, function (line) {
lines_to_recompute.forEach((line) => {
line.set_unit_price(
line.product.get_price(self.pricelist, line.get_quantity(), line.get_price_extra())
);
@@ -102,7 +102,7 @@ var PortalChatter = publicWidget.Widget.extend({
* @returns {Array}
*/
preprocessMessages(messages) {
_.each(messages, function (m) {
messages.forEach((m) => {
m['author_avatar_url'] = sprintf('/web/image/%s/%s/author_avatar/50x50', 'mail.message', m.id);
m['published_date_str'] = sprintf(_t('Published on %s'), moment(time.str_to_datetime(m.date)).format('MMMM Do YYYY, h:mm:ss a'));
m['body'] = Markup(m.body);
@@ -52,7 +52,7 @@ var PortalComposer = publicWidget.Widget.extend({
return this._super.apply(this, arguments).then(function () {
if (self.options.default_attachment_ids) {
self.attachments = self.options.default_attachment_ids || [];
_.each(self.attachments, function(attachment) {
self.attachments.forEach((attachment) => {
attachment.state = 'done';
});
self._updateAttachments();
@@ -28,8 +28,8 @@ var PortalSidebar = publicWidget.Widget.extend({
* @private
*/
_setDelayLabel: function () {
var $sidebarTimeago = this.$el.find('.o_portal_sidebar_timeago');
_.each($sidebarTimeago, function (el) {
var $sidebarTimeago = this.$el.find('.o_portal_sidebar_timeago').toArray();
$sidebarTimeago.forEach((el) => {
var dateTime = moment(time.auto_str_to_date($(el).attr('datetime'))),
today = moment().startOf('day'),
diff = dateTime.diff(today, 'days', true),
@@ -65,7 +65,7 @@ PortalChatter.include({
var self = this;
messages = this._super.apply(this, arguments);
if (this.options['display_rating']) {
_.each(messages, function (m, i) {
messages.forEach((m, i) => {
m.rating_value = self.roundToHalf(m['rating_value']);
m.rating = self._preprocessCommentData(m.rating, i);
});
@@ -136,12 +136,14 @@ PortalChatter.include({
'avg': Math.round(result['rating_stats']['avg'] * 100) / 100,
'percent': [],
};
_.each(_.sortBy(Object.keys(result['rating_stats']['percent'])).reverse(), function (rating) {
ratingData['percent'].push({
'num': self.roundToHalf(rating),
'percent': utils.round_precision(result['rating_stats']['percent'][rating], 0.01),
_.sortBy(Object.keys(result["rating_stats"]["percent"]))
.reverse()
.forEach((rating) => {
ratingData["percent"].push({
num: self.roundToHalf(rating),
percent: utils.round_precision(result["rating_stats"]["percent"][rating], 0.01),
});
});
});
this.set('rating_card_values', ratingData);
},
/**
@@ -59,35 +59,19 @@ publicWidget.registry.PurchasePortalSidebar = PortalSidebar.extend({
"id",
""
);
_.each(this.spyWatched.find("#quote_content h2, #quote_content h3"), function (el) {
var id, text;
switch (el.tagName.toLowerCase()) {
case "h2":
id = self._setElementId("quote_header_", el);
text = self._extractText($(el));
if (!text) {
break;
}
lastLI = $("<li class='nav-item'>")
.append(
$(
'<a class="nav-link" style="max-width: 200px;" href="#' + id + '"/>'
).text(text)
)
.appendTo($bsSidenav);
lastUL = false;
break;
case "h3":
id = self._setElementId("quote_", el);
text = self._extractText($(el));
if (!text) {
break;
}
if (lastLI) {
if (!lastUL) {
lastUL = $("<ul class='nav flex-column'>").appendTo(lastLI);
this.spyWatched
.find("#quote_content h2, #quote_content h3")
.toArray()
.forEach((el) => {
var id, text;
switch (el.tagName.toLowerCase()) {
case "h2":
id = self._setElementId("quote_header_", el);
text = self._extractText($(el));
if (!text) {
break;
}
$("<li class='nav-item'>")
lastLI = $("<li class='nav-item'>")
.append(
$(
'<a class="nav-link" style="max-width: 200px;" href="#' +
@@ -95,12 +79,33 @@ publicWidget.registry.PurchasePortalSidebar = PortalSidebar.extend({
'"/>'
).text(text)
)
.appendTo(lastUL);
}
break;
}
el.setAttribute("data-anchor", true);
});
.appendTo($bsSidenav);
lastUL = false;
break;
case "h3":
id = self._setElementId("quote_", el);
text = self._extractText($(el));
if (!text) {
break;
}
if (lastLI) {
if (!lastUL) {
lastUL = $("<ul class='nav flex-column'>").appendTo(lastLI);
}
$("<li class='nav-item'>")
.append(
$(
'<a class="nav-link" style="max-width: 200px;" href="#' +
id +
'"/>'
).text(text)
)
.appendTo(lastUL);
}
break;
}
el.setAttribute("data-anchor", true);
});
this.trigger_up("widgets_start_request", { $target: $bsSidenav });
},
/**
@@ -113,19 +118,22 @@ publicWidget.registry.PurchasePortalSidebar = PortalSidebar.extend({
_extractText: function ($node) {
var self = this;
var rawText = [];
_.each($node.contents(), function (el) {
var current = $(el);
if ($.trim(current.text())) {
var tagName = current.prop("tagName");
if (
_.isUndefined(tagName) ||
(!_.isUndefined(tagName) &&
_.contains(self.authorizedTextTag, tagName.toLowerCase()))
) {
rawText.push($.trim(current.text()));
$node
.contents()
.toArray()
.forEach((el) => {
var current = $(el);
if ($.trim(current.text())) {
var tagName = current.prop("tagName");
if (
_.isUndefined(tagName) ||
(!_.isUndefined(tagName) &&
_.contains(self.authorizedTextTag, tagName.toLowerCase()))
) {
rawText.push($.trim(current.text()));
}
}
}
});
});
return rawText.join(" ");
},
});
@@ -61,7 +61,7 @@ publicWidget.registry.SalePortalSidebar = PortalSidebar.extend({
$bsSidenav = this.$el.find('.bs-sidenav');
$("#quote_content [id^=quote_header_], #quote_content [id^=quote_]", this.spyWatched).attr("id", "");
_.each(this.spyWatched.find("#quote_content h2, #quote_content h3"), function (el) {
this.spyWatched.find("#quote_content h2, #quote_content h3").toArray().forEach((el) => {
var id, text;
switch (el.tagName.toLowerCase()) {
case "h2":
@@ -101,7 +101,7 @@ publicWidget.registry.SalePortalSidebar = PortalSidebar.extend({
_extractText: function ($node) {
var self = this;
var rawText = [];
_.each($node.contents(), function (el) {
$node.contents().toArray().forEach((el) => {
var current = $(el);
if ($.trim(current.text())) {
var tagName = current.prop("tagName");
+8 -7
View File
@@ -295,7 +295,7 @@ var VariantMixin = {
'input.js_variant_change:checked',
'select.js_variant_change'
];
_.each($container.find(variantsValuesSelectors.join(', ')), function (el) {
$container.find(variantsValuesSelectors.join(', ')).toArray().forEach((el) => {
values.push(+$(el).val());
});
@@ -383,10 +383,10 @@ var VariantMixin = {
// for each of them, contains array with the other ptav they exclude
if (combinationData.exclusions) {
// browse all the currently selected attributes
_.each(combination, function (current_ptav) {
Object.values(combination).forEach((current_ptav) => {
if (combinationData.exclusions.hasOwnProperty(current_ptav)) {
// for each exclusion of the current attribute:
_.each(combinationData.exclusions[current_ptav], function (excluded_ptav) {
Object.values(combinationData.exclusions[current_ptav]).forEach((excluded_ptav) => {
// disable the excluded input (even when not already selected)
// to give a visual feedback before click
self._disableInput(
@@ -439,10 +439,11 @@ var VariantMixin = {
}
// parent exclusions (tell which attributes are excluded from parent)
_.each(combinationData.parent_exclusions, function (exclusions, excluded_by){
for (const [excluded_by, exclusions] of Object.entries(
combinationData.parent_exclusions || {}
)) {
// check that the selected combination is in the parent exclusions
_.each(exclusions, function (ptav) {
exclusions.forEach((ptav) => {
// disable the excluded input (even when not already selected)
// to give a visual feedback before click
self._disableInput(
@@ -453,7 +454,7 @@ var VariantMixin = {
combinationData.parent_product_name
);
});
});
}
},
/**
* Extracted to a method to be extendable by other modules
@@ -146,8 +146,8 @@ export const OptionalProductsModal = Dialog.extend(ServicesMixin, VariantMixin,
this.$el.find('input[name="add_qty"]').val(this.rootProduct.quantity);
// set a unique id to each row for options hierarchy
var $products = this.$el.find('tr.js_product');
_.each($products, function (el) {
var $products = this.$el.find('tr.js_product').toArray();
$products.forEach((el) => {
var $el = $(el);
var uniqueId = self._getUniqueId(el);
@@ -188,7 +188,7 @@ patch(SaleOrderLineProductField.prototype, 'sale_product_configurator', {
var customAttributeValues = mainProduct.product_custom_attribute_values;
var customValuesCommands = [{ operation: "DELETE_ALL" }];
if (customAttributeValues && customAttributeValues.length !== 0) {
_.each(customAttributeValues, function (customValue) {
customAttributeValues.forEach((customValue) => {
customValuesCommands.push({
operation: "CREATE",
context: [
@@ -75,8 +75,8 @@ import BrowserDetection from "web.BrowserDetection";
if (this.options.skipRenderOverlay) {
return;
}
var accesskeyElements = $(document).find('[accesskey]').filter(':visible');
_.each(accesskeyElements, function (elem) {
var accesskeyElements = $(document).find('[accesskey]').filter(':visible').toArray();
accesskeyElements.forEach((elem) => {
var overlay = $(`<div class='o_web_accesskey_overlay font-sans-serif'>${$(elem).attr('accesskey').toUpperCase()}</div>`);
var $overlayParent;
@@ -167,7 +167,7 @@ import BrowserDetection from "web.BrowserDetection";
.not('[accesskey]')
.not('[disabled]')
.not('[tabindex="-1"]');
_.each(buttonsWithoutAccessKey, function (elem) {
buttonsWithoutAccessKey.toArray().forEach((elem) => {
var buttonString = [elem.innerText, elem.title, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"].join('');
for (var letterIndex = 0; letterIndex < buttonString.length; letterIndex++) {
var candidateAccessKey = buttonString[letterIndex].toUpperCase();
@@ -182,7 +182,7 @@ import BrowserDetection from "web.BrowserDetection";
}
var elementsWithoutAriaKeyshortcut = this.$el.find('[accesskey]').not('[aria-keyshortcuts]');
_.each(elementsWithoutAriaKeyshortcut, function (elem) {
elementsWithoutAriaKeyshortcut.toArray().forEach((elem) => {
elem.setAttribute('aria-keyshortcuts', 'Alt+Shift+' + elem.accessKey);
});
this._addAccessKeyOverlays();
+2 -2
View File
@@ -164,9 +164,9 @@ function get_file(options) {
} else {
xhr.open('POST', options.url);
data = new FormData();
_.each(options.data || {}, function (v, k) {
for (const [k, v] of Object.entries(options.data || {})) {
data.append(k, v);
});
}
}
if (core.csrf_token) {
data.append('csrf_token', core.csrf_token);
@@ -73,7 +73,7 @@ OdooClass.extend = function() {
initializing = false;
// Copy the properties over onto the new prototype
_.each(prop, function(val, name) {
Object.keys(prop).forEach((name) => {
// Check if we're overwriting an existing function
prototype[name] = typeof prop[name] == "function" &&
fnTest.test(prop[name]) ?
@@ -110,7 +110,7 @@ OdooClass.extend = function() {
return this;
}
Class.include = function (properties) {
_.each(properties, function(val, name) {
Object.keys(properties).forEach((name) => {
if (typeof properties[name] !== 'function'
|| !fnTest.test(properties[name])) {
prototype[name] = properties[name];
@@ -9,9 +9,7 @@ var Context = Class.extend({
this.__contexts = [];
this.__eval_context = null;
var self = this;
_.each(arguments, function (x) {
self.add(x);
});
Object.values(arguments).forEach((x) => self.add(x));
},
//--------------------------------------------------------------------------
@@ -220,7 +220,7 @@ var Domain = collections.Tree.extend({
this._children.push(subdomain);
} else {
var self = this;
_.each(subdomain._children, function (childDomain) {
subdomain._children.forEach((childDomain) => {
self._children.push(childDomain);
});
}
@@ -330,7 +330,7 @@ var Domain = collections.Tree.extend({
}
var stack = [];
_.each(domain, function (dom) {
domain.forEach((dom) => {
if (dom === '|' || dom === '&') {
stack.push(dom);
} else {
+3 -3
View File
@@ -31,7 +31,7 @@ var Throbber = Widget.extend({
return;
var seconds = (new Date().getTime() - self.start_time) / 1000;
var mes;
_.each(messages_by_seconds(), function(el) {
messages_by_seconds().forEach((el) => {
if (seconds >= el[0])
mes = el[1];
});
@@ -58,7 +58,7 @@ if ($.blockUI) {
function blockAccessKeys() {
var elementWithAccessKey = [];
elementWithAccessKey = document.querySelectorAll('[accesskey]');
_.each(elementWithAccessKey, function (elem) {
elementWithAccessKey.forEach((elem) => {
elem.setAttribute("data-accesskey",elem.getAttribute('accesskey'));
elem.removeAttribute('accesskey');
});
@@ -67,7 +67,7 @@ function blockAccessKeys() {
function unblockAccessKeys() {
var elementWithDataAccessKey = [];
elementWithDataAccessKey = document.querySelectorAll('[data-accesskey]');
_.each(elementWithDataAccessKey, function (elem) {
elementWithDataAccessKey.forEach((elem) => {
elem.setAttribute('accesskey', elem.getAttribute('data-accesskey'));
elem.removeAttribute('data-accesskey');
});
+13 -11
View File
@@ -185,12 +185,12 @@ var Events = Class.extend({
callbackList: function () {
var lst = [];
_.each(this._callbacks || {}, function (el, eventName) {
for (const [eventName, el] of Object.entries(this._callbacks || {})) {
var node = el;
while ((node = node.next) && node.next) {
lst.push([eventName, node.callback, node.context]);
}
});
}
return lst;
},
@@ -291,7 +291,7 @@ var EventDispatcherMixin = Object.assign({}, ParentedMixin, {
throw new Error("Event handler must be a function.");
}
events = events.split(/\s+/);
_.each(events, function (eventName) {
events.forEach((eventName) => {
self.__edispatcherEvents.on(eventName, func, dest);
if (dest && dest.__eventDispatcherMixin) {
dest.__edispatcherRegisteredEvents.push({name: eventName, func: func, source: self});
@@ -302,7 +302,7 @@ var EventDispatcherMixin = Object.assign({}, ParentedMixin, {
off: function (events, dest, func) {
var self = this;
events = events.split(/\s+/);
_.each(events, function (eventName) {
events.forEach((eventName) => {
self.__edispatcherEvents.off(eventName, func, dest);
if (dest && dest.__eventDispatcherMixin) {
dest.__edispatcherRegisteredEvents = dest.__edispatcherRegisteredEvents.filter(el => {
@@ -342,16 +342,18 @@ var EventDispatcherMixin = Object.assign({}, ParentedMixin, {
},
destroy: function () {
var self = this;
_.each(this.__edispatcherRegisteredEvents, function (event) {
this.__edispatcherRegisteredEvents.forEach((event) => {
event.source.__edispatcherEvents.off(event.name, event.func, self);
});
this.__edispatcherRegisteredEvents = [];
_.each(this.__edispatcherEvents.callbackList(), function (cal) {
this.off(cal[0], cal[2], cal[1]);
}, this);
this.__edispatcherEvents.callbackList().forEach(
((cal) => {
this.off(cal[0], cal[2], cal[1]);
}).bind(this)
);
this.__edispatcherEvents.off();
ParentedMixin.destroy.call(this);
}
},
});
/**
@@ -376,7 +378,7 @@ var PropertiesMixin = Object.assign({}, EventDispatcherMixin, {
}
var self = this;
var changed = false;
_.each(map, function (val, key) {
for (const [key, val] of Object.entries(map)) {
var tmp = self.__getterSetterInternalMap[key];
if (tmp === val)
return;
@@ -399,7 +401,7 @@ var PropertiesMixin = Object.assign({}, EventDispatcherMixin, {
oldValue: tmp,
newValue: val
});
});
}
if (changed)
self.trigger("change", self);
},
@@ -175,7 +175,7 @@ function eval_domains(domains, evaluation_context) {
*/
function get_normalized_domain(domain_array) {
var expected = 1; // Holds the number of expected domain expressions
_.each(domain_array, function (item) {
domain_array.forEach((item) => {
if (item === "&" || item === "|") {
expected++;
} else if (item !== "!") {
@@ -24,7 +24,7 @@ var TranslationDataBase = Class.extend(/** @lends instance.TranslationDataBase#
if (_.include(modules, "web")) {
modules = ["web"].concat(_.without(modules, "web"));
}
_.each(modules, function(name) {
modules.forEach((name) => {
self.add_module_translation(translation_bundle.modules[name]);
});
if (translation_bundle.lang_parameters) {
@@ -34,7 +34,7 @@ var TranslationDataBase = Class.extend(/** @lends instance.TranslationDataBase#
},
add_module_translation: function(mod) {
var self = this;
_.each(mod.messages, function(message) {
mod.messages.forEach((message) => {
self.db[message.id] = message.string;
});
},
@@ -1077,7 +1077,9 @@ const utils = {
*/
traverse: function (tree, f) {
if (f(tree)) {
_.each(tree.children, function (c) { utils.traverse(c, f); });
Object.values(tree.children || {}).forEach((c) => {
utils.traverse(c, f);
});
}
},
/**
@@ -1090,7 +1092,7 @@ const utils = {
traversePath: function (tree, f, path) {
path = path || [];
f(tree, path);
_.each(tree.children, function (node) {
Object.values(tree.children || {}).forEach((node) => {
utils.traversePath(node, f, path.concat(tree));
});
},
@@ -254,7 +254,7 @@ var FieldMany2One = AbstractField.extend({
this.$input.autocomplete({
source: function (req, resp) {
self.suggestions = [];
_.each(self._autocompleteSources, function (source) {
self._autocompleteSources.forEach((source) => {
// Resets the results for this source
source.results = [];
@@ -357,7 +357,7 @@ var FieldMany2One = AbstractField.extend({
*/
_concatenateAutocompleteResults: function () {
var results = [];
_.each(this._autocompleteSources, function (source) {
this._autocompleteSources.forEach((source) => {
if (source.results && source.results.length) {
results = results.concat(source.results);
} else if (source.loading) {
@@ -1630,7 +1630,7 @@ var FieldRadio = FieldSelection.extend({
this.$el.empty();
this.$el.attr('role', 'radiogroup')
.attr('aria-label', this.string);
_.each(this.values, function (value, index) {
this.values.forEach((value, index) => {
self.$el.append(qweb.render('FieldRadio.button', {
checked: value[0] === currentValue,
id: self.unique_id + '_' + value[0],
@@ -324,8 +324,8 @@ export const PublicRoot = publicWidget.RootWidget.extend({
* @private
*/
_onWebsiteFormSubmit: function (ev) {
var $buttons = $(ev.currentTarget).find('button[type="submit"], a.a-submit');
_.each($buttons, function (btn) {
var $buttons = $(ev.currentTarget).find('button[type="submit"], a.a-submit').toArray();
$buttons.forEach((btn) => {
var $btn = $(btn);
$btn.prepend('<i class="fa fa-circle-o-notch fa-spin"></i> ');
$btn.prop('disabled', true);
@@ -197,7 +197,7 @@ var PublicWidget = Widget.extend({
var originalEvents = this.events;
var events = {};
_.each(this.events, function (method, event) {
Object.entries(this.events || {}).forEach(([event, method]) => {
// If the method is a function, use the default Widget system
if (typeof method !== 'string') {
events[event] = method;
@@ -14,12 +14,12 @@ import translation from "web.translation";
*/
var bus = new Bus();
_.each('click,dblclick,keydown,keypress,keyup'.split(','), function (evtype) {
["click","dblclick","keydown","keypress","keyup"].forEach((evtype) => {
$('html').on(evtype, function (ev) {
bus.trigger(evtype, ev);
});
});
_.each('resize,scroll'.split(','), function (evtype) {
["resize", "scroll"].forEach((evtype) => {
$(window).on(evtype, function (ev) {
bus.trigger(evtype, ev);
});
@@ -370,7 +370,7 @@ var BasicModel = AbstractModel.extend({
context: context,
})
.then(function () {
_.each(records, function (record) {
records.forEach((record) => {
// discard any changes to prevent creating a new record with auto-save
self.discardChanges(record.id);
var parent = record.parentID && self.localData[record.parentID];
@@ -610,7 +610,7 @@ var BasicModel = AbstractModel.extend({
this._sortList(element);
if (!element.orderedResIDs && element._changes) {
_.each(element._changes, function (change) {
element._changes.forEach((change) => {
if (change.operation === 'ADD' && change.isNew) {
element.data = _.without(element.data, change.id);
if (change.position === 'top') {
@@ -842,13 +842,13 @@ var BasicModel = AbstractModel.extend({
var self = this;
var defs = [];
var record_fields = {};
_.each(fields, function (field) {
fields.forEach((field) => {
record_fields[field.name] = _.pick(field, 'type', 'relation', 'domain', 'selection');
});
fieldInfo = fieldInfo || {};
var fieldsInfo = {};
fieldsInfo.default = {};
_.each(fields, function (field) {
fields.forEach((field) => {
fieldsInfo.default[field.name] = fieldInfo[field.name] || {};
});
var record = this._makeDataPoint({
@@ -857,7 +857,7 @@ var BasicModel = AbstractModel.extend({
fieldsInfo: fieldsInfo,
viewType: 'default',
});
_.each(fields, function (field) {
fields.forEach((field) => {
var dataPoint;
record.data[field.name] = null;
if (field.type === 'many2one') {
@@ -890,7 +890,7 @@ var BasicModel = AbstractModel.extend({
} else if (field.type === 'one2many' || field.type === 'many2many') {
var relatedFieldsInfo = {};
relatedFieldsInfo.default = {};
_.each(field.fields, function (field) {
(field.fields || []).forEach((field) => {
relatedFieldsInfo.default[field.name] = {};
});
var dpParams = {
@@ -910,7 +910,7 @@ var BasicModel = AbstractModel.extend({
if (_.isObject(field.value[0])) {
dpParams.res_ids = _.pluck(field.value, 'id');
dataPoint = self._makeDataPoint(dpParams);
_.each(field.value, function (data) {
field.value.forEach((data) => {
var recordDP = self._makeDataPoint({
data: data,
modelName: field.relation,
@@ -1061,7 +1061,7 @@ var BasicModel = AbstractModel.extend({
if (data.data.length) {
var dataType = self.localData[data.data[0]].type;
if (dataType === 'record') {
_.each(data.data, function (dataPoint) {
data.data.forEach((dataPoint) => {
var recordData = self.localData[dataPoint].data;
var inRecords = _.findWhere(records, {id: recordData.id});
if (inRecords) {
@@ -1079,7 +1079,7 @@ var BasicModel = AbstractModel.extend({
}
}
data.res_ids = [];
_.each(data.data, function (d) {
data.data.forEach((d) => {
var dataPoint = self.localData[d];
if (dataPoint.type === 'record') {
data.res_ids.push(dataPoint.res_id);
@@ -1144,7 +1144,7 @@ var BasicModel = AbstractModel.extend({
if (method === 'create') {
var fieldNames = record.getFieldNames();
_.each(fieldNames, function (name) {
fieldNames.forEach((name) => {
if (changes[name] === null) {
delete changes[name];
}
@@ -1238,7 +1238,7 @@ var BasicModel = AbstractModel.extend({
if (list.type === 'record') {
return;
} else if (list._changes) {
_.each(list._changes, function (change) {
list._changes.forEach((change) => {
delete change.isNew;
});
}
@@ -1460,7 +1460,7 @@ var BasicModel = AbstractModel.extend({
var additionalContexts = options && options.context;
var makeDefaultRecords = [];
if (additionalContexts){
_.each(additionalContexts, function (context) {
additionalContexts.forEach((context) => {
params.context = self._getContext(list, {additionalContext: context, full: true, sanitize_default_values: true});
makeDefaultRecords.push(self._makeDefaultRecord(list.model, params));
});
@@ -1471,7 +1471,7 @@ var BasicModel = AbstractModel.extend({
return Promise.all(makeDefaultRecords).then(function (resultIds){
var ids = [];
_.each(resultIds, function (id){
resultIds.forEach((id) => {
ids.push(id);
list._changes.push({operation: 'ADD', id: id, position: position, isNew: true});
@@ -1800,7 +1800,7 @@ var BasicModel = AbstractModel.extend({
// save it in case of a [5] which will remove the _changes
var oldChanges = list._changes;
_.each(val, function (command) {
val.forEach((command) => {
var rec, recID;
if (command[0] === 0 || command[0] === 1) {
// CREATE or UPDATE
@@ -1860,7 +1860,7 @@ var BasicModel = AbstractModel.extend({
list._changes = [{operation: 'REMOVE_ALL'}];
} else if (command[0] === 6) {
list._changes = [{operation: 'REMOVE_ALL'}];
_.each(command[2], function (resID) {
Object.values(command[2] || {}).forEach((resID) => {
linkRecord(list, resID);
});
}
@@ -1988,7 +1988,7 @@ var BasicModel = AbstractModel.extend({
}
var list_records = {};
_.each(data, function (d) {
data.forEach((d) => {
rec = self._makeDataPoint({
context: record.context,
modelName: field.relation,
@@ -2016,7 +2016,7 @@ var BasicModel = AbstractModel.extend({
args: [_.pluck(data, 'id'), fieldNames],
context: Object.assign({}, record.context, field.context, list.getContext()),
}).then(function (records) {
_.each(records, function (record) {
records.forEach((record) => {
list_records[record.id].data = record;
self._parseServerData(fieldNames, list, record);
});
@@ -2036,7 +2036,7 @@ var BasicModel = AbstractModel.extend({
createOptions.viewType = fieldInfo.mode;
def = this._addX2ManyDefaultRecord(list, createOptions).then(function (ids) {
_.each(ids, function(id){
ids.forEach((id) => {
if (command.position === 'bottom' && list.orderedResIDs && list.orderedResIDs.length >= list.limit) {
list.tempLimitIncrement = (list.tempLimitIncrement || 0) + 1;
list.limit += 1;
@@ -2121,7 +2121,7 @@ var BasicModel = AbstractModel.extend({
return Promise.all([addDef, removedDef]);
case 'MULTI':
// allows batching multiple operations
_.each(command.commands, function (innerCommand){
command.commands.forEach((innerCommand) => {
defs.push(self._applyX2ManyChange(
record,
fieldName,
@@ -2170,7 +2170,7 @@ var BasicModel = AbstractModel.extend({
var to = options.to === 0 ? 0 : (options.to || changes.length);
changes = changes.slice(options.from || 0, to);
}
_.each(changes, function (change) {
changes.forEach((change) => {
var relRecord;
if (change.id) {
relRecord = self.localData[change.id];
@@ -2234,7 +2234,7 @@ var BasicModel = AbstractModel.extend({
// and their subviews
function generateSpecs(fieldsInfo, fields, prefix) {
prefix = prefix || '';
_.each(Object.keys(fieldsInfo), function (name) {
Object.keys(fieldsInfo).forEach((name) => {
var field = fields[name];
var fieldInfo = fieldsInfo[name];
var key = prefix + name;
@@ -2243,7 +2243,7 @@ var BasicModel = AbstractModel.extend({
hasOnchange = true;
}
if (field.type === 'one2many' || field.type === 'many2many') {
_.each(fieldInfo.views, function (view) {
Object.values(fieldInfo.views || {}).forEach((view) => {
generateSpecs(view.fieldsInfo[view.type], view.fields, key + '.');
});
}
@@ -2492,7 +2492,7 @@ var BasicModel = AbstractModel.extend({
var ids = [];
list = this._applyX2ManyOperations(list);
_.each(list.data, function (localId) {
list.data.forEach((localId) => {
var record = self.localData[localId];
var data = record._changes || record.data;
var many2oneId = data[fieldName];
@@ -2515,7 +2515,7 @@ var BasicModel = AbstractModel.extend({
context: list.context,
})
.then(function (name_gets) {
_.each(records, function (record) {
records.forEach((record) => {
var nameGet = name_gets.find(nameGet => nameGet[0] === record.data.id);
record.data.display_name = nameGet[1];
});
@@ -2619,9 +2619,9 @@ var BasicModel = AbstractModel.extend({
args: [ids],
context: self.localData[parent].getContext({fieldName: fieldName, withoutRecordData: true}),
}).then(function (result) {
_.each(result, function (el) {
result.forEach((el) => {
var parentIDs = datapoints[el[0]];
_.each(parentIDs, function (parentID) {
parentIDs.forEach((parentID) => {
var parent = self.localData[parentID];
var referenceDp = self._makeDataPoint({
data: {
@@ -2649,7 +2649,7 @@ var BasicModel = AbstractModel.extend({
var self = this;
var defs = [];
var fieldNames = options && options.fieldNames || record.getFieldNames();
_.each(fieldNames, function (fieldName) {
fieldNames.forEach((fieldName) => {
var field = record.fields[fieldName];
if (field.type === 'reference') {
var def = self._fetchReference(record, fieldName).then(function (dataPoint) {
@@ -2679,7 +2679,7 @@ var BasicModel = AbstractModel.extend({
var toFetch = this._getDataToFetchByModel(list, fieldName);
var defs = [];
// one name_get by model
_.each(toFetch, function (datapoints, model) {
Object.entries(toFetch).forEach(([model, datapoints]) => {
defs.push(self._fetchReferenceData(datapoints, model, fieldName));
});
@@ -2715,14 +2715,14 @@ var BasicModel = AbstractModel.extend({
// collect ids by model
var toFetch = {};
_.each(list.data, function (groupIndex) {
list.data.forEach((groupIndex) => {
var group = self.localData[groupIndex];
self._getDataToFetchByModel(group, fieldName, toFetch);
});
var defs = [];
// one name_get by model
_.each(toFetch, function (datapoints, model) {
Object.entries(toFetch).forEach(([model, datapoints]) => {
defs.push(self._fetchReferenceData(datapoints, model, fieldName));
});
@@ -2958,7 +2958,7 @@ var BasicModel = AbstractModel.extend({
var foldField = fieldInfo.options.fold_field;
var fieldsToRead = foldField ? [foldField] : [];
return this._fetchSpecialMany2ones(record, fieldName, fieldInfo, fieldsToRead).then(function (m2os) {
_.each(m2os, function (m2o) {
Object.values(m2os || {}).forEach((m2o) => {
m2o.fold = foldField ? m2o[foldField] : false;
});
return m2os;
@@ -3042,7 +3042,7 @@ var BasicModel = AbstractModel.extend({
options = options || {};
var fieldNames = options.fieldNames || record.getFieldNames(options);
var viewType = options.viewType || record.viewType;
_.each(fieldNames, function (fieldName) {
fieldNames.forEach((fieldName) => {
var field = record.fields[fieldName];
if (field.type === 'one2many' || field.type === 'many2many') {
var fieldInfo = record.fieldsInfo[viewType][fieldName];
@@ -3119,10 +3119,10 @@ var BasicModel = AbstractModel.extend({
_fetchX2ManySingleBatch: function (list, fieldName) {
var self = this;
var toFetch = {};
_.each(list.data, function (groupIndex) {
list.data.forEach((groupIndex) => {
var group = self.localData[groupIndex];
var nextDataToFetch = self._getDataToFetch(group, fieldName);
_.each(Object.keys(nextDataToFetch), function (id) {
Object.keys(nextDataToFetch).forEach((id) => {
if (toFetch[id]) {
toFetch[id] = toFetch[id].concat(nextDataToFetch[id]);
} else {
@@ -3304,7 +3304,7 @@ var BasicModel = AbstractModel.extend({
var oldResIDs = list.res_ids.slice(0);
var relRecordAdded = [];
var relRecordUpdated = [];
_.each(list._changes, function (change) {
Object.values(list._changes || {}).forEach((change) => {
if (change.operation === 'ADD' && change.id) {
relRecordAdded.push(self.localData[change.id]);
} else if (change.operation === 'UPDATE' && !self.isNew(change.id)) {
@@ -3325,13 +3325,13 @@ var BasicModel = AbstractModel.extend({
// and 2) to guard against concurrent updates (policy: force
// a complete override of the actual value of the m2m)
commands[fieldName].push(x2ManyCommands.replace_with(realIDs));
_.each(relRecordCreated, function (relRecord) {
relRecordCreated.forEach((relRecord) => {
var changes = self._generateChanges(relRecord, options);
commands[fieldName].push(x2ManyCommands.create(relRecord.ref, changes));
});
// generate update commands for records that have been
// updated (it may happen with editable lists)
_.each(relRecordUpdated, function (relRecord) {
relRecordUpdated.forEach((relRecord) => {
var changes = self._generateChanges(relRecord, options);
if (!_.isEmpty(changes)) {
var command = x2ManyCommands.update(relRecord.res_id, changes);
@@ -3533,7 +3533,7 @@ var BasicModel = AbstractModel.extend({
return;
}
_.each(record.data[fieldName], function (id) {
Object.values(record.data[fieldName] || {}).forEach((id) => {
toFetch[id] = toFetch[id] || [];
toFetch[id].push(record);
});
@@ -3571,7 +3571,7 @@ var BasicModel = AbstractModel.extend({
_getDataToFetchByModel: function (list, fieldName, toFetchAcc) {
var self = this;
var toFetch = toFetchAcc || {};
_.each(list.data, function (dataPoint) {
list.data.forEach((dataPoint) => {
var record = self.localData[dataPoint];
var value = record.data[fieldName];
// if the reference field has already been fetched, the value is a
@@ -3828,11 +3828,11 @@ var BasicModel = AbstractModel.extend({
*/
_getMany2OneFieldNames: function (datapoint) {
var many2ones = [];
_.each(datapoint.fields, function (field, name) {
for (const [name, field] of Object.entries(datapoint.fields)) {
if (field.type === 'many2one') {
many2ones.push(name);
}
});
}
return many2ones;
},
/**
@@ -4043,7 +4043,7 @@ var BasicModel = AbstractModel.extend({
var self = this;
var isValid = true;
var element = this.localData[id];
_.each(element._changes, function (command) {
Object.values(element._changes || {}).forEach((command) => {
if (command.operation === 'DELETE' ||
command.operation === 'FORGET' ||
(command.operation === 'ADD' && !command.isNew)||
@@ -4052,7 +4052,7 @@ var BasicModel = AbstractModel.extend({
}
var recordData = self.get(command.id, {raw: true}).data;
var record = self.localData[command.id];
_.each(element.getFieldNames(), function (fieldName) {
element.getFieldNames().forEach((fieldName) => {
var field = element.fields[fieldName];
var fieldInfo = element.fieldsInfo[element.viewType][fieldName];
var rawModifiers = fieldInfo.modifiers || {};
@@ -4312,7 +4312,7 @@ var BasicModel = AbstractModel.extend({
*/
_parseServerData: function (fieldNames, element, data) {
var self = this;
_.each(fieldNames, function (fieldName) {
fieldNames.forEach((fieldName) => {
var field = element.fields[fieldName];
var val = data[fieldName];
if (field.type === 'many2one') {
@@ -4500,7 +4500,7 @@ var BasicModel = AbstractModel.extend({
var viewType = options && options.viewType || record.viewType;
var defs = [];
_.each(record.getFieldNames(options), function (name) {
record.getFieldNames(options).forEach((name) => {
var field = record.fields[name];
var fieldInfo = record.fieldsInfo[viewType][name] || {};
var options = fieldInfo.options || {};
@@ -4593,7 +4593,7 @@ var BasicModel = AbstractModel.extend({
if (!isCommandList) {
commands = [[6, false, commands]];
}
_.each(commands, function (value) {
commands.forEach((value) => {
// value is a command
if (value[0] === 0) {
// CREATE
@@ -4610,7 +4610,7 @@ var BasicModel = AbstractModel.extend({
x2manyList._cache[r.res_id] = r.id;
// this is necessary so the fields are initialized
_.each(r.getFieldNames(), function (fieldName) {
r.getFieldNames().forEach((fieldName) => {
r.data[fieldName] = null;
});
@@ -4654,7 +4654,7 @@ var BasicModel = AbstractModel.extend({
}
if (value[0] === 6) {
// REPLACE_WITH
_.each(value[2], function (res_id) {
value[2].forEach((res_id) => {
x2manyList._changes.push({operation: 'ADD', resID: res_id});
});
var def = self._readUngroupedList(x2manyList).then(function () {
@@ -4668,7 +4668,7 @@ var BasicModel = AbstractModel.extend({
});
// fetch many2ones display_name
_.each(Object.keys(many2ones), function (name) {
Object.keys(many2ones).forEach((name) => {
defs.push(self._fetchNameGets(x2manyList, name));
});
@@ -4716,7 +4716,7 @@ var BasicModel = AbstractModel.extend({
}));
}
return def.then(function (records) {
_.each(resIDs, function (id) {
resIDs.forEach((id) => {
var dataPoint;
var data = _.findWhere(records, {id: id});
if (id in list._cache) {
@@ -4741,7 +4741,7 @@ var BasicModel = AbstractModel.extend({
list._cache[id] = dataPoint.id;
}
// set the dataPoint id in potential 'ADD' operation adding the current record
_.each(list._changes, function (change) {
Object.values(list._changes || {}).forEach((change) => {
if (change.operation === 'ADD' && !change.id && change.resID === id) {
change.id = dataPoint.id;
}
@@ -4796,14 +4796,14 @@ var BasicModel = AbstractModel.extend({
var defs = [];
var openGroupCount = 0;
_.each(groups, function (group) {
groups.forEach((group) => {
var aggregateValues = {};
_.each(group, function (value, key) {
for (const [key, value] of Object.entries(group)) {
if (_.contains(fields, key) && key !== groupByField &&
AGGREGATABLE_TYPES.includes(list.fields[key].type)) {
aggregateValues[key] = value;
}
});
}
// When a view is grouped, we need to display the name of each group in
// the 'title'.
var value = group[groupByField];
@@ -4871,7 +4871,7 @@ var BasicModel = AbstractModel.extend({
// Note that these groups are put after existing groups so
// the order is not conserved. A sort *might* be useful.
var emptyGroupsIDs = _.difference(_.pluck(previousGroups, 'id'), list.data);
_.each(emptyGroupsIDs, function (groupID) {
emptyGroupsIDs.forEach((groupID) => {
list.data.push(groupID);
var emptyGroup = self.localData[groupID];
// this attribute hasn't been updated in the previous
@@ -4993,7 +4993,7 @@ var BasicModel = AbstractModel.extend({
}
} else if (element._changes) {
delete element.tempLimitIncrement;
_.each(element._changes, function (change) {
element._changes.forEach((change) => {
delete change.isNew;
});
}
@@ -5161,7 +5161,7 @@ var BasicModel = AbstractModel.extend({
idsInRange = list.res_ids;
}
list.data = [];
_.each(idsInRange, function (id) {
idsInRange.forEach((id) => {
if (list._cache[id]) {
list.data.push(list._cache[id]);
}
@@ -5320,10 +5320,10 @@ var BasicModel = AbstractModel.extend({
var viewType = view ? view.type : fieldInfo.viewType;
var id2Values = new Map(values.map((value) => [value.id, value]))
_.each(records, function (record) {
records.forEach((record) => {
var x2mList = self.localData[record.data[fieldName]];
x2mList.data = [];
_.each(x2mList.res_ids, function (res_id) {
x2mList.res_ids.forEach((res_id) => {
var dataPoint = self._makeDataPoint({
modelName: field.relation,
data: id2Values.get(res_id),
@@ -5408,7 +5408,7 @@ var BasicModel = AbstractModel.extend({
}
if (element.type === 'list') {
element = this._applyX2ManyOperations(element);
_.each(element.data, function (elemId) {
element.data.forEach((elemId) => {
var elem = self.localData[elemId];
self._visitChildren(elem, fn);
});
@@ -41,11 +41,11 @@ var StandaloneFieldManagerMixin = Object.assign({}, FieldManagerMixin, {
_confirmChange: function (id, fields, event) {
var result = FieldManagerMixin._confirmChange.apply(this, arguments);
var record = this.model.get(id);
_.each(this.registeredWidgets[id], function (widget, fieldName) {
for (const [fieldName, widget] of Object.entries(this.registeredWidgets[id])) {
if (_.contains(fields, fieldName)) {
widget.reset(record, event);
}
});
}
return result;
},
@@ -135,9 +135,9 @@ var ColorpickerWidget = Widget.extend({
var self = this;
// Update inputs
_.each(this.colorComponents, function (value, color) {
for (const [color, value] of Object.entries(this.colorComponents)) {
self.$(`.o_${color}_input`).val(value);
});
}
// Update preview
this.$('.o_color_preview').css('background-color', this.colorComponents.cssColor);
@@ -222,7 +222,7 @@ var DomainTree = DomainNode.extend({
getDomain: function () {
var childDomains = [];
var nbChildren = 0;
_.each(this.children, function (child) {
this.children.forEach((child) => {
var childDomain = child.getDomain();
if (childDomain.length) {
nbChildren++;
@@ -276,10 +276,12 @@ var DomainTree = DomainNode.extend({
this.children.push(node);
return;
}
_.each(node.children, (function (child) {
child.setParent(this);
this.children.push(child);
}).bind(this));
node.children.forEach(
((child) => {
child.setParent(this);
this.children.push(child);
}).bind(this)
);
node.destroy();
},
/**
@@ -380,7 +382,7 @@ var DomainTree = DomainNode.extend({
return Promise.all(_.map(children, (function (child) {
return child.appendTo($div);
}).bind(this))).then((function () {
_.each(children, function (child) {
children.forEach((child) => {
child.$el.appendTo($to); // Forced to do it this way so that the
// children are not misordered
});
@@ -570,10 +572,14 @@ var DomainSelector = DomainTree.extend({
if (_redrawId !== this._redrawId) {
return;
}
_.each(oldChildren, function (child) { child.destroy(); });
oldChildren.forEach((child) => { child.destroy(); });
this.renderElement();
this._postRender();
_.each(this.children, (function (child) { child.$el.appendTo(this.$childrenContainer); }).bind(this));
this.children.forEach(
((child) => {
child.$el.appendTo(this.$childrenContainer);
}).bind(this)
);
}).bind(this));
},
@@ -5,7 +5,7 @@ const domParser = new DOMParser();
function traverse(tree, f) {
if (f(tree)) {
_.each(tree.children, function (c) {
Object.values(tree.children || {}).forEach((c) => {
traverse(c, f);
});
}
@@ -66,7 +66,9 @@ export function processArch(arch, viewType, resModel, models) {
const viewFieldsInfo = models[resModel][fieldName];
const nodeString = node.getAttribute("string");
if (nodeString === null && viewFieldsInfo === undefined) {
throw new Error(`Missing field string information for the field '${fieldName}' from the '${resModel}' model`);
throw new Error(
`Missing field string information for the field '${fieldName}' from the '${resModel}' model`
);
}
viewFields[fieldName] = {
...viewFieldsInfo,
@@ -1218,9 +1218,9 @@ export class RelationalModel extends Model {
// avoid losing the initial fields (display_name)
const fieldViews = fieldInfo.views || fieldInfo.fieldsInfo || {};
const defaultFieldInfo = legRec.data[name].fieldsInfo.default;
_.each(fieldViews, function (fieldView) {
Object.values(fieldViews).forEach((fieldView) => {
_.defaults(fieldView.fields, defaultFieldInfo);
_.each(fieldView.fieldsInfo, function (x2mFieldInfo) {
Object.values(fieldView.fieldsInfo).forEach((x2mFieldInfo) => {
_.defaults(x2mFieldInfo, defaultFieldInfo);
});
});
@@ -357,8 +357,8 @@ export class MockServer {
defaultValues[attr] = !!field[attr];
});
// LPE: what is this ?
/* _.each(field.states || {}, function (modifs, state) {
_.each(modifs, function (modif) {
/* for (const [state, modifs] of Object.entries(field.states || {})) {
modifs.forEach((modif) => {
if (defaultValues[modif[0]] !== modif[1]) {
stateExceptions[modif[0]].append(state);
}
@@ -334,24 +334,24 @@ var MockServer = Class.extend({
}
var defaultValues = {};
var stateExceptions = {};
_.each(modifiersNames, function (attr) {
modifiersNames.forEach((attr) => {
stateExceptions[attr] = [];
defaultValues[attr] = !!field[attr];
});
_.each(field.states || {}, function (modifs, state) {
_.each(modifs, function (modif) {
for (const [state, modifs] of Object.entries(field.states || {})) {
modifs.forEach((modif) => {
if (defaultValues[modif[0]] !== modif[1]) {
stateExceptions[modif[0]].append(state);
}
});
});
_.each(defaultValues, function (defaultValue, attr) {
}
for (const [attr, defaultValue] of Object.entries(defaultValues)) {
if (stateExceptions[attr].length) {
modifiers[attr] = [("state", defaultValue ? "not in" : "in", stateExceptions[attr])];
} else {
modifiers[attr] = defaultValue;
}
});
}
} else if (isGroupby && !node._isProcessed) {
var groupbyName = node.getAttribute('name');
fieldNodes[groupbyName] = node;
@@ -374,7 +374,7 @@ var MockServer = Class.extend({
}
const inListHeader = inTreeView && node.closest('header');
_.each(modifiersNames, function (a) {
modifiersNames.forEach((a) => {
var mod = node.getAttribute(a);
if (mod) {
var pyevalContext = window.py.dict.fromJSON(context || {});
@@ -387,7 +387,7 @@ var MockServer = Class.extend({
}
});
_.each(modifiersNames, function (a) {
modifiersNames.forEach((a) => {
if (a in modifiers && (!!modifiers[a] === false || (Array.isArray(modifiers[a]) && !modifiers[a].length))) {
delete modifiers[a];
}
@@ -405,7 +405,7 @@ var MockServer = Class.extend({
});
let relModel, relFields;
_.each(fieldNodes, function (node, name) {
for (const [name, node] of Object.entries(fieldNodes)) {
var field = fields[name];
if (field.type === "many2one" || field.type === "many2many") {
var canCreate = node.getAttribute('can_create');
@@ -416,7 +416,7 @@ var MockServer = Class.extend({
if (field.type === "one2many" || field.type === "many2many") {
relModel = field.relation;
relatedModels.add(relModel);
_.each(node.childNodes, function (childNode) {
node.childNodes.forEach((childNode) => {
if (childNode.tagName) { // skip text nodes
relFields = $.extend(true, {}, self.data[relModel].fields);
// this is hackhish, but _getView modifies the subview document in place,
@@ -432,8 +432,8 @@ var MockServer = Class.extend({
if (name in onchanges) {
node.setAttribute('on_change', "1");
}
});
_.each(groupbyNodes, function (node, name) {
}
for (const [name, node] of Object.entries(groupbyNodes)) {
var field = fields[name];
if (field.type !== 'many2one') {
throw new Error('groupby can only target many2one');
@@ -446,7 +446,7 @@ var MockServer = Class.extend({
// postprocess simulation
const { models } = self._getView(node, relModel, relFields, context);
[...models].forEach((modelName) => relatedModels.add(modelName));
});
}
var xmlSerializer = new XMLSerializer();
var processedArch = xmlSerializer.serializeToString(doc);
@@ -480,7 +480,7 @@ var MockServer = Class.extend({
if (active_test && 'active' in this.data[model].fields) {
// add ['active', '=', true] to the domain if 'active' is not yet present in domain
var activeInDomain = false;
_.each(domain, function (subdomain) {
domain.forEach((subdomain) => {
activeInDomain = activeInDomain || subdomain[0] === 'active';
});
if (!activeInDomain) {
@@ -497,7 +497,7 @@ var MockServer = Class.extend({
var childIDs = [criterion[2]];
while (childIDs.length > oldLength) {
oldLength = childIDs.length;
_.each(records, function (r) {
records.forEach((r) => {
if (childIDs.indexOf(r.parent_id) >= 0) {
childIDs.push(r.id);
}
@@ -1205,7 +1205,7 @@ var MockServer = Class.extend({
_mockGetViews: function (model, kwargs) {
var self = this;
var views = {};
_.each(kwargs.views, function (view_descr) {
kwargs.views.forEach((view_descr) => {
var viewID = view_descr[0] || false;
var viewType = view_descr[1];
if (!viewID) {
@@ -1443,7 +1443,7 @@ var MockServer = Class.extend({
var self = this;
var fields = this.data[model].fields;
var aggregatedFields = [];
_.each(kwargs.fields, function (field) {
kwargs.fields.forEach((field) => {
var split = field.split(":");
var fieldName = split[0];
if (kwargs.groupby.indexOf(fieldName) > 0) {
@@ -1700,7 +1700,7 @@ var MockServer = Class.extend({
var records = this._getRecords(model, domain || []);
var data = {};
_.each(records, function (record) {
records.forEach((record) => {
var groupByValue = record[groupBy]; // always technical value here
// special case for bool values: rpc call response with capitalized strings
@@ -1714,7 +1714,7 @@ var MockServer = Class.extend({
if (!(groupByValue in data)) {
data[groupByValue] = {};
_.each(progress_bar.colors, function (val, key) {
Object.keys(progress_bar.colors).forEach((key) => {
data[groupByValue][key] = 0;
});
}
@@ -1836,7 +1836,7 @@ var MockServer = Class.extend({
records = records.slice(offset, args.limit ? (offset + args.limit) : nbRecords);
var processedRecords = _.map(records, function (r) {
var result = {};
_.each(_.uniq(fields.concat(['id'])), function (fieldName) {
_.uniq(fields.concat(['id'])).forEach((fieldName) => {
var field = self.data[args.model].fields[fieldName];
if (field.type === 'many2one') {
var related_record = _.findWhere(self.data[field.relation].records, {
@@ -1872,12 +1872,12 @@ var MockServer = Class.extend({
this.data[model].records = this.data[model].records.filter(record => !_.contains(ids, record.id));
// update value of relationnal fields pointing to the deleted records
_.each(this.data, function (d) {
Object.values(this.data).forEach((d) => {
var relatedFields = _.pick(d.fields, function (field) {
return field.relation === model;
});
_.each(Object.keys(relatedFields), function (relatedField) {
_.each(d.records, function (record) {
Object.keys(relatedFields).forEach((relatedField) => {
d.records.forEach((record) => {
if (Array.isArray(record[relatedField])) {
record[relatedField] = _.difference(record[relatedField], ids);
} else if (ids.includes(record[relatedField])) {
@@ -1943,7 +1943,7 @@ var MockServer = Class.extend({
* @returns {boolean} currently, always return 'true'
*/
_mockWrite: function (model, args) {
_.each(args[0], id => {
args[0].forEach((id) => {
const originalRecord = this._mockSearchRead(model, [[['id', '=', id]]], {})[0];
this._writeRecord(model, args[1], id);
const updatedRecord = this.data[model].records.find(record => record.id === id);
@@ -2115,7 +2115,9 @@ var MockServer = Class.extend({
_traverse: function (tree, f) {
var self = this;
if (f(tree)) {
_.each(tree.childNodes, function (c) { self._traverse(c, f); });
Object.values(tree.childNodes || {}).forEach((c) => {
self._traverse(c, f);
});
}
},
/**
@@ -632,7 +632,7 @@ function patch(target, props) {
ownPatchedProps: [],
};
if (target.prototype) {
_.each(props, function (value, key) {
Object.keys(props).forEach((key) => {
if (target.prototype.hasOwnProperty(key)) {
patches[patchID].ownPatchedProps.push({
key: key,
@@ -644,7 +644,7 @@ function patch(target, props) {
});
target.include(props);
} else {
_.each(props, function (value, key) {
for (const [key, value] of Object.entries(props)) {
if (key in target) {
var oldValue = target[key];
patches[patchID].ownPatchedProps.push({
@@ -670,7 +670,7 @@ function patch(target, props) {
patches[patchID].otherPatchedProps.push(key);
target[key] = value;
}
});
}
}
}
@@ -683,17 +683,17 @@ function unpatch(target) {
var patchID = target.__patchID;
var patch = patches[patchID];
if (target.prototype) {
_.each(patch.ownPatchedProps, function (p) {
patch.ownPatchedProps.forEach((p) => {
target.prototype[p.key] = p.initialValue;
});
_.each(patch.otherPatchedProps, function (key) {
patch.otherPatchedProps.forEach((key) => {
delete target.prototype[key];
});
} else {
_.each(patch.ownPatchedProps, function (p) {
patch.ownPatchedProps.forEach((p) => {
target[p.key] = p.initialValue;
});
_.each(patch.otherPatchedProps, function (key) {
patch.otherPatchedProps.forEach((key) => {
delete target[key];
});
}
+44 -38
View File
@@ -524,11 +524,11 @@ var ViewEditor = Widget.extend({
// Initialize a 0 level for each view and assign them an array containing their children.
var self = this;
var roots = [];
_.each(this.views, function (view) {
Object.values(this.views).forEach((view) => {
view.level = 0;
view.children = [];
});
_.each(this.views, function (view) {
Object.values(this.views).forEach((view) => {
var parentId = view.inherit_id[0];
var parent = parentId && self.views[parentId];
if (parent) {
@@ -544,11 +544,11 @@ var ViewEditor = Widget.extend({
function visit(view, level) {
view.level = level;
self.sortedViews.push(view);
_.each(view.children, function (child) {
view.children.forEach((child) => {
visit(child, level + 1);
});
}
_.each(roots, function (root) {
roots.forEach((root) => {
visit(root, 0);
});
}
@@ -563,8 +563,10 @@ var ViewEditor = Widget.extend({
// Store the URL ungrouped by bundle and use the URL as key (resource ID)
var resources = type === 'scss' ? this.scss : this.js;
_.each(data, function (bundleInfos) {
_.each(bundleInfos[1], function (info) { info.bundle = bundleInfos[0]; });
data.forEach((bundleInfos) => {
bundleInfos[1].forEach((info) => {
info.bundle = bundleInfos[0];
});
Object.assign(resources, _.indexBy(bundleInfos[1], 'url'));
});
}
@@ -629,41 +631,45 @@ var ViewEditor = Widget.extend({
var self = this;
var toSave = {};
var errorFound = false;
_.each(this.editingSessions, (function (editingSessions, type) {
if (errorFound) return;
Object.entries(this.editingSessions || {}).forEach(
(([type, editingSessions]) => {
if (errorFound) return;
var dirtySessions = _.pick(editingSessions, function (session) {
return session.getUndoManager().hasUndo();
});
toSave[type] = _.map(dirtySessions, function (session, resID) {
return {
id: parseInt(resID, 10) || resID,
text: session.getValue(),
};
});
var dirtySessions = _.pick(editingSessions, function (session) {
return session.getUndoManager().hasUndo();
});
toSave[type] = _.map(dirtySessions, function (session, resID) {
return {
id: parseInt(resID, 10) || resID,
text: session.getValue(),
};
});
this._showErrorLine();
for (var i = 0 ; i < toSave[type].length && !errorFound ; i++) {
var check = (type === 'xml' ? checkXML : checkSCSS)(toSave[type][i].text);
if (!check.isValid) {
this._showErrorLine(check.error.line, check.error.message, toSave[type][i].id, type);
errorFound = toSave[type][i];
this._showErrorLine();
for (var i = 0 ; i < toSave[type].length && !errorFound ; i++) {
var check = (type === 'xml' ? checkXML : checkSCSS)(toSave[type][i].text);
if (!check.isValid) {
this._showErrorLine(check.error.line, check.error.message, toSave[type][i].id, type);
errorFound = toSave[type][i];
}
}
}
}).bind(this));
}).bind(this)
);
if (errorFound) return Promise.reject(errorFound);
var defs = [];
var mutex = new concurrency.Mutex();
_.each(toSave, (function (_toSave, type) {
// Child views first as COW on a parent would delete them
_toSave = _.sortBy(_toSave, 'id').reverse();
_.each(_toSave, function (session) {
defs.push(mutex.exec(function () {
return (type === 'xml' ? self._saveView(session) : self._saveSCSSorJS(session));
}));
});
}).bind(this));
Object.entries(toSave || {}).forEach(
(([type, _toSave]) => {
// Child views first as COW on a parent would delete them
_toSave = _.sortBy(_toSave, 'id').reverse();
_toSave.forEach((session) => {
defs.push(mutex.exec(function () {
return (type === 'xml' ? self._saveView(session) : self._saveSCSSorJS(session));
}));
});
}).bind(this)
);
var self = this;
return Promise.all(defs).guardedCatch(function (results) {
@@ -811,7 +817,7 @@ var ViewEditor = Widget.extend({
_switchType: function (type) {
this.currentType = type;
this.$typeSwitcherBtn.html(this.$typeSwitcherChoices.filter('[data-type=' + type + ']').html());
_.each(this.$lists, function ($list, _type) { $list.toggleClass('d-none', type !== _type); });
Object.entries(this.$lists).forEach(([_type, $list]) => { $list.toggleClass('d-none', type !== _type); });
this.$lists[type].change();
this.$includeBundlesArea.toggleClass('d-none', this.currentType !== 'xml' || !config.isDebug());
@@ -851,7 +857,7 @@ var ViewEditor = Widget.extend({
var self = this;
this.$lists.xml.empty();
_.each(this.sortedViews, function (view) {
this.sortedViews.forEach((view) => {
self.$lists.xml.append($('<option/>', {
value: view.id,
text: view.name,
@@ -887,11 +893,11 @@ var ViewEditor = Widget.extend({
this.$lists.js.data('select2').dropdown.addClass('o_ace_select2_dropdown');
function _populateList(sortedData, $list, lettersToRemove) {
_.each(sortedData, function (bundleInfos) {
sortedData.forEach((bundleInfos) => {
var $optgroup = $('<optgroup/>', {
label: bundleInfos[0],
}).appendTo($list);
_.each(bundleInfos[1], function (dataInfo) {
bundleInfos[1].forEach((dataInfo) => {
var name = dataInfo.url.substring(dataInfo.url.lastIndexOf('/') + 1, dataInfo.url.length - lettersToRemove);
$optgroup.append($('<option/>', {
value: dataInfo.url,
@@ -1539,7 +1539,7 @@ var SnippetEditor = Widget.extend({
// propagated to parent editor
if (ev.data.optionNames) {
ev.stopPropagation();
_.each(ev.data.optionNames, function (name) {
ev.data.optionNames.forEach((name) => {
notifyForEachMatchedOption(name);
});
}
@@ -3037,7 +3037,7 @@ var SnippetsMenu = Widget.extend({
: $els => $els;
var check = false;
_.each(self.templateOptions, function (option, k) {
self.templateOptions.forEach((option, k) => {
if (check || !($snippetBody.is(option.base_selector) && !$snippetBody.is(option.base_exclude))) {
return;
}
@@ -4444,13 +4444,13 @@ registry.sizing = SnippetOptionWidget.extend({
let current = 0;
const cssProperty = resize[2];
const cssPropertyValue = parseInt(self.$target.css(cssProperty));
_.each(resize[0], function (val, key) {
for (const [key, val] of Object.entries(resize[0])) {
if (self.$target.hasClass(val)) {
current = key;
} else if (resize[1][key] === cssPropertyValue) {
current = key;
}
});
}
props.resize = resize;
props.current = current;
@@ -4551,9 +4551,9 @@ registry.sizing = SnippetOptionWidget.extend({
$body.on('mouseup', bodyMouseUp);
});
_.each(resizeValues, (value, key) => {
for (const [key, value] of Object.entries(resizeValues)) {
this.$handles.filter('.' + key).toggleClass('readonly', !value);
});
}
if (this.$target[0].classList.contains('o_grid_item')) {
this.$handles.filter('.o_grid_handle').toggleClass('readonly', false);
}
@@ -4661,7 +4661,7 @@ registry.sizing = SnippetOptionWidget.extend({
// Adapt the resize handles according to the classes and dimensions
var resizeValues = this._getSize();
var $handles = this.$overlay.find('.o_handle');
_.each(resizeValues, function (resizeValue, direction) {
for (const [direction, resizeValue] of Object.entries(resizeValues)) {
var classes = resizeValue[0];
var values = resizeValue[1];
var cssProperty = resizeValue[2];
@@ -4670,7 +4670,7 @@ registry.sizing = SnippetOptionWidget.extend({
var current = 0;
var cssPropertyValue = parseInt(self.$target.css(cssProperty));
_.each(classes, function (className, key) {
classes.forEach((className, key) => {
if (self.$target.hasClass(className)) {
current = key;
} else if (values[key] === cssPropertyValue) {
@@ -4680,7 +4680,7 @@ registry.sizing = SnippetOptionWidget.extend({
$handle.toggleClass('o_handle_start', current === 0);
$handle.toggleClass('o_handle_end', current === classes.length - 1);
});
}
// Adapt the handles to fit the left, top and bottom sizes
var ml = this.$target.css('margin-left');
@@ -4691,7 +4691,7 @@ registry.sizing = SnippetOptionWidget.extend({
this.$overlay.find('.o_handle.e').css({
width: 0,
});
_.each(this.$overlay.find(".o_handle.n, .o_handle.s"), function (handle) {
this.$overlay.find(".o_handle.n, .o_handle.s").toArray().forEach((handle) => {
var $handle = $(handle);
var direction = $handle.hasClass('n') ? 'top' : 'bottom';
$handle.height(self.$target.css('padding-' + direction));
@@ -5288,7 +5288,7 @@ registry.layout_column = SnippetOptionWidget.extend({
var colSize = Math.floor(12 / colsLength) || 1;
var colOffset = Math.floor((12 - colSize * colsLength) / 2);
var colClass = 'col-lg-' + colSize;
_.each($columns, function (column) {
$columns.toArray().forEach((column) => {
var $column = $(column);
$column.attr('class', $column.attr('class').replace(/\b(col|offset)-lg(-\d+)?\b/g, ''));
$column.addClass(colClass);
@@ -88,7 +88,7 @@ export default {
*/
computeFonts: _.once(function () {
var self = this;
_.each(this.fontIcons, function (data) {
this.fontIcons.forEach((data) => {
data.cssData = self.getCssSelectors(data.parser);
data.alias = _.flatten(_.map(data.cssData, _.property('names')));
});
@@ -121,11 +121,11 @@ const ColorPaletteWidget = Widget.extend({
colorpickerEl.querySelectorAll('button').forEach(el => el.classList.add('o_we_color_btn'));
// Populate tabs based on the tabs configuration indicated in this.tabs
_.each(this.tabs, (tab, index) => {
this.tabs.forEach((tab, index) => {
// Append pickers to section
const sectionEl = this.el.querySelector(`.o_colorpicker_sections[data-color-tab="${tab.id}"]`);
let sectionIsEmpty = true;
_.each(tab.pickers, pickerId => {
tab.pickers.forEach((pickerId) => {
let pickerEl;
switch (pickerId) {
case 'common_grays':
@@ -215,7 +215,7 @@ const ColorPaletteWidget = Widget.extend({
// Remove excluded palettes (note: only hide them to still be able
// to remove their related colors on the DOM target)
_.each(this.options.excluded, exc => {
this.options.excluded.forEach((exc) => {
this.$('[data-name="' + exc + '"]').addClass('d-none');
});
if (this.options.excludeSectionOf) {
@@ -367,7 +367,7 @@ const ColorPaletteWidget = Widget.extend({
this._addCustomColor(existingColors, color);
}
});
_.each(this.options.$editable.find('[style*="color"]'), el => {
this.options.$editable.find('[style*="color"]').toArray().forEach((el) => {
for (const colorProp of ['color', 'backgroundColor']) {
this._addCustomColor(existingColors, el.style[colorProp]);
}
+1 -1
View File
@@ -357,7 +357,7 @@ var keyboardMap = {
"91": "OS_KEY", // 'left command': Windows Key (Windows) or Command Key (Mac)
"93": "CONTEXT_MENU", // 'right command'
};
_.each(range(40, 127), function (keyCode) {
range(40, 127).forEach((keyCode) => {
if (!keyboardMap[keyCode]) {
keyboardMap[keyCode] = String.fromCharCode(keyCode);
}
@@ -17,7 +17,7 @@ export class AttributeTranslateDialog extends Component {
useEffect(() => {
this.translation = $(this.props.node).data('translation');
const $group = $('<div/>', {class: 'mb-3'}).appendTo(this.formEl.el);
_.each(this.translation, function (node, attr) {
for (const [attr, node] of Object.entries(this.translation)) {
const $node = $(node);
const $label = $('<label class="col-form-label"></label>').text(attr);
const $input = $('<input class="form-control"/>').val($node.html());
@@ -38,7 +38,7 @@ export class AttributeTranslateDialog extends Component {
$node.trigger('change');
});
$group.append($label).append($input);
});
}
}, () => [this.props.node]);
}
}
@@ -132,7 +132,7 @@ export class WebsiteTranslator extends WebsiteEditorComponent {
const $editable = this.getEditableArea();
const translationRegex = /<span [^>]*data-oe-translation-initial-sha="([^"]+)"[^>]*>(.*)<\/span>/;
let $edited = $();
_.each(attrs, function (attr) {
attrs.forEach((attr) => {
const attrEdit = $editable.filter('[' + attr + '*="data-oe-translation-initial-sha="]').filter(':empty, input, select, textarea, img');
attrEdit.each(function () {
var $node = $(this);
@@ -269,7 +269,7 @@ export class WebsiteTranslator extends WebsiteEditorComponent {
this.$translations.each(function () {
var $node = $(this);
var translation = $node.data('translation');
_.each(translation, function (node, attr) {
Object.values(translation).forEach((node) => {
var trans = self.getTranslationObject(node);
trans.value = (trans.value ? trans.value : $node.html()).replace(/[ \t\n\r]+/, ' ');
$node.attr('data-oe-translation-state', (trans.state || 'to_translate'));
@@ -109,7 +109,7 @@ var Dashboard = AbstractAction.extend({
render_dashboards: function() {
var self = this;
_.each(this.dashboards_templates, function(template) {
this.dashboards_templates.forEach((template) => {
self.$('.o_website_dashboard').append(QWeb.render(template, {widget: self}));
});
},
@@ -205,7 +205,7 @@ var Dashboard = AbstractAction.extend({
render_graphs: function() {
var self = this;
if (this._isInDom) {
_.each(this.graphs, function(e) {
this.graphs.forEach((e) => {
var renderGraph = self.groups[e.group] &&
self.dashboards_data[e.name].summary.order_count;
if (!self.chartIds[e.name]) {
@@ -165,10 +165,10 @@ var AnimationEffect = Class.extend(mixins.ParentedMixin, {
}
function _processEvents(events, namespace) {
events = events.split(' ');
return _.each(events, function (e, index) {
events[index] += ('.' + namespace);
}).join(' ');
return events
.split(" ")
.map((e) => (e += "." + namespace))
.join(" ");
}
},
/**
@@ -375,7 +375,7 @@ var Animation = publicWidget.Widget.extend({
*/
start: function () {
this._prepareEffects();
_.each(this._animationEffects, function (effect) {
this._animationEffects.forEach((effect) => {
effect.start();
});
return this._super.apply(this, arguments);
@@ -397,7 +397,7 @@ var Animation = publicWidget.Widget.extend({
this._animationEffects = [];
var self = this;
_.each(this.effects, function (desc) {
this.effects.forEach((desc) => {
self._addEffect(self[desc.update], desc.startEvents, _findTarget(desc.startTarget), {
getStateCallback: desc.getState && self[desc.getState],
endEvents: desc.endEvents || undefined,
@@ -462,9 +462,11 @@ registry.slider = publicWidget.Widget.extend({
this.$('img').off('.slider');
this.$el.carousel('pause');
this.$el.removeData('bs.carousel');
_.each(this.$('.carousel-item'), function (el) {
$(el).css('min-height', '');
});
this.$(".carousel-item")
.toArray()
.forEach((el) => {
$(el).css("min-height", "");
});
$(window).off('.slider');
},
@@ -479,7 +481,7 @@ registry.slider = publicWidget.Widget.extend({
var maxHeight = 0;
var $items = this.$('.carousel-item');
$items.css('min-height', '');
_.each($items, el => {
$items.toArray().forEach((el) => {
var $item = $(el);
var isActive = $item.hasClass('active');
this.options.wysiwyg && this.options.wysiwyg.odooEditor.observerUnactive('_computeHeights');
@@ -1265,7 +1267,7 @@ registry.WebsiteAnimate = publicWidget.Widget.extend({
// By default, elements are hidden by the css of o_animate.
// Render elements and trigger the animation then pause it in state 0.
_.each(this.$animatedElements, el => {
this.$animatedElements.toArray().forEach((el) => {
if (el.closest('.dropdown')) {
el.classList.add('o_animate_in_dropdown');
return;
@@ -1389,7 +1391,7 @@ registry.WebsiteAnimate = publicWidget.Widget.extend({
* @param {Element} el
*/
_scrollWebsiteAnimate(el) {
_.each(this.$('.o_animate:not(.o_animate_in_dropdown)'), el => {
this.$('.o_animate:not(.o_animate_in_dropdown)').toArray().forEach((el) => {
const $el = $(el);
const elHeight = el.offsetHeight;
const animateOnScroll = el.classList.contains('o_animate_on_scroll');
@@ -305,7 +305,7 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({
// Adapt font variable indexes to the removal
const style = window.getComputedStyle(this.$target[0].ownerDocument.documentElement);
_.each(FontFamilyPickerUserValueWidget.prototype.fontVariables, variable => {
FontFamilyPickerUserValueWidget.prototype.fontVariables.forEach((variable) => {
const value = weUtils.getCSSVariableValue(variable, style);
if (value.substring(1, value.length - 1) === googleFontName) {
// If an element is using the google font being removed, reset
@@ -1755,7 +1755,7 @@ options.registry.Carousel = options.Class.extend({
const id = 'myCarousel' + Date.now();
this.$target.attr('id', id);
this.$target.find('[data-bs-target]').attr('data-bs-target', '#' + id);
_.each(this.$target.find('[data-bs-slide], [data-bs-slide-to]'), function (el) {
this.$target.find('[data-bs-slide], [data-bs-slide-to]').toArray().forEach((el) => {
var $el = $(el);
if ($el.attr('data-bs-target')) {
$el.attr('data-bs-target', '#' + id);
@@ -103,9 +103,9 @@ options.registry.facebookPage = options.Class.extend({
} else {
this.fbData.height = 150;
}
_.each(this.fbData, (value, key) => {
for (const [key, value] of Object.entries(this.fbData)) {
this.$target[0].dataset[key] = value;
});
}
});
},
/**
@@ -163,7 +163,7 @@ options.registry.gallery = options.Class.extend({
var colClass = 'col-lg-' + (12 / columns);
var $container = this._replaceContent($row);
_.each(imgs, function (img, index) {
imgs.forEach((img, index) => {
var $img = $(img);
var $col = $('<div/>', {class: colClass});
$col.append($img).appendTo($row);
@@ -199,7 +199,7 @@ options.registry.gallery = options.Class.extend({
while (imgs.length) {
var min = Infinity;
var $lowest;
_.each(cols, function (col) {
cols.forEach((col) => {
var $col = $(col);
var height = $col.is(':empty') ? 0 : $col.find('img').last().offset().top + $col.find('img').last().height() - self.$target.offset().top;
if (height < min) {
@@ -244,7 +244,7 @@ options.registry.gallery = options.Class.extend({
this._replaceContent($row);
_.each(imgs, function (img) {
imgs.forEach((img) => {
var wrapClass = 'col-lg-3';
if (img.width >= img.height * 2 || img.width > 600) {
wrapClass = 'col-lg-6';
@@ -296,7 +296,7 @@ options.registry.gallery = options.Class.extend({
},
$slideshow = $(qweb.render('website.gallery.slideshow', params));
this._replaceContent($slideshow);
_.each(this.$('img'), function (img, index) {
this.$("img").toArray().forEach((img, index) => {
$(img).attr({contenteditable: true, 'data-index': index});
});
this.$target.css('height', Math.round(window.innerHeight * 0.7));
@@ -339,7 +339,7 @@ options.registry.gallery = options.Class.extend({
break;
}
position = imgs.indexOf(data.$image[0]);
_.each(imgs, function (img, index) {
imgs.forEach((img, index) => {
// Note: there might be more efficient ways to do that but it is
// more simple this way and allows compatibility with 10.0 where
// indexes were not the same as positions.
@@ -377,7 +377,7 @@ options.registry.gallery = options.Class.extend({
_adaptNavigationIDs: function () {
var uuid = new Date().getTime();
this.$target.find('.carousel').attr('id', 'slideshow_' + uuid);
_.each(this.$target.find('[data-bs-slide], [data-bs-slide-to]'), function (el) {
this.$target.find('[data-bs-slide], [data-bs-slide-to]').toArray().forEach((el) => {
var $el = $(el);
if ($el.attr('data-bs-target')) {
$el.attr('data-bs-target', '#slideshow_' + uuid);
@@ -21,7 +21,7 @@ options.registry.ProductCatalog = options.Class.extend({
const $name = $dishes.find('.s_product_catalog_dish_name');
$name.toggleClass('s_product_catalog_dish_dot_leaders', !widgetValue);
if (widgetValue) {
_.each($dishes, el => {
$dishes.toArray().forEach((el) => {
const $description = $(el).find('.s_product_catalog_dish_description');
if ($description.length) {
$description.removeClass('d-none');
@@ -35,7 +35,7 @@ options.registry.ProductCatalog = options.Class.extend({
}
});
} else {
_.each($dishes, el => {
$dishes.toArray().forEach((el) => {
const $description = $(el).find('.s_product_catalog_dish_description');
if ($description.hasClass('o_default_snippet_text') || $description.find('.o_default_snippet_text').length) {
$description.remove();
@@ -61,7 +61,7 @@ const TableOfContent = publicWidget.Widget.extend({
}
let position = 0;
const $fixedElements = $('.o_top_fixed_element');
_.each($fixedElements, el => position += $(el).outerHeight());
$fixedElements.toArray().forEach((el) => position += $(el).outerHeight());
const isHorizontalNavbar = this.$el.hasClass('s_table_of_content_horizontal_navbar');
this.$el.css('top', isHorizontalNavbar ? position : '');
this.$el.find('.s_table_of_content_navbar').css('top', isHorizontalNavbar ? '' : position + 20);
@@ -97,7 +97,7 @@ options.registry.TableOfContent = options.Class.extend({
this._disposeScrollSpy();
const $nav = this.$target.find('.s_table_of_content_navbar');
$nav.empty();
_.each(headingsEls, el => {
headingsEls.forEach((el) => {
const $el = $(el);
const id = 'table_of_content_heading_' + _.now() + '_' + _.uniqueId();
$('<a>').attr('href', "#" + id)
@@ -285,7 +285,7 @@ import { sprintf } from "@web/core/utils/strings";
// Serialize form inputs into a single object
// Aggregate multiple values into arrays
var form_values = {};
_.each(this.form_fields, function (input) {
this.form_fields.forEach((input) => {
if (input.name in form_values) {
// If a value already exists for this field,
// we are facing a x2many field, so we store
@@ -818,11 +818,13 @@ options.registry.WebsiteFieldEditor = FieldEditor.extend({
authorizedFieldsCache[model] = getFields;
}
this.existingFields = await getFields.then(fields => {
this.fields = _.each(fields, function (field, fieldName) {
this.existingFields = await getFields.then((fields) => {
this.fields = {};
for (const [fieldName, field] of Object.entries(fields)) {
field.name = fieldName;
field.domain = field.domain || [];
});
this.fields[fieldName] = field;
}
// Create the buttons for the type we-select
return Object.keys(fields).map(key => {
const field = fields[key];
@@ -64,7 +64,7 @@ publicWidget.registry.websiteEventTrackProposalFormTags = publicWidget.Widget.ex
fill_data: function (query, data) {
var that = this,
tags = {results: []};
_.each(data, function (obj) {
data.forEach((obj) => {
// select tags matching either category or tag name
if (that.matcher(query.term, obj[nameKey]) || that.matcher(query.term, obj.category_id[1])) {
if (obj.category_id[1]) {
@@ -93,7 +93,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
},
results: function (data) {
var ret = [];
_.each(data, function (x) {
data.forEach((x) => {
ret.push({
id: x.id,
text: x.name,
@@ -107,7 +107,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
// Take default tags from the input value
initSelection: function (element, callback) {
var data = [];
_.each(element.data('init-value'), function (x) {
element.data("init-value").forEach((x) => {
data.push({id: x.id, text: x.name, isNew: false});
});
element.val('');
@@ -115,7 +115,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
},
});
_.each($('textarea.o_wysiwyg_loader'), function (textarea) {
$('textarea.o_wysiwyg_loader').toArray().forEach((textarea) => {
var $textarea = $(textarea);
var editorKarma = $textarea.data('karma') || 0; // default value for backward compatibility
var $form = $textarea.closest('form');
@@ -146,7 +146,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
});
});
_.each(this.$('.o_wforum_bio_popover'), authorBox => {
this.$('.o_wforum_bio_popover').toArray().forEach((authorBox) => {
$(authorBox).popover({
trigger: 'hover',
offset: '10',
@@ -216,7 +216,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
ev.preventDefault();
setTimeout(function() {
var $buttons = $(ev.currentTarget).find('button[type="submit"], a.a-submit');
_.each($buttons, function (btn) {
$buttons.toArray().forEach((btn) => {
let $btn = $(btn);
$btn.find('i').remove();
$btn.prop('disabled', false);
@@ -443,7 +443,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
type: "warning",
});
} else {
_.each(this.$('.forum_answer'), answer => {
this.$('.forum_answer').toArray().forEach((answer) => {
var $answer = $(answer);
var isCorrect = $answer.is(target) ? data : false;
var $toggler = $answer.find('.o_wforum_validate_toggler');
@@ -600,7 +600,7 @@ publicWidget.registry.websiteForumSpam = publicWidget.Widget.extend({
],
kwargs: {}
}).then(function (o) {
_.each(o, function (r) {
Object.values(o).forEach((r) => {
r.content = $('<p>' + $(r.content).html() + '</p>').text().substring(0, 250);
});
self.$('div.post_spam').html(qweb.render('website_forum.spam_search_name', {
@@ -301,7 +301,7 @@ var RecentLinks = publicWidget.Widget.extend({
limit: 20,
},
}).then(function (result) {
_.each(result.reverse(), function (link) {
result.reverse().forEach((link) => {
self._addLink(link);
});
self._updateNotification();
@@ -74,7 +74,7 @@ publicWidget.registry.DonationSnippet = publicWidget.Widget.extend({
this.currency = result;
this.$('.s_donation_currency').remove();
const $prefilledButtons = this.$('.s_donation_btn, .s_range_bubble');
_.each($prefilledButtons, button => {
$prefilledButtons.toArray().forEach((button) => {
const before = result.position === "before";
const $currencySymbol = document.createElement('span');
$currencySymbol.innerText = result.symbol;
@@ -97,7 +97,7 @@ options.registry.Donation = options.Class.extend({
const valueList = JSON.parse(value);
const donationAmounts = [];
delete this.$target[0].dataset.donationAmounts;
_.each(valueList, value => {
valueList.forEach((value) => {
donationAmounts.push(value.display_name);
});
this.$target[0].dataset.donationAmounts = JSON.stringify(donationAmounts);
@@ -233,7 +233,7 @@ options.registry.Donation = options.Class.extend({
if (this.$target[0].dataset.descriptions) {
const $descriptions = this.$target.find('#s_donation_description_inputs > input');
const $tableEl = this.$el.find('we-list table');
_.each($tableEl.find('tr'), (trEl, i) => {
$tableEl.find("tr").toArray().forEach((trEl, i) => {
const $inputAmount = $(trEl).find('td').first();
$inputAmount.addClass('w-25');
const tdEl = document.createElement('td');
@@ -256,7 +256,7 @@ options.registry.Donation = options.Class.extend({
const descriptionInputs = this.$target.find('#s_donation_description_inputs');
descriptionInputs.empty();
const descriptions = this.$el.find('we-list input[type=text]');
_.each(descriptions, description => {
descriptions.toArray().forEach((description) => {
const inputEl = document.createElement('input');
inputEl.type = 'hidden';
inputEl.classList.add('o_translatable_input_hidden', 'd-block', 'mb-1', 'w-100');
@@ -760,9 +760,12 @@ options.registry.WebsiteSaleProductPage = options.Class.extend({
'input.js_variant_change:checked',
'select.js_variant_change'
];
_.each($container.find(variantsValuesSelectors.join(', ')), function (el) {
values.push(+$(el).val());
});
$container
.find(variantsValuesSelectors.join(", "))
.toArray()
.forEach((el) => {
values.push(+$(el).val());
});
return values;
},
@@ -69,7 +69,9 @@ publicWidget.registry.WebsiteSale = publicWidget.Widget.extend(VariantMixin, car
this._applyHashFromSearch();
_.each(this.$('div.js_product'), function (product) {
this.$("div.js_product")
.toArray()
.forEach((product) => {
$('input.js_product_change', product).first().trigger('change');
});
@@ -159,7 +161,7 @@ publicWidget.registry.WebsiteSale = publicWidget.Widget.extend(VariantMixin, car
if (params['attr']) {
var attributeIds = params['attr'].split(',');
var $inputs = this.$('input.js_variant_change, select.js_variant_change option');
_.each(attributeIds, function (id) {
attributeIds.forEach((id) => {
var $toSelect = $inputs.filter('[data-value_id="' + id + '"]');
if ($toSelect.is('input[type="radio"]')) {
$toSelect.prop('checked', true);
@@ -191,17 +193,15 @@ publicWidget.registry.WebsiteSale = publicWidget.Widget.extend(VariantMixin, car
* @param {Array} valueSelectors Selectors
*/
_changeAttribute: function (valueSelectors) {
_.each(valueSelectors, function (selector) {
$(selector).removeClass("active")
.filter(':has(input:checked)')
.addClass("active");
valueSelectors.forEach((selector) => {
$(selector).removeClass("active").filter(":has(input:checked)").addClass("active");
});
},
/**
* @private
*/
_changeCartQuantity: function ($input, value, $dom_optional, line_id, productIDs) {
_.each($dom_optional, function (elem) {
$($dom_optional).toArray().forEach((elem) => {
$(elem).find('.js_quantity').text(value);
productIDs.push($(elem).find('span[data-product-id]').data('product-id'));
});
@@ -259,7 +259,7 @@ publicWidget.registry.WebsiteSale = publicWidget.Widget.extend(VariantMixin, car
if (selectStates.data('init')===0 || selectStates.find('option').length===1) {
if (data.states.length || data.state_required) {
selectStates.html('');
_.each(data.states, function (x) {
data.states.forEach((x) => {
var opt = $('<option>').text(x[1])
.attr('value', x[0])
.attr('data-code', x[2]);
@@ -282,7 +282,7 @@ publicWidget.registry.WebsiteSale = publicWidget.Widget.extend(VariantMixin, car
$(".div_zip").after($(".div_city"));
}
var all_fields = ["street", "zip", "city", "country_name"]; // "state_code"];
_.each(all_fields, function (field) {
all_fields.forEach((field) => {
$(".checkout_autoformat .div_" + field.split('_')[0]).toggle($.inArray(field, data.fields)>=0);
});
}
@@ -38,7 +38,7 @@ publicWidget.registry.websiteSaleDelivery = publicWidget.Widget.extend({
}
await this._getCurrentLocation();
await _.each(carriers, async carrierInput => {
await carriers.forEach(async (carrierInput) => {
this._showLoading((carrierInput));
await this._handleCarrierUpdateResult(carrierInput)
});
@@ -145,7 +145,7 @@ var ProductComparison = publicWidget.Widget.extend(VariantMixin, {
}).then(function (data) {
self.comparelist_product_ids = JSON.parse(data.cookies);
delete data.cookies;
_.each(data, function (product) {
Object.values(data).forEach((product) => {
self.product_data[product.product.id] = product;
});
if (product_ids.length > Object.keys(data).length) {
@@ -191,7 +191,7 @@ var ProductComparison = publicWidget.Widget.extend(VariantMixin, {
_updateContent: function (force) {
var self = this;
this.$('.o_comparelist_products .o_product_row').remove();
_.each(this.comparelist_product_ids, function (res) {
this.comparelist_product_ids.forEach((res) => {
if (self.product_data.hasOwnProperty(res)) {
// It is possible that we do not have the required product_data for all IDs in
// comparelist_product_ids
@@ -13,7 +13,7 @@ publicWidget.registry.websiteSlides = publicWidget.Widget.extend({
start: function (parent) {
var defs = [this._super.apply(this, arguments)];
_.each($("timeago.timeago"), function (el) {
$("timeago.timeago").toArray().forEach((el) => {
var datetime = $(el).attr('datetime');
var datetimeObj = time.str_to_datetime(datetime);
// if presentation 7 days, 24 hours, 60 min, 60 second, 1000 millis old(one week)
@@ -130,7 +130,7 @@ var TagCourseDialog = Dialog.extend({
fill_data: function (query, data) {
var that = this,
tags = {results: []};
_.each(data, function (obj) {
Object.values(data).forEach((obj) => {
if (that.matcher(query.term, obj[nameKey])) {
tags.results.push({id: obj.id, text: obj[nameKey]});
}
@@ -231,7 +231,7 @@ var SlideUploadDialog = Dialog.extend({
var self = this;
// tags
var tagValues = [];
_.each(this.$('#tag_ids').select2('data'), function (val) {
this.$('#tag_ids').select2('data').forEach((val) => {
if (val.create) {
tagValues.push([0, 0, {'name': val.text}]);
} else {
@@ -312,7 +312,7 @@ var SlideUploadDialog = Dialog.extend({
fill_data: function (query, data) {
var self = this,
tags = {results: []};
_.each(data, function (obj) {
data.forEach((obj) => {
if (self.matcher(query.term, obj[nameKey])) {
tags.results.push({id: obj.id, text: obj[nameKey]});
}
@@ -77,7 +77,7 @@ publicWidget.registry.twitter = publicWidget.Widget.extend({
var tweetSlices = [tweets.slice(0, f).join(' '), tweets.slice(f, f * 2).join(' '), tweets.slice(f * 2, tweets.length).join(' ')];
self.$scroller = $(qweb.render('website.Twitter.Scroller')).appendTo($timeline);
_.each(self.$scroller.find('div[id^="scroller"]'), function (element, index) {
self.$scroller.find('div[id^="scroller"]').toArray().forEach((element, index) => {
var $scrollWrapper = $('<div/>', {class: 'scrollWrapper'});
var $scrollableArea = $('<div/>', {class: 'scrollableArea'});
$scrollWrapper.append($scrollableArea)
@@ -85,7 +85,7 @@ publicWidget.registry.twitter = publicWidget.Widget.extend({
$scrollableArea.append(tweetSlices[index]);
$(element).append($scrollWrapper);
var totalWidth = 0;
_.each($scrollableArea.children(), function (area) {
$scrollableArea.children().forEach((area) => {
totalWidth += $(area).outerWidth(true);
});
$scrollableArea.width(totalWidth);
@@ -115,7 +115,7 @@ publicWidget.registry.twitter = publicWidget.Widget.extend({
if (!this.$scroller) {
return;
}
_.each(this.$scroller.find('.scrollWrapper'), function (el) {
this.$scroller.find('.scrollWrapper').toArray().forEach((el) => {
var $wrapper = $(el);
$wrapper.data('getNextElementWidth', true);
$wrapper.data('autoScrollingInterval', setInterval(function () {
@@ -140,7 +140,7 @@ publicWidget.registry.twitter = publicWidget.Widget.extend({
if (!this.$scroller) {
return;
}
_.each(this.$scroller.find('.scrollWrapper'), function (el) {
this.$scroller.find('.scrollWrapper').toArray().forEach((el) => {
var $wrapper = $(el);
clearInterval($wrapper.data('autoScrollingInterval'));
});