[REF] website, *: remove (deprecated) $target uses in public widgets

*: auth_totp_portal, mail_group, portal, survey, web, website_event,
   website_event_track, website_mail, website_mail_group,
   website_mass_mailing, website_payment, website_sale

Although this is deprecated since 5 years with [1], new occurrences of
`this.$target` in widgets kept being introduced. `this.$el` can be used
just like in any other widget, or even better: `this.el` to not rely on
jQuery.

For now, this still keeps the definition. This just removes the bad uses
to prevent more copy/paste... let's delay the decision to remove the
definition entirely to another day.

[1]: https://github.com/odoo/odoo/commit/2972976962617d4b8a0113bae58c640ab41cdff8

closes odoo/odoo#106437

Related: odoo/design-themes#618
Related: odoo/enterprise#34343
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
qsm-odoo
2022-11-24 19:25:14 +01:00
parent 05a8f79b46
commit d49200feca
20 changed files with 135 additions and 135 deletions
@@ -278,7 +278,7 @@ publicWidget.registry.RevokeTrustedDeviceButton = publicWidget.Widget.extend({
this._rpc({
model: 'auth_totp.device',
method: 'remove',
args: [parseInt(this.target.id)]
args: [parseInt(this.el.id)]
})
);
window.location = window.location;
+12 -12
View File
@@ -15,8 +15,8 @@ publicWidget.registry.MailGroup = publicWidget.Widget.extend({
* @override
*/
start: function () {
this.mailgroupId = this.$target.data('id');
this.isMember = this.$target.data('isMember') || false;
this.mailgroupId = this.$el.data('id');
this.isMember = this.$el.data('isMember') || false;
const searchParams = (new URL(document.location.href)).searchParams;
this.token = searchParams.get('token');
this.forceUnsubscribe = searchParams.has('unsubscribe');
@@ -32,15 +32,15 @@ publicWidget.registry.MailGroup = publicWidget.Widget.extend({
*/
_onSubscribeBtnClick: async function (ev) {
ev.preventDefault();
const $email = this.$target.find(".o_mg_subscribe_email");
const $email = this.$el.find(".o_mg_subscribe_email");
const email = $email.val();
if (!email.match(/.+@.+/)) {
this.$target.addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid');
this.$el.addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid');
return false;
}
this.$target.removeClass('o_has_error').find('.form-control, .form-select').removeClass('is-invalid');
this.$el.removeClass('o_has_error').find('.form-control, .form-select').removeClass('is-invalid');
const action = (this.isMember || this.forceUnsubscribe) ? 'unsubscribe' : 'subscribe';
@@ -57,29 +57,29 @@ publicWidget.registry.MailGroup = publicWidget.Widget.extend({
if (response === 'added') {
this.isMember = true;
this.$target.find('.o_mg_subscribe_btn').text(_t('Unsubscribe')).removeClass('btn-primary').addClass('btn-outline-primary');
this.$el.find('.o_mg_subscribe_btn').text(_t('Unsubscribe')).removeClass('btn-primary').addClass('btn-outline-primary');
} else if (response === 'removed') {
this.isMember = false;
this.$target.find('.o_mg_subscribe_btn').text(_t('Subscribe')).removeClass('btn-outline-primary').addClass('btn-primary');
this.$el.find('.o_mg_subscribe_btn').text(_t('Subscribe')).removeClass('btn-outline-primary').addClass('btn-primary');
} else if (response === 'email_sent') {
// The confirmation email has been sent
this.$target.html(
this.$el.html(
$('<div class="o_mg_alert alert alert-success" role="alert"/>')
.text(_t('An email with instructions has been sent.'))
);
} else if (response === 'is_already_member') {
this.isMember = true;
this.$target.find('.o_mg_subscribe_btn').text(_t('Unsubscribe')).removeClass('btn-primary').addClass('btn-outline-primary');
this.$target.find('.o_mg_subscribe_form').before(
this.$el.find('.o_mg_subscribe_btn').text(_t('Unsubscribe')).removeClass('btn-primary').addClass('btn-outline-primary');
this.$el.find('.o_mg_subscribe_form').before(
$('<div class="o_mg_alert alert alert-warning" role="alert"/>')
.text(_t('This email is already subscribed.'))
);
} else if (response === 'is_not_member') {
if (!this.forceUnsubscribe) {
this.isMember = false;
this.$target.find('.o_mg_subscribe_btn').text(_t('Subscribe'));
this.$el.find('.o_mg_subscribe_btn').text(_t('Subscribe'));
}
this.$target.find('.o_mg_subscribe_form').before(
this.$el.find('.o_mg_subscribe_form').before(
$('<div class="o_mg_alert alert alert-warning" role="alert"/>')
.text(_t('This email is not subscribed.'))
);
+1 -1
View File
@@ -252,7 +252,7 @@ publicWidget.registry.RemoveAPIKeyButton = publicWidget.Widget.extend({
this._rpc({
model: 'res.users.apikeys',
method: 'remove',
args: [parseInt(this.target.id)]
args: [parseInt(this.el.id)]
})
);
window.location = window.location;
+3 -3
View File
@@ -42,7 +42,7 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa
var self = this;
this.fadeInOutDelay = 400;
return this._super.apply(this, arguments).then(function () {
self.options = self.$target.find('form').data();
self.options = self.$('form').data();
self.readonly = self.options.readonly;
self.selectedAnswers = self.options.selectedAnswers;
self.imgZoomer = false;
@@ -339,10 +339,10 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa
// Custom Events
// -------------------------------------------------------------------------
/**
* Changes the tooltip according to the type of the field.
* @param {Event} event
* @param {Event} event
*/
_updateEnterButtonText: function (event) {
const $target = event.target;
@@ -104,9 +104,9 @@ var RootWidget = Widget.extend({
var PublicWidget = Widget.extend({
/**
* The selector attribute, if defined, allows to automatically create an
* instance of this widget on page load for each DOM element which
* matches this selector. The `PublicWidget.$target` element will then be
* that particular DOM element. This should be the main way of instantiating
* instance of this widget on page load for each DOM element which matches
* this selector. The `PublicWidget.$el / el` element will then be that
* particular DOM element. This should be the main way of instantiating
* `PublicWidget` elements.
*
* @todo do not make this part of the Widget but rather an info to give when
@@ -337,7 +337,7 @@ var Animation = publicWidget.Widget.extend({
* @type {string} [startTarget]
* A selector to find the target where to listen for the start events
* (if no selector, the window target will be used). If the whole
* $target of the animation should be used, use the 'selector' string.
* element of the animation should be used, use the 'selector' string.
* @type {string} [endEvents]
* The name of the events which trigger the end of the effect (if none
* is defined, the animation will stop after a while
@@ -345,7 +345,7 @@ var Animation = publicWidget.Widget.extend({
* @type {string} [endTarget]
* A selector to find the target where to listen for the end events
* (if no selector, the startTarget will be used). If the whole
* $target of the animation should be used, use the 'selector' string.
* element of the animation should be used, use the 'selector' string.
* @type {string} update
* A string which refers to a method which will be used as the update
* callback for the effect. It receives 3 arguments: the animation
@@ -407,7 +407,7 @@ var Animation = publicWidget.Widget.extend({
function _findTarget(selector) {
if (selector) {
if (selector === 'selector') {
return self.$target;
return self.$el;
}
return self.$(selector);
}
@@ -446,7 +446,7 @@ registry.slider = publicWidget.Widget.extend({
this.$('img').on('load.slider', () => this._computeHeights());
this._computeHeights();
// Initialize carousel and pause if in edit mode.
this.$target.carousel(this.editableMode ? 'pause' : undefined);
this.$el.carousel(this.editableMode ? 'pause' : undefined);
$(window).on('resize.slider', _.debounce(() => this._computeHeights(), 250));
return this._super.apply(this, arguments);
},
@@ -456,8 +456,8 @@ registry.slider = publicWidget.Widget.extend({
destroy: function () {
this._super.apply(this, arguments);
this.$('img').off('.slider');
this.$target.carousel('pause');
this.$target.removeData('bs.carousel');
this.$el.carousel('pause');
this.$el.removeData('bs.carousel');
_.each(this.$('.carousel-item'), function (el) {
$(el).css('min-height', '');
});
@@ -539,7 +539,7 @@ registry.Parallax = Animation.extend({
this.$bg = this.$('> .s_parallax_bg');
// Get parallax speed
this.speed = parseFloat(this.$target.attr('data-scroll-background-ratio') || 0);
this.speed = parseFloat(this.$el.attr('data-scroll-background-ratio') || 0);
// Reset offset if parallax effect will not be performed and leave
var noParallaxSpeed = (this.speed === 0 || this.speed === 1);
@@ -554,8 +554,8 @@ registry.Parallax = Animation.extend({
// Initialize parallax data according to snippet and viewport dimensions
this.viewport = document.body.clientHeight - $('#wrapwrap').position().top;
this.visibleArea = [this.$target.offset().top];
this.visibleArea.push(this.visibleArea[0] + this.$target.innerHeight() + this.viewport);
this.visibleArea = [this.$el.offset().top];
this.visibleArea.push(this.visibleArea[0] + this.$el.innerHeight() + this.viewport);
this.ratio = this.speed * (this.viewport / 10);
// Provide a "safe-area" to limit parallax
@@ -657,7 +657,7 @@ registry.mediaVideo = publicWidget.Widget.extend(MobileYoutubeAutoplayMixin, {
// integrated with Odoo (this refactoring should be done in master).
const proms = [this._super.apply(this, arguments)];
let iframeEl = this.$target[0].querySelector(':scope > iframe');
let iframeEl = this.el.querySelector(':scope > iframe');
// The following code is only there to ensure compatibility with
// videos added before bug fixes or new Odoo versions where the
@@ -688,10 +688,10 @@ registry.mediaVideo = publicWidget.Widget.extend(MobileYoutubeAutoplayMixin, {
_generateIframe: function () {
// Bug fix / compatibility: empty the <div/> element as all information
// to rebuild the iframe should have been saved on the <div/> element
this.$target.empty();
this.$el.empty();
// Add extra content for size / edition
this.$target.append(
this.$el.append(
'<div class="css_editable_mode_display">&nbsp;</div>' +
'<div class="media_iframe_video_size">&nbsp;</div>'
);
@@ -700,7 +700,7 @@ registry.mediaVideo = publicWidget.Widget.extend(MobileYoutubeAutoplayMixin, {
// the src is saved in the 'data-src' attribute or the
// 'data-oe-expression' one (the latter is used as a workaround in 10.0
// system but should obviously be reviewed in master).
var src = _.escape(this.$target.data('oe-expression') || this.$target.data('src'));
var src = _.escape(this.$el.data('oe-expression') || this.$el.data('src'));
// Validate the src to only accept supported domains we can trust
var m = src.match(/^(?:https?:)?\/\/([^/?#]+)/);
if (!m) {
@@ -718,7 +718,7 @@ registry.mediaVideo = publicWidget.Widget.extend(MobileYoutubeAutoplayMixin, {
frameborder: '0',
allowfullscreen: 'allowfullscreen',
})[0];
this.$target.append(iframeEl);
this.$el.append(iframeEl);
return iframeEl;
},
});
@@ -754,15 +754,15 @@ registry.backgroundVideo = publicWidget.Widget.extend(MobileYoutubeAutoplayMixin
$(window).on('resize.' + this.iframeID, throttledUpdate);
const $modal = this.$target.closest('.modal');
const $modal = this.$el.closest('.modal');
if ($modal.length) {
$modal.on('show.bs.modal', () => {
const videoContainerEl = this.$target[0].querySelector('.o_bg_video_container');
const videoContainerEl = this.el.querySelector('.o_bg_video_container');
videoContainerEl.classList.add('d-none');
});
$modal.on('shown.bs.modal', () => {
this._adjustIframe();
const videoContainerEl = this.$target[0].querySelector('.o_bg_video_container');
const videoContainerEl = this.el.querySelector('.o_bg_video_container');
videoContainerEl.classList.remove('d-none');
});
}
@@ -803,8 +803,8 @@ registry.backgroundVideo = publicWidget.Widget.extend(MobileYoutubeAutoplayMixin
this.$iframe.removeClass('show');
// Adjust the iframe
var wrapperWidth = this.$target.innerWidth();
var wrapperHeight = this.$target.innerHeight();
var wrapperWidth = this.$el.innerWidth();
var wrapperHeight = this.$el.innerHeight();
var relativeRatio = (wrapperWidth / wrapperHeight) / (16 / 9);
var style = {};
if (relativeRatio >= 1.0) {
@@ -838,7 +838,7 @@ registry.backgroundVideo = publicWidget.Widget.extend(MobileYoutubeAutoplayMixin
this.$iframe.one('load', () => {
this.$bgVideoContainer.find('.o_bg_video_loading').remove();
});
this.$bgVideoContainer.prependTo(this.$target);
this.$bgVideoContainer.prependTo(this.$el);
$oldContainer.remove();
this._adjustIframe();
@@ -964,10 +964,10 @@ registry.anchorSlide = publicWidget.Widget.extend({
* @private
*/
_onAnimateClick: function (ev) {
if (this.$target[0].pathname !== window.location.pathname) {
if (this.el.pathname !== window.location.pathname) {
return;
}
var hash = this.$target[0].hash;
var hash = this.el.hash;
if (!utils.isValidAnchor(hash)) {
return;
}
@@ -1193,7 +1193,7 @@ registry.WebsiteAnimate = publicWidget.Widget.extend({
this.$scrollingElement = $().getScrollingElement();
// By default, elements are hidden by the css of o_animate.
// Render elements and trigger the animation then pause it in state 0.
this.$animatedElements = this.$target.find('.o_animate');
this.$animatedElements = this.$('.o_animate');
_.each(this.$animatedElements, el => {
if (el.closest('.dropdown')) {
el.classList.add('o_animate_in_dropdown');
@@ -1226,7 +1226,7 @@ registry.WebsiteAnimate = publicWidget.Widget.extend({
*/
destroy() {
this._super(...arguments);
this.$target.find('.o_animate')
this.$('.o_animate')
.removeClass('o_animating o_animated o_animate_preview o_animate_in_dropdown')
.css({
'animation-name': '',
@@ -1315,7 +1315,7 @@ registry.WebsiteAnimate = publicWidget.Widget.extend({
* @param {Element} el
*/
_scrollWebsiteAnimate(el) {
_.each(this.$target.find('.o_animate:not(.o_animate_in_dropdown)'), el => {
_.each(this.$('.o_animate:not(.o_animate_in_dropdown)'), el => {
const $el = $(el);
const elHeight = el.offsetHeight;
const animateOnScroll = el.classList.contains('o_animate_on_scroll');
@@ -1328,12 +1328,12 @@ registry.WebsiteAnimate = publicWidget.Widget.extend({
// not really one (eg 'discrete' layout), and should not be used as
// scrollTop value.
const scrollTop = document.body.classList.contains('modal-open') ?
this.$target.find('.modal:visible').scrollTop() :
this.$('.modal:visible').scrollTop() :
this.$scrollingElement.scrollTop();
const elTop = this._getElementOffsetTop(el) - scrollTop;
let visible;
const footerEl = el.closest('.o_footer_slideout');
const wrapEl = this.$target[0];
const wrapEl = this.el;
if (footerEl && wrapEl.classList.contains('o_footer_effect_enable')) {
// Since the footer slideout is always in the viewport but not
// always displayed, the way to calculate if an element is
@@ -1417,7 +1417,7 @@ registry.ImagesLazyLoading = publicWidget.Widget.extend({
// priority). However, the min-height would always be forced even once
// the image is loaded, which could mess with some layouts relying on
// the image intrinsic min-height.
const imgEls = this.$target[0].querySelectorAll('img[loading="lazy"]');
const imgEls = this.el.querySelectorAll('img[loading="lazy"]');
for (const imgEl of imgEls) {
// Write initial min-height on the dataset, so that it can also
// be properly restored on widget destroy.
@@ -1437,7 +1437,7 @@ registry.ImagesLazyLoading = publicWidget.Widget.extend({
*/
destroy() {
this._super(...arguments);
const imgEls = this.$target[0].querySelectorAll('img[data-lazy-loading-initial-min-height]');
const imgEls = this.el.querySelectorAll('img[data-lazy-loading-initial-min-height]');
for (const imgEl of imgEls) {
this._restoreImage(imgEl);
}
@@ -147,7 +147,7 @@ const DynamicSnippet = publicWidget.Widget.extend({
* @private
*/
_getQWebRenderOptions: function () {
const dataset = this.$target[0].dataset;
const dataset = this.el.dataset;
const numberOfRecords = parseInt(dataset.numberOfRecords);
let numberOfElements;
if (config.device.isMobile) {
@@ -26,9 +26,9 @@ const DynamicSnippetCarousel = DynamicSnippet.extend({
return Object.assign(
this._super.apply(this, arguments),
{
interval: parseInt(this.$target[0].dataset.carouselInterval),
rowPerSlide: parseInt(config.device.isMobile ? 1 : this.$target[0].dataset.rowPerSlide || 1),
arrowPosition: this.$target[0].dataset.arrowPosition || '',
interval: parseInt(this.el.dataset.carouselInterval),
rowPerSlide: parseInt(config.device.isMobile ? 1 : this.el.dataset.rowPerSlide || 1),
arrowPosition: this.el.dataset.arrowPosition || '',
},
);
},
@@ -79,7 +79,7 @@ const GallerySliderWidget = publicWidget.Widget.extend({
*/
start: function () {
var self = this;
this.$carousel = this.$target.is('.carousel') ? this.$target : this.$target.find('.carousel');
this.$carousel = this.$el.is('.carousel') ? this.$el : this.$('.carousel');
this.$indicator = this.$carousel.find('.carousel-indicators');
this.$prev = this.$indicator.find('li.o_indicators_left').css('visibility', ''); // force visibility as some databases have it hidden
this.$next = this.$indicator.find('li.o_indicators_right').css('visibility', '');
@@ -82,7 +82,7 @@ const PopupWidget = publicWidget.Widget.extend({
destroy: function () {
this._super.apply(this, arguments);
$(document).off('mouseleave.open_popup');
this.$target.find('.modal').modal('hide');
this.$el.find('.modal').modal('hide');
clearTimeout(this.timeout);
},
@@ -94,7 +94,7 @@ const PopupWidget = publicWidget.Widget.extend({
* @private
*/
_bindPopup: function () {
const $main = this.$target.find('.modal');
const $main = this.$el.find('.modal');
let display = $main.data('display');
let delay = $main.data('showAfter');
@@ -122,7 +122,7 @@ const PopupWidget = publicWidget.Widget.extend({
* @private
*/
_hidePopup: function () {
this.$target.find('.modal').modal('hide');
this.$el.find('.modal').modal('hide');
},
/**
* @private
@@ -131,7 +131,7 @@ const PopupWidget = publicWidget.Widget.extend({
if (this._popupAlreadyShown || !this._canShowPopup()) {
return;
}
this.$target.find('.modal').modal('show');
this.$el.find('.modal').modal('show');
},
//--------------------------------------------------------------------------
@@ -152,7 +152,7 @@ const PopupWidget = publicWidget.Widget.extend({
setCookie(this.el.id, this.cookieValue, nbDays * 24 * 60 * 60, 'required');
this._popupAlreadyShown = true;
this.$target.find('.media_iframe_video iframe').each((i, iframe) => {
this.$el.find('.media_iframe_video iframe').each((i, iframe) => {
iframe.src = '';
});
},
@@ -26,8 +26,8 @@ const TableOfContent = publicWidget.Widget.extend({
extraMenuUpdateCallbacks.splice(indexCallback, 1);
}
this._scrollingElement.scrollspy('dispose');
this.$target.css('top', '');
this.$target.find('.s_table_of_content_navbar').css('top', '');
this.$el.css('top', '');
this.$el.find('.s_table_of_content_navbar').css('top', '');
this._super(...arguments);
},
@@ -42,14 +42,14 @@ const TableOfContent = publicWidget.Widget.extend({
let position = 0;
const $fixedElements = $('.o_top_fixed_element');
_.each($fixedElements, el => position += $(el).outerHeight());
const isHorizontalNavbar = this.$target.hasClass('s_table_of_content_horizontal_navbar');
this.$target.css('top', isHorizontalNavbar ? position : '');
this.$target.find('.s_table_of_content_navbar').css('top', isHorizontalNavbar ? '' : position + 20);
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);
const $mainNavBar = $('#oe_main_menu_navbar');
position += $mainNavBar.length ? $mainNavBar.outerHeight() : 0;
position += isHorizontalNavbar ? this.$target.outerHeight() : 0;
position += isHorizontalNavbar ? this.$el.outerHeight() : 0;
this._scrollingElement = $().getScrollingElement();
this._scrollingElement.scrollspy({target: this.$target.find('.s_table_of_content_navbar'), method: 'offset', offset: position + 100, alwaysKeepFirstActive: true});
this._scrollingElement.scrollspy({target: this.$el.find('.s_table_of_content_navbar'), method: 'offset', offset: position + 100, alwaysKeepFirstActive: true});
},
});
@@ -24,7 +24,7 @@ odoo.define('website.s_website_form', function (require) {
// We do not initialize the datetime picker in edit mode but want the dates to be formated
const dateTimeFormat = time.getLangDatetimeFormat();
const dateFormat = time.getLangDateFormat();
this.$target[0].querySelectorAll('.s_website_form_input.datetimepicker-input').forEach(el => {
this.el.querySelectorAll('.s_website_form_input.datetimepicker-input').forEach(el => {
const value = el.getAttribute('value');
if (value) {
const format = el.closest('.s_website_form_field').dataset.type === 'date' ? dateFormat : dateTimeFormat;
@@ -55,7 +55,7 @@ odoo.define('website.s_website_form', function (require) {
},
willStart: async function () {
const res = this._super(...arguments);
if (!this.$target[0].classList.contains('s_website_form_no_recaptcha')) {
if (!this.el.classList.contains('s_website_form_no_recaptcha')) {
this._recaptchaLoaded = true;
this._recaptcha.loadLibs();
}
@@ -73,7 +73,7 @@ odoo.define('website.s_website_form', function (require) {
start: function () {
// Prepare visibility data and update field visibilities
const visibilityFunctionsByFieldName = new Map();
for (const fieldEl of this.$target[0].querySelectorAll('[data-visibility-dependency]')) {
for (const fieldEl of this.el.querySelectorAll('[data-visibility-dependency]')) {
const inputName = fieldEl.querySelector('.s_website_form_input').name;
if (!visibilityFunctionsByFieldName.has(inputName)) {
visibilityFunctionsByFieldName.set(inputName, []);
@@ -107,12 +107,12 @@ odoo.define('website.s_website_form', function (require) {
format: time.getLangDatetimeFormat(),
extraFormats: ['X'],
};
const $datetimes = this.$target.find('.s_website_form_datetime, .o_website_form_datetime'); // !compatibility
const $datetimes = this.$el.find('.s_website_form_datetime, .o_website_form_datetime'); // !compatibility
$datetimes.datetimepicker(datepickers_options);
// Adapt options to date-only pickers
datepickers_options.format = time.getLangDateFormat();
const $dates = this.$target.find('.s_website_form_date, .o_website_form_date'); // !compatibility
const $dates = this.$el.find('.s_website_form_date, .o_website_form_date'); // !compatibility
$dates.datetimepicker(datepickers_options);
this.$allDates = $datetimes.add($dates);
@@ -123,7 +123,7 @@ odoo.define('website.s_website_form', function (require) {
// Because, using t-att- inside form make it non-editable
// Data-fill-with attribute is given during registry and is used by
// to know which user data should be used to prfill fields.
const dataForEl = document.querySelector(`[data-for='${this.$target[0].id}']`);
const dataForEl = document.querySelector(`[data-for='${this.el.id}']`);
if (dataForEl || Object.keys(this.preFillValues).length) {
const dataForValues = dataForEl ?
JSON.parse(dataForEl.dataset.values
@@ -131,7 +131,7 @@ odoo.define('website.s_website_form', function (require) {
.replace('None', '""')
.replace(/'/g, '"')
) : {};
const fieldNames = this.$target.serializeArray().map(el => el.name);
const fieldNames = this.$el.serializeArray().map(el => el.name);
// All types of inputs do not have a value property (eg:hidden),
// for these inputs any function that is supposed to put a value
// property actually puts a HTML value attribute. Because of
@@ -140,7 +140,7 @@ odoo.define('website.s_website_form', function (require) {
// the values to submit() for these fields but this could break
// customizations that use the current behavior as a feature.
for (const name of fieldNames) {
const fieldEl = this.$target[0].querySelector(`[name="${name}"]`);
const fieldEl = this.el.querySelector(`[name="${name}"]`);
// In general, we want the data-for and prefill values to
// take priority over set default values. The 'email_to'
@@ -179,7 +179,7 @@ odoo.define('website.s_website_form', function (require) {
});
}
// Check disabled states
this.inputEls = this.$target[0].querySelectorAll('.s_website_form_field.s_website_form_field_hidden_if .s_website_form_input');
this.inputEls = this.el.querySelectorAll('.s_website_form_field.s_website_form_field_hidden_if .s_website_form_input');
this._disabledStates = new Map();
for (const inputEl of this.inputEls) {
this._disabledStates[inputEl] = inputEl.disabled;
@@ -190,15 +190,15 @@ odoo.define('website.s_website_form', function (require) {
destroy: function () {
this._super.apply(this, arguments);
this.$target.find('button').off('click');
this.$el.find('button').off('click');
// Empty imputs
this.$target[0].reset();
this.el.reset();
// Apply default values
const dateTimeFormat = time.getLangDatetimeFormat();
const dateFormat = time.getLangDateFormat();
this.$target[0].querySelectorAll('input[type="text"], input[type="email"], input[type="number"]').forEach(el => {
this.el.querySelectorAll('input[type="text"], input[type="email"], input[type="number"]').forEach(el => {
let value = el.getAttribute('value');
if (value) {
if (el.classList.contains('datetimepicker-input')) {
@@ -208,17 +208,17 @@ odoo.define('website.s_website_form', function (require) {
el.value = value;
}
});
this.$target[0].querySelectorAll('textarea').forEach(el => el.value = el.textContent);
this.el.querySelectorAll('textarea').forEach(el => el.value = el.textContent);
// Remove saving of the error colors
this.$target.find('.o_has_error').removeClass('o_has_error').find('.form-control, .form-select').removeClass('is-invalid');
this.$el.find('.o_has_error').removeClass('o_has_error').find('.form-control, .form-select').removeClass('is-invalid');
// Remove the status message
this.$target.find('#s_website_form_result, #o_website_form_result').empty(); // !compatibility
this.$el.find('#s_website_form_result, #o_website_form_result').empty(); // !compatibility
// Remove the success message and display the form
this.$target.removeClass('d-none');
this.$target.parent().find('.s_website_form_end_message').addClass('d-none');
this.$el.removeClass('d-none');
this.$el.parent().find('.s_website_form_end_message').addClass('d-none');
// Reinitialize dates
this.$allDates.removeClass('s_website_form_datepicker_initialized');
@@ -229,7 +229,7 @@ odoo.define('website.s_website_form', function (require) {
}
// All 'hidden if' fields start with d-none
this.$target[0].querySelectorAll('.s_website_form_field_hidden_if:not(.d-none)').forEach(el => el.classList.add('d-none'));
this.el.querySelectorAll('.s_website_form_field_hidden_if:not(.d-none)').forEach(el => el.classList.add('d-none'));
// Reset the initial default values.
for (const [fieldEl, initialValue] of this.initialValues.entries()) {
@@ -246,22 +246,22 @@ odoo.define('website.s_website_form', function (require) {
send: async function (e) {
e.preventDefault(); // Prevent the default submit behavior
// Prevent users from crazy clicking
const $button = this.$target.find('.s_website_form_send, .o_website_form_send');
const $button = this.$el.find('.s_website_form_send, .o_website_form_send');
$button.addClass('disabled') // !compatibility
.attr('disabled', 'disabled');
this.restoreBtnLoading = dom.addButtonLoadingEffect($button[0]);
var self = this;
self.$target.find('#s_website_form_result, #o_website_form_result').empty(); // !compatibility
self.$el.find('#s_website_form_result, #o_website_form_result').empty(); // !compatibility
if (!self.check_error_fields({})) {
self.update_status('error', _t("Please fill in the form correctly."));
return false;
}
// Prepare form inputs
this.form_fields = this.$target.serializeArray();
$.each(this.$target.find('input[type=file]:not([disabled])'), (outer_index, input) => {
this.form_fields = this.$el.serializeArray();
$.each(this.$el.find('input[type=file]:not([disabled])'), (outer_index, input) => {
$.each($(input).prop('files'), function (index, file) {
// Index field name as ajax won't accept arrays of files
// when aggregating multiple files into a single field value
@@ -293,7 +293,7 @@ odoo.define('website.s_website_form', function (require) {
});
// force server date format usage for existing fields
this.$target.find('.s_website_form_field:not(.s_website_form_custom)')
this.$el.find('.s_website_form_field:not(.s_website_form_custom)')
.find('.s_website_form_date, .s_website_form_datetime').each(function () {
var date = $(this).datetimepicker('viewDate').clone().locale('en');
var format = 'YYYY-MM-DD';
@@ -315,10 +315,10 @@ odoo.define('website.s_website_form', function (require) {
}
// Post form and handle result
ajax.post(this.$target.attr('action') + (this.$target.data('force_action') || this.$target.data('model_name')), form_values)
ajax.post(this.$el.attr('action') + (this.$el.data('force_action') || this.$el.data('model_name')), form_values)
.then(async function (result_data) {
// Restore send button behavior
self.$target.find('.s_website_form_send, .o_website_form_send')
self.$el.find('.s_website_form_send, .o_website_form_send')
.removeAttr('disabled')
.removeClass('disabled'); // !compatibility
result_data = JSON.parse(result_data);
@@ -331,10 +331,10 @@ odoo.define('website.s_website_form', function (require) {
}
} else {
// Success, redirect or update status
let successMode = self.$target[0].dataset.successMode;
let successPage = self.$target[0].dataset.successPage;
let successMode = self.el.dataset.successMode;
let successPage = self.el.dataset.successPage;
if (!successMode) {
successPage = self.$target.attr('data-success_page'); // Compatibility
successPage = self.$el.attr('data-success_page'); // Compatibility
successMode = successPage ? 'redirect' : 'nothing';
}
switch (successMode) {
@@ -356,8 +356,8 @@ odoo.define('website.s_website_form', function (require) {
// message)
await concurrency.delay(dom.DEBOUNCE);
self.$target[0].classList.add('d-none');
self.$target[0].parentElement.querySelector('.s_website_form_end_message').classList.remove('d-none');
self.el.classList.add('d-none');
self.el.parentElement.querySelector('.s_website_form_end_message').classList.remove('d-none');
return;
}
default: {
@@ -371,7 +371,7 @@ odoo.define('website.s_website_form', function (require) {
}
}
self.$target[0].reset();
self.el.reset();
self.restoreBtnLoading();
}
})
@@ -387,7 +387,7 @@ odoo.define('website.s_website_form', function (require) {
var self = this;
var form_valid = true;
// Loop on all fields
this.$target.find('.form-field, .s_website_form_field').each(function (k, field) { // !compatibility
this.$el.find('.form-field, .s_website_form_field').each(function (k, field) { // !compatibility
var $field = $(field);
// FIXME that seems broken, "for" does not contain the field
// but this is used to retrieve errors sent from the server...
@@ -501,7 +501,7 @@ odoo.define('website.s_website_form', function (require) {
update_status: function (status, message) {
if (status !== 'success') { // Restore send button behavior if result is an error
this.$target.find('.s_website_form_send, .o_website_form_send')
this.$el.find('.s_website_form_send, .o_website_form_send')
.removeAttr('disabled')
.removeClass('disabled'); // !compatibility
this.restoreBtnLoading();
@@ -624,7 +624,7 @@ odoo.define('website.s_website_form', function (require) {
return false;
}
const formData = new FormData(this.$target[0]);
const formData = new FormData(this.el);
const currentValueOfDependency = formData.get(dependencyName);
return this._compareTo(comparator, currentValueOfDependency, visibilityCondition, between);
};
@@ -18,7 +18,7 @@ publicWidget.registry.displayTimerWidget = publicWidget.Widget.extend({
start: function () {
var self = this;
return this._super.apply(this, arguments).then(function () {
self.options = self.$target.data();
self.options = self.$el.data();
self.preCountdownDisplay = self.options["preCountdownDisplay"];
self.preCountdownTime = self.options["preCountdownTime"];
self.preCountdownText = self.options["preCountdownText"];
@@ -163,7 +163,7 @@ publicWidget.registry.websiteEventTrackProposalForm = publicWidget.Widget.extend
ev.stopPropagation();
// Prevent further clicking
this.$target.find('.o_wetrack_proposal_submit_button')
this.$el.find('.o_wetrack_proposal_submit_button')
.addClass('disabled')
.attr('disabled', 'disabled');
@@ -192,7 +192,7 @@ publicWidget.registry.websiteEventTrackProposalForm = publicWidget.Widget.extend
}
// Restore button
this.$target.find('.o_wetrack_proposal_submit_button')
this.$el.find('.o_wetrack_proposal_submit_button')
.removeAttr('disabled')
.removeClass('disabled');
},
+1 -1
View File
@@ -45,7 +45,7 @@ publicWidget.registry.follow = publicWidget.Widget.extend({
// not if editable mode to allow designer to edit
if (!this.editableMode) {
$('.js_follow > .d-none').removeClass('d-none');
this.$target.find('.js_follow_btn, .js_unfollow_btn').on('click', function (event) {
this.$el.find('.js_follow_btn, .js_unfollow_btn').on('click', function (event) {
event.preventDefault();
self._onClick(event);
});
@@ -40,7 +40,7 @@ MailGroup.include({
}
if (this.isMember) {
this.$target.find('.o_mg_subscribe_btn').text(_t('Unsubscribe')).removeClass('btn-primary').addClass('btn-outline-primary');
this.$el.find('.o_mg_subscribe_btn').text(_t('Unsubscribe')).removeClass('btn-primary').addClass('btn-outline-primary');
}
this.$el.data('isMember', this.isMember);
@@ -40,7 +40,7 @@ publicWidget.registry.subscribe = publicWidget.Widget.extend({
return def;
}
const always = this._updateView.bind(this);
const inputName = this.$target[0].querySelector('input').name;
const inputName = this.el.querySelector('input').name;
return Promise.all([def, this._rpc({
route: '/website_mass_mailing/is_subscriber',
params: {
@@ -68,22 +68,22 @@ publicWidget.registry.subscribe = publicWidget.Widget.extend({
*/
_updateView(data) {
const isSubscriber = data.is_subscriber;
const subscribeBtnEl = this.$target[0].querySelector('.js_subscribe_btn');
const thanksBtnEl = this.$target[0].querySelector('.js_subscribed_btn');
const valueInputEl = this.$target[0].querySelector('input.js_subscribe_value');
const subscribeBtnEl = this.el.querySelector('.js_subscribe_btn');
const thanksBtnEl = this.el.querySelector('.js_subscribed_btn');
const valueInputEl = this.el.querySelector('input.js_subscribe_value');
subscribeBtnEl.disabled = isSubscriber;
valueInputEl.value = data.value || '';
valueInputEl.disabled = isSubscriber;
// Compat: remove d-none for DBs that have the button saved with it.
this.$target[0].classList.remove('d-none');
this.el.classList.remove('d-none');
subscribeBtnEl.classList.toggle('d-none', !!isSubscriber);
thanksBtnEl.classList.toggle('d-none', !isSubscriber);
},
_getListId: function () {
return this.$target.closest('[data-snippet=s_newsletter_block').data('list-id') || this.$target.data('list-id');
return this.$el.closest('[data-snippet=s_newsletter_block').data('list-id') || this.$el.data('list-id');
},
//--------------------------------------------------------------------------
@@ -98,10 +98,10 @@ publicWidget.registry.subscribe = publicWidget.Widget.extend({
const inputName = this.$('input').attr('name');
const $input = this.$(".js_subscribe_value:visible");
if (inputName === 'email' && $input.length && !$input.val().match(/.+@.+/)) {
this.$target.addClass('o_has_error').find('.form-control').addClass('is-invalid');
this.$el.addClass('o_has_error').find('.form-control').addClass('is-invalid');
return false;
}
this.$target.removeClass('o_has_error').find('.form-control').removeClass('is-invalid');
this.$el.removeClass('o_has_error').find('.form-control').removeClass('is-invalid');
const tokenObj = await this._recaptcha.getToken('website_mass_mailing_subscribe');
if (tokenObj.error) {
self.displayNotification({
@@ -126,7 +126,7 @@ publicWidget.registry.subscribe = publicWidget.Widget.extend({
self.$(".js_subscribe_btn").addClass('d-none');
self.$(".js_subscribed_btn").removeClass('d-none');
self.$('input.js_subscribe_value').prop('disabled', !!result);
const $popup = self.$target.closest('.o_newsletter_modal');
const $popup = self.$el.closest('.o_newsletter_modal');
if ($popup.length) {
$popup.modal('hide');
}
@@ -18,14 +18,14 @@ publicWidget.registry.WebsitePaymentDonation = publicWidget.Widget.extend({
* @param {Event} ev
*/
_onFocusAmountInput(ev) {
this.$target.find('#other_amount').prop("checked", true);
this.$el.find('#other_amount').prop("checked", true);
},
/**
* @private
* @param {Event} ev
*/
_onChangeDonationComment(ev) {
const $donationComment = this.$target.find('#donation_comment');
const $donationComment = this.$el.find('#donation_comment');
const checked = $(ev.currentTarget).is(':checked');
$donationComment.toggleClass('d-none', !checked);
if (!checked) {
@@ -18,7 +18,7 @@ publicWidget.registry.DonationSnippet = publicWidget.Widget.extend({
async start() {
await this._super(...arguments);
this.$rangeSlider = this.$('#s_donation_range_slider');
this.defaultAmount = this.$target[0].dataset.defaultAmount;
this.defaultAmount = this.el.dataset.defaultAmount;
if (this.$rangeSlider.length) {
this.$rangeSlider.val(this.defaultAmount);
this._setBubble(this.$rangeSlider);
@@ -29,7 +29,7 @@ publicWidget.registry.DonationSnippet = publicWidget.Widget.extend({
* @override
*/
destroy() {
this.$target.find('.s_donation_currency').remove();
this.$el.find('.s_donation_currency').remove();
this._deselectPrefilledButtons();
this.$('.alert-danger').remove();
this._super(...arguments);
@@ -114,13 +114,13 @@ publicWidget.registry.DonationSnippet = publicWidget.Widget.extend({
const $buttons = this.$('.s_donation_btn');
const $selectedButton = $buttons.filter('.active');
let amount = $selectedButton.length ? $selectedButton[0].dataset.donationValue : 0;
if (this.$target[0].dataset.displayOptions && !amount) {
if (this.el.dataset.displayOptions && !amount) {
if (this.$rangeSlider.length) {
amount = this.$rangeSlider.val();
} else if ($buttons.length) {
amount = parseFloat(this.$('#s_donation_amount_input').val());
let errorMessage = '';
const minAmount = this.$target[0].dataset.minimumAmount;
const minAmount = this.el.dataset.minimumAmount;
if (!amount) {
errorMessage = _t("Please select or enter an amount");
} else if (amount < parseFloat(minAmount)) {
@@ -1040,8 +1040,8 @@ publicWidget.registry.websiteSaleCarouselProduct = publicWidget.Widget.extend({
await this._super(...arguments);
this._updateCarouselPosition();
extraMenuUpdateCallbacks.push(this._updateCarouselPosition.bind(this));
if (this.$target.find('.carousel-indicators').length > 0) {
this.$target.on('slide.bs.carousel.carousel_product_slider', this._onSlideCarouselProduct.bind(this));
if (this.$el.find('.carousel-indicators').length > 0) {
this.$el.on('slide.bs.carousel.carousel_product_slider', this._onSlideCarouselProduct.bind(this));
$(window).on('resize.carousel_product_slider', _.throttle(this._onSlideCarouselProduct.bind(this), 150));
this._updateJustifyContent();
}
@@ -1050,8 +1050,8 @@ publicWidget.registry.websiteSaleCarouselProduct = publicWidget.Widget.extend({
* @override
*/
destroy() {
this.$target.css('top', '');
this.$target.off('.carousel_product_slider');
this.$el.css('top', '');
this.$el.off('.carousel_product_slider');
this._super(...arguments);
},
@@ -1063,7 +1063,7 @@ publicWidget.registry.websiteSaleCarouselProduct = publicWidget.Widget.extend({
* @private
*/
_updateCarouselPosition() {
this.$target.css('top', dom.scrollFixedOffset() + 5);
this.$el.css('top', dom.scrollFixedOffset() + 5);
},
//--------------------------------------------------------------------------
@@ -1078,11 +1078,11 @@ publicWidget.registry.websiteSaleCarouselProduct = publicWidget.Widget.extend({
* @param {Event} ev
*/
_onSlideCarouselProduct: function (ev) {
const isReversed = this.$target.css('flex-direction') === "column-reverse";
const isLeftIndicators = this.$target.hasClass('o_carousel_product_left_indicators');
const $indicatorsDiv = isLeftIndicators ? this.$target.find('.o_carousel_product_indicators') : this.$target.find('.carousel-indicators');
const isReversed = this.$el.css('flex-direction') === "column-reverse";
const isLeftIndicators = this.$el.hasClass('o_carousel_product_left_indicators');
const $indicatorsDiv = isLeftIndicators ? this.$el.find('.o_carousel_product_indicators') : this.$el.find('.carousel-indicators');
let indicatorIndex = $(ev.relatedTarget).index();
indicatorIndex = indicatorIndex > -1 ? indicatorIndex : this.$target.find('li.active').index();
indicatorIndex = indicatorIndex > -1 ? indicatorIndex : this.$el.find('li.active').index();
const $indicator = $indicatorsDiv.find('[data-bs-slide-to=' + indicatorIndex + ']');
const indicatorsDivSize = isLeftIndicators && !isReversed ? $indicatorsDiv.outerHeight() : $indicatorsDiv.outerWidth();
const indicatorSize = isLeftIndicators && !isReversed ? $indicator.outerHeight() : $indicator.outerWidth();
@@ -1100,10 +1100,10 @@ publicWidget.registry.websiteSaleCarouselProduct = publicWidget.Widget.extend({
* @private
*/
_updateJustifyContent: function () {
const $indicatorsDiv = this.$target.find('.carousel-indicators');
const $indicatorsDiv = this.$el.find('.carousel-indicators');
$indicatorsDiv.css('justify-content', 'start');
if (config.device.size_class <= config.device.SIZES.MD) {
if (($indicatorsDiv.children().last().position().left + this.$target.find('li').outerWidth()) < $indicatorsDiv.outerWidth()) {
if (($indicatorsDiv.children().last().position().left + this.$el.find('li').outerWidth()) < $indicatorsDiv.outerWidth()) {
$indicatorsDiv.css('justify-content', 'center');
}
}
@@ -1115,9 +1115,9 @@ publicWidget.registry.websiteSaleCarouselProduct = publicWidget.Widget.extend({
_onMouseWheel: function (ev) {
ev.preventDefault();
if (ev.originalEvent.deltaY > 0) {
this.$target.carousel('next');
this.$el.carousel('next');
} else {
this.$target.carousel('prev');
this.$el.carousel('prev');
}
},
});
@@ -1138,7 +1138,7 @@ publicWidget.registry.websiteSaleProductPageReviews = publicWidget.Widget.extend
* @override
*/
destroy() {
this.$target.find('.o_portal_chatter_composer').css('top', '');
this.$el.find('.o_portal_chatter_composer').css('top', '');
this._super(...arguments);
},
@@ -1150,7 +1150,7 @@ publicWidget.registry.websiteSaleProductPageReviews = publicWidget.Widget.extend
* @private
*/
_updateChatterComposerPosition() {
this.$target.find('.o_portal_chatter_composer').css('top', dom.scrollFixedOffset() + 20);
this.$el.find('.o_portal_chatter_composer').css('top', dom.scrollFixedOffset() + 20);
},
});