[REF] web, *: BS4, use custom BS4 checkbox everywhere

Before this commit, Odoo used checkboxes in three different ways:

- A simple <input type="checkbox"/>, mainly in the frontend. The style
  is browser dependant.

- Same as above but with the BS3, checkbox structure. The style is still
  the same, but the alignement is supposed to be better (which is not
  always the case).

- The Odoo official structure:
	```
	<div class="o_checkbox">
	    <input type="checkbox"/>
	    <span/>
	</div>
	```
  which allows to have a cross-browser checkbox style and correct
  alignements.

The goal after this commit is to only use the BS4 *custom* checkbox
structure to achieve the same goal as our official structure (and
remove that one):

```
<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="customCheck1">
  <label class="custom-control-label" for="customCheck1">...</label>
</div>
```

/!\ Labels are now required (use a zero-width space if necessary)
This commit is contained in:
qsm-odoo
2018-07-27 12:36:54 +02:00
parent 6e223b9273
commit f4fbaf1efa
22 changed files with 192 additions and 155 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ tour.register('hr_expense_tour' ,
content: _t('<p>Click on <b> Create Report </b> to create the report.</p>'),
position: 'right',
}, {
trigger: '.o_expense_tree .o_checkbox > input[type=checkbox]',
trigger: '.o_expense_tree input[type=checkbox]',
content: _t('<p>Select expenses to submit them to your manager</p>'),
position: 'bottom'
}, {
+7 -4
View File
@@ -28,14 +28,17 @@
<div class="o_composer_suggestedPartners">
<t t-foreach='widget.suggestedPartners' t-as='recipient'>
<div t-attf-title="Add as recipient and follower (reason: #{recipient.reason})">
<div class="o_checkbox">
<div class="custom-control custom-checkbox">
<input type="checkbox"
class="custom-control-input"
t-attf-id="o_composer_suggested_partners_p#{recipient_index}"
t-att-checked="recipient.checked ? 'checked' : undefined"
t-att-data-fullname="recipient.full_name"/>
<span/>
<label t-attf-for="o_composer_suggested_partners_p#{recipient_index}" class="custom-control-label">
<t t-esc="recipient.name"/>
<t t-if="recipient.email_address">(<t t-esc="recipient.email_address"/>)</t>
</label>
</div>
<t t-esc="recipient.name"/>
<t t-if="recipient.email_address">(<t t-esc="recipient.email_address"/>)</t>
</div>
</t>
</div>
+11 -8
View File
@@ -70,15 +70,18 @@
-->
<t t-name="mail.Followers.subtype">
<div role="menuitem" class="o_subtype dropdown-item">
<div class="o_checkbox">
<input type="checkbox" t-att-checked="record.followed"
t-att-id="'input_mail_followers_subtype_'+record.id+(dialog ? '_in_dialog': '')"
t-att-data-id="record.id" t-att-name="record.name" class="o_subtype_checkbox"/>
<span/>
<div class="custom-control custom-checkbox">
<input type="checkbox"
t-attf-id="input_mail_followers_subtype_#{record.id + (dialog ? '_in_dialog': '')}"
t-att-name="record.name"
class="custom-control-input o_subtype_checkbox"
t-att-checked="record.followed"
t-att-data-id="record.id"/>
<label t-attf-for="input_mail_followers_subtype_#{record.id + (dialog ? '_in_dialog': '')}"
class="custom-control-label">
<t t-esc="record.name"/>
</label>
</div>
<span t-att-for="'input_mail_followers_subtype_'+record.id+(dialog ? '_in_dialog': '')">
<t t-esc="record.name"/>
</span>
<i t-if="display_warning" class="fa fa-warning text-warning" role="img" aria-label="Warning" title="Warning"/>
</div>
</t>
+1 -1
View File
@@ -857,7 +857,7 @@ QUnit.test('chatter: discard changes on message post with post_refresh "recipien
$input.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER}));
// untick recipient as follower (prompts a res.partner form otherwise)
form.$('.o_checkbox input').prop('checked', false);
form.$('input[type="checkbox"]').prop('checked', false);
// send message
form.$('.oe_chatter .o_composer_button_send').click();
+24 -16
View File
@@ -261,33 +261,41 @@ return {
return $button;
},
/**
* Renders a checkbox with standard odoo template. This does not use any xml
* template to avoid forcing the frontend part to lazy load a xml file for
* each widget which might want to create a simple checkbox.
* Renders a checkbox with standard odoo/BS template. This does not use any
* xml template to avoid forcing the frontend part to lazy load a xml file
* for each widget which might want to create a simple checkbox.
*
* @param {Object} [options]
* @param {Object} [options.prop]
* Allows to set the input properties (disabled and checked states).
* @param {string} [options.text]
* The checkbox's associated text. If none is given then a simple
* checkbox without label structure is rendered.
* checkbox is rendered.
* @returns {jQuery}
*/
renderCheckbox: function (options) {
var $container = $('<div class="o_checkbox"><input type="checkbox"/><span/></div>');
var id = _.uniqueId('checkbox-');
var $container = $('<div/>', {
class: 'custom-control custom-checkbox',
});
var $input = $('<input/>', {
type: 'checkbox',
id: id,
class: 'custom-control-input',
});
var $label = $('<label/>', {
for: id,
class: 'custom-control-label',
text: options && options.text || '',
});
if (!options || !options.text) {
$label.html('&#8203;'); // BS checkboxes need some label content (so
// add a zero-width space when there is no text)
}
if (options && options.prop) {
$container.children('input').prop(options.prop);
$input.prop(options.prop);
}
if (options && options.text) {
$container = $('<label/>').append(
$container,
$('<span/>', {
class: 'ml8',
text: options.text,
})
);
}
return $container;
return $container.append($input, $label);
},
/**
* Sets the selection range of a given input or textarea
@@ -304,7 +304,6 @@ var AbstractField = Widget.extend({
this._reset(record, event);
return this._render() || $.when();
},
/**
* Remove the invalid class on a field
*/
@@ -312,7 +311,15 @@ var AbstractField = Widget.extend({
this.$el.removeClass('o_field_invalid');
this.$el.removeAttr('aria-invalid');
},
/**
* Sets the given id on the focusable element of the field and as 'for'
* attribute of potential internal labels.
*
* @param {string} id
*/
setIDForLabel: function (id) {
this.getFocusableElement().attr('id', id);
},
/**
* add the invalid class on a field
*/
@@ -320,7 +327,6 @@ var AbstractField = Widget.extend({
this.$el.addClass('o_field_invalid');
this.$el.attr('aria-invalid', 'true');
},
/**
* Update the modifiers with the newest value.
* Now this.attrs.modifiersValue can be used consistantly even with
@@ -701,8 +701,8 @@ var FieldBoolean = AbstractField.extend({
// The formatValue of boolean fields renders HTML elements similar to
// the one rendered by the widget itself. Even though the event might
// have been fired on the non-widget version of this field, we can still
// test the presence of its o_checkbox class.
if (activated && options && options.event && $(options.event.target).parents('.o_checkbox').length) {
// test the presence of its custom class.
if (activated && options && options.event && $(options.event.target).closest('.custom-control.custom-checkbox').length) {
this._setValue(!this.value); // Toggle the checkbox
}
return activated;
@@ -737,6 +737,15 @@ var FieldBoolean = AbstractField.extend({
}
return rendered;
},
/**
* Associates the 'for' attribute of the internal label.
*
* @override
*/
setIDForLabel: function (id) {
this._super.apply(this, arguments);
this.$('.custom-control-label').attr('for', id);
},
//--------------------------------------------------------------------------
// Private
@@ -1887,7 +1887,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
this.$color_picker.dropdown('toggle');
this.$color_picker.attr("tabindex", 1).focus();
if (!tagColor) {
this.$('.o_checkbox input').prop('checked', true);
this.$('.custom-checkbox input').prop('checked', true);
}
}
},
@@ -1909,7 +1909,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
var changes = {};
if ($target.is('.o_hide_in_kanban')) {
var $checkbox = $('.o_hide_in_kanban .o_checkbox input');
var $checkbox = $('.o_hide_in_kanban .custom-checkbox input');
$checkbox.prop('checked', !$checkbox.prop('checked')); // toggle checkbox
this.prevColors = this.prevColors ? this.prevColors : {};
if ($checkbox.is(':checked')) {
@@ -98,7 +98,7 @@ var SidebarFilter = Widget.extend(FieldManagerMixin, {
this.many2one.filter_ids = _.without(_.pluck(this.filters, 'value'), 'all');
}
this.$el.on('click', '.o_remove', this._onFilterRemove.bind(this));
this.$el.on('click', '.o_checkbox input', this._onFilterActive.bind(this));
this.$el.on('click', '.custom-checkbox input', this._onFilterActive.bind(this));
},
//--------------------------------------------------------------------------
@@ -902,7 +902,7 @@ var FormRenderer = BasicRenderer.extend({
// enterprise label will be displayed as many times as the field
// exists on settings.
var $widgets = self.$('.o_field_widget[name=' + widget.name + ']');
var $label = idForLabel ? self.$('label[for=' + idForLabel + ']') : $();
var $label = idForLabel ? self.$('.o_form_label[for=' + idForLabel + ']') : $();
$label = $label.eq($widgets.index(widget.$el));
if (config.debug || widget.attrs.help || widget.field.help) {
self._addFieldTooltip(widget, $label);
@@ -922,7 +922,7 @@ var FormRenderer = BasicRenderer.extend({
* @param {idForLabel} string
*/
_setIDForLabel: function (widget, idForLabel) {
widget.getFocusableElement().attr('id', idForLabel);
widget.setIDForLabel(idForLabel);
},
//--------------------------------------------------------------------------
+1 -1
View File
@@ -13,7 +13,7 @@
// Checkbox in editable list
// should be clickable and activate the row
&.o_editable_list .o_data_row:not(.o_selected_row) .o_data_cell {
.o_checkbox:not(.o_readonly_modifier) {
.custom-checkbox:not(.o_readonly_modifier) {
pointer-events: none;
}
}
-10
View File
@@ -1,10 +0,0 @@
//------------------------------------------------------------------------------
// Checkboxes
//------------------------------------------------------------------------------
div.o_checkbox {
display: inline-block;
vertical-align: sub;
> input + span {
display: none;
}
}
+15 -10
View File
@@ -868,10 +868,10 @@
<div role="menuitem" class="o_hide_in_kanban"
t-att-data-id="tag_id"
t-att-data-color="0">
<div class="o_checkbox">
<input type="checkbox"/>
<span/>
</div> Hide in Kanban
<div class="custom-control custom-checkbox">
<input type="checkbox" id="o_hide_in_kanban_checkbox" class="custom-control-input"/>
<label for="o_hide_in_kanban_checkbox" class="custom-control-label">Hide in Kanban</label>
</div>
</div>
</li>
</ul>
@@ -1283,10 +1283,16 @@
<input type="text" class="o_input"></input>
</div>
<div role="menuitem" class="dropdown-item-text o_save_name">
<span><div class="o_checkbox"><input type="checkbox"/><span/></div> Use by default</span>
<div class="custom-control custom-checkbox">
<input type="checkbox" id="o_fav_menu_use_by_default" class="custom-control-input"/>
<label for="o_fav_menu_use_by_default" class="custom-control-label">Use by default</label>
</div>
</div>
<div role="menuitem" class="dropdown-item-text o_save_name">
<span><div class="o_checkbox"><input type="checkbox"/><span/></div> Share with all users </span><span class="fa fa-users" role="img" aria-label="Users" title="Users"/>
<div class="custom-control custom-checkbox">
<input type="checkbox" id="o_fav_menu_share_all_users" class="custom-control-input"/>
<label for="o_fav_menu_share_all_users" class="custom-control-label">Share with all users <span class="fa fa-users" role="img" aria-label="Users" title="Users"/></label>
</div>
</div>
<div class="dropdown-item-text o_save_name">
<button role="menuitem" type="button" class="btn btn-primary">Save</button>
@@ -1392,11 +1398,10 @@
<div aria-atomic="true">
<div t-foreach="widget.m2mValues" t-as="m2m_value">
<t t-set="id_for_label" t-value="'o_many2many_checkbox_' + _.uniqueId()"/>
<div class="o_checkbox">
<input type="checkbox" t-att-id="id_for_label" t-att-data-record-id="JSON.stringify(m2m_value[0])"/>
<span/>
<div class="custom-control custom-checkbox">
<input type="checkbox" t-att-id="id_for_label" class="custom-control-input" t-att-data-record-id="JSON.stringify(m2m_value[0])"/>
<label t-att-for="id_for_label" class="custom-control-label o_form_label"><t t-esc="m2m_value[1]"/></label>
</div>
<label t-att-for="id_for_label" class="o_form_label"><t t-esc="m2m_value[1]"/></label>
</div>
</div>
</t>
+20 -13
View File
@@ -40,22 +40,29 @@
<h3 t-if="widget.title"><t t-esc="widget.title"/></h3>
<div class="o_calendar_filter_items">
<div t-foreach="widget.filters" t-as="filter" t-if="filter.display == null || filter.display" class="o_calendar_filter_item" t-att-data-value="filter.value" t-att-data-id="filter.id">
<div class="o_checkbox">
<input type="checkbox" name="selection" t-att-checked="(filter.active ? true : undefined)"/><span/>
<div class="custom-control custom-checkbox">
<input type="checkbox"
t-attf-id="o_calendar_filter_item_#{filter_index}"
name="selection"
class="custom-control-input"
t-att-checked="(filter.active ? true : undefined)"/>
<label t-attf-for="o_calendar_filter_item_#{filter_index}"
class="custom-control-label">
<t t-if="filter.value == 'all'">
<span><i class="fa fa-users fa-fw o_cal_avatar" role="img" aria-label="Avatar" title="Avatar"/></span>
</t>
<t t-if="widget.avatar_field &amp;&amp; (filter.value != 'all')">
<img t-attf-src="/web/image/#{widget.avatar_model}/#{filter.value}/#{widget.avatar_field}" class="o_cal_avatar" alt="Avatar"/>
</t>
<t t-set="color" t-value="widget.getColor(filter.color_index)"/>
<span t-if="typeof color === 'number'" t-attf-class="color_filter o_underline_color_#{widget.getColor(filter.color_index)}"><t t-esc="filter.label"/></span>
<span t-elif="color" t-attf-style="border-bottom: 4px solid #{color};"><t t-esc="filter.label"/></span>
<span t-else=""><t t-esc="filter.label"/></span>
</label>
</div>
<t t-if="filter.value == 'all'">
<span><i class="fa fa-users fa-fw o_cal_avatar" role="img" aria-label="Avatar" title="Avatar"/></span>
</t>
<t t-if="widget.avatar_field &amp;&amp; (filter.value != 'all')">
<img t-attf-src="/web/image/#{widget.avatar_model}/#{filter.value}/#{widget.avatar_field}" class="o_cal_avatar" alt="Avatar"/>
</t>
<t t-set="color" t-value="widget.getColor(filter.color_index)"/>
<span t-if="typeof color === 'number'" t-attf-class="color_filter o_underline_color_#{widget.getColor(filter.color_index)}"><t t-esc="filter.label"/></span>
<span t-elif="color" t-attf-style="border-bottom: 4px solid #{color};"><t t-esc="filter.label"/></span>
<span t-else=""><t t-esc="filter.label"/></span>
<t t-if="filter.id">
<span class="o_remove fa fa-times" title="Remove this favorite from the list" role="img" aria-label="Remove this favorite from the list"/>
</t>
</t>
</div>
</div>
</div>
@@ -233,12 +233,12 @@ QUnit.module('basic_fields', {
"checkbox should now be unchecked");
// check the checkbox by clicking on label
form.$('label').click();
form.$('label:first').click();
assert.strictEqual(form.$('.o_field_boolean input:checked').length, 1,
"checkbox should now be checked");
// uncheck it back
form.$('label').click();
form.$('label:first').click();
assert.strictEqual(form.$('.o_field_boolean input:checked').length, 0,
"checkbox should now be unchecked");
@@ -273,52 +273,52 @@ QUnit.module('basic_fields', {
arch: '<tree editable="bottom"><field name="bar"/></tree>',
});
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input').length, 5,
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .custom-checkbox input').length, 5,
"should have 5 checkboxes");
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input:checked').length, 4,
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .custom-checkbox input:checked').length, 4,
"should have 4 checked input");
// Edit a line
var $cell = list.$('tr.o_data_row:has(.o_checkbox input:checked) td:not(.o_list_record_selector)').first();
assert.ok($cell.find('.o_checkbox input:checked').prop('disabled'),
var $cell = list.$('tr.o_data_row:has(.custom-checkbox input:checked) td:not(.o_list_record_selector)').first();
assert.ok($cell.find('.custom-checkbox input:checked').prop('disabled'),
"input should be disabled in readonly mode");
$cell.click();
assert.ok(!$cell.find('.o_checkbox input:checked').prop('disabled'),
assert.ok(!$cell.find('.custom-checkbox input:checked').prop('disabled'),
"input should not have the disabled property in edit mode");
$cell.find('.o_checkbox input:checked').click();
$cell.find('.custom-checkbox input:checked').click();
// save
list.$buttons.find('.o_list_button_save').click();
$cell = list.$('tr.o_data_row:has(.o_checkbox input:not(:checked)) td:not(.o_list_record_selector)').first();
assert.ok($cell.find('.o_checkbox input:not(:checked)').prop('disabled'),
$cell = list.$('tr.o_data_row:has(.custom-checkbox input:not(:checked)) td:not(.o_list_record_selector)').first();
assert.ok($cell.find('.custom-checkbox input:not(:checked)').prop('disabled'),
"input should be disabled again");
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input').length, 5,
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .custom-checkbox input').length, 5,
"should still have 5 checkboxes");
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input:checked').length, 3,
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .custom-checkbox input:checked').length, 3,
"should now have only 3 checked input");
// Re-Edit the line and fake-check the checkbox
$cell.click();
$cell.find('.o_checkbox input').click(); // Change the checkbox
$cell.find('.o_checkbox input').click(); // Undo the change
$cell.find('.custom-checkbox input').click(); // Change the checkbox
$cell.find('.custom-checkbox input').click(); // Undo the change
// Save
list.$buttons.find('.o_list_button_save').click();
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input').length, 5,
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .custom-checkbox input').length, 5,
"should still have 5 checkboxes");
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input:checked').length, 3,
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .custom-checkbox input:checked').length, 3,
"should still have only 3 checked input");
// Re-Edit the line to check the checkbox back but this time click on
// the checkbox directly in readonly mode !
$cell = list.$('tr.o_data_row:has(.o_checkbox input:not(:checked)) td:not(.o_list_record_selector)').first();
$cell.find('.o_checkbox span').click();
$cell = list.$('tr.o_data_row:has(.custom-checkbox input:not(:checked)) td:not(.o_list_record_selector)').first();
$cell.find('.custom-checkbox .custom-control-label').click();
// save
list.$buttons.find('.o_form_button_save').click();
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input').length, 5,
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .custom-checkbox input').length, 5,
"should still have 5 checkboxes");
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input:checked').length, 4,
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .custom-checkbox input:checked').length, 4,
"should now have 4 checked input back");
list.destroy();
});
@@ -370,8 +370,8 @@ QUnit.module('basic_fields', {
res_id: 2,
});
assert.strictEqual(form.$(".o_checkbox.o_boolean_toggle").length, 1, "Boolean toggle widget applied to boolean field");
assert.strictEqual(form.$(".o_checkbox.o_boolean_toggle").find(".slider").length, 1, "Boolean toggle contains slider to toggle");
assert.strictEqual(form.$(".custom-checkbox.o_boolean_toggle").length, 1, "Boolean toggle widget applied to boolean field");
assert.strictEqual(form.$(".custom-checkbox.o_boolean_toggle").find(".slider").length, 1, "Boolean toggle contains slider to toggle");
form.destroy();
});
@@ -10698,23 +10698,23 @@ QUnit.module('relational_fields', {
}
});
assert.notOk(form.$('.o_checkbox input').eq(0).prop('checked'),
assert.notOk(form.$('.custom-checkbox input').eq(0).prop('checked'),
"first checkbox should not be checked");
assert.notOk(form.$('.o_checkbox input').eq(1).prop('checked'),
assert.notOk(form.$('.custom-checkbox input').eq(1).prop('checked'),
"second checkbox should not be checked");
assert.ok(form.$('.o_checkbox input').eq(2).prop('checked'),
assert.ok(form.$('.custom-checkbox input').eq(2).prop('checked'),
"third checkbox should be checked");
form.$('.o_checkbox input:checked').click(); // Uncheck default record
form.$('.o_checkbox input').first().click(); // Check first record
form.$('.o_checkbox input').first().click(); // Uncheck first record
form.$('.o_checkbox input').first().click(); // Recheck first record
form.$('.custom-checkbox input:checked').click(); // Uncheck default record
form.$('.custom-checkbox input').first().click(); // Check first record
form.$('.custom-checkbox input').first().click(); // Uncheck first record
form.$('.custom-checkbox input').first().click(); // Recheck first record
assert.ok(form.$('.o_checkbox input').eq(0).prop('checked'),
assert.ok(form.$('.custom-checkbox input').eq(0).prop('checked'),
"first checkbox should be checked");
assert.notOk(form.$('.o_checkbox input').eq(1).prop('checked'),
assert.notOk(form.$('.custom-checkbox input').eq(1).prop('checked'),
"second checkbox should not be checked");
assert.notOk(form.$('.o_checkbox input').eq(2).prop('checked'),
assert.notOk(form.$('.custom-checkbox input').eq(2).prop('checked'),
"third checkbox should not be checked");
form.$buttons.find('.o_form_button_save').click();
@@ -10745,23 +10745,23 @@ QUnit.module('relational_fields', {
}
});
assert.notOk(form.$('.o_checkbox input').eq(0).prop('checked'),
assert.notOk(form.$('.custom-checkbox input').eq(0).prop('checked'),
"first checkbox should not be checked");
assert.notOk(form.$('.o_checkbox input').eq(1).prop('checked'),
assert.notOk(form.$('.custom-checkbox input').eq(1).prop('checked'),
"second checkbox should not be checked");
assert.ok(form.$('.o_checkbox input').eq(2).prop('checked'),
assert.ok(form.$('.custom-checkbox input').eq(2).prop('checked'),
"third checkbox should be checked");
form.$('.o_checkbox input:checked').click(); // Uncheck default record
form.$('.o_checkbox input').first().click(); // Check first record
form.$('.o_checkbox input').first().click(); // Uncheck first record
form.$('.o_checkbox input').first().click(); // Recheck first record
form.$('.custom-checkbox input:checked').click(); // Uncheck default record
form.$('.custom-checkbox input').first().click(); // Check first record
form.$('.custom-checkbox input').first().click(); // Uncheck first record
form.$('.custom-checkbox input').first().click(); // Recheck first record
assert.ok(form.$('.o_checkbox input').eq(0).prop('checked'),
assert.ok(form.$('.custom-checkbox input').eq(0).prop('checked'),
"first checkbox should be checked");
assert.notOk(form.$('.o_checkbox input').eq(1).prop('checked'),
assert.notOk(form.$('.custom-checkbox input').eq(1).prop('checked'),
"second checkbox should not be checked");
assert.notOk(form.$('.o_checkbox input').eq(2).prop('checked'),
assert.notOk(form.$('.custom-checkbox input').eq(2).prop('checked'),
"third checkbox should not be checked");
form.$buttons.find('.o_form_button_save').click();
@@ -11649,10 +11649,10 @@ QUnit.module('relational_fields', {
// checkbox 'Hide in Kanban'
$input = form.$('.o_field_many2manytags button[data-id=13]'); // selects 'red' tag
$input.click(); // opens the colorpicker dropdown
assert.ok(form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .o_checkbox'), "should have a checkbox in the colorpicker dropdown menu");
assert.ok(form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .custom-checkbox'), "should have a checkbox in the colorpicker dropdown menu");
$input.click();
var $checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .o_checkbox input');
var $checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .custom-checkbox input');
assert.notOk($checkBox.is(':checked'), "should have unticked checkbox in colorpicker dropdown menu");
$checkBox.mousedown();
@@ -11660,7 +11660,7 @@ QUnit.module('relational_fields', {
assert.equal($input.data('color'), "0", "should become transparent when toggling on checkbox");
$input.click();
$checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .o_checkbox input'); // refresh
$checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .custom-checkbox input'); // refresh
assert.ok($checkBox.is(':checked'), "should have a ticked checkbox in colorpicker dropdown menu after mousedown");
$checkBox.mousedown();
@@ -11668,7 +11668,7 @@ QUnit.module('relational_fields', {
assert.equal($input.data('color'), "8", "should revert to old color when toggling off checkbox");
$input.click();
$checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .o_checkbox input'); // refresh
$checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .custom-checkbox input'); // refresh
assert.notOk($checkBox.is(':checked'), "should have an unticked checkbox in colorpicker dropdown menu after 2nd click");
// TODO: it would be nice to test the behaviors of the autocomplete dropdown
@@ -12285,24 +12285,24 @@ QUnit.module('relational_fields', {
res_id: 1,
});
assert.strictEqual(form.$('div.o_field_widget div.o_checkbox').length, 2,
assert.strictEqual(form.$('div.o_field_widget div.custom-checkbox').length, 2,
"should have fetched and displayed the 2 values of the many2many");
assert.ok(form.$('div.o_field_widget div.o_checkbox input').eq(0).prop('checked'),
assert.ok(form.$('div.o_field_widget div.custom-checkbox input').eq(0).prop('checked'),
"first checkbox should be checked");
assert.notOk(form.$('div.o_field_widget div.o_checkbox input').eq(1).prop('checked'),
assert.notOk(form.$('div.o_field_widget div.custom-checkbox input').eq(1).prop('checked'),
"second checkbox should not be checked");
assert.ok(form.$('div.o_field_widget div.o_checkbox input').prop('disabled'),
assert.ok(form.$('div.o_field_widget div.custom-checkbox input').prop('disabled'),
"the checkboxes should be disabled");
form.$buttons.find('.o_form_button_edit').click();
assert.notOk(form.$('div.o_field_widget div.o_checkbox input').prop('disabled'),
assert.notOk(form.$('div.o_field_widget div.custom-checkbox input').prop('disabled'),
"the checkboxes should not be disabled");
// add a m2m value by clicking on input
form.$('div.o_field_widget div.o_checkbox input').eq(1).click();
form.$('div.o_field_widget div.custom-checkbox input').eq(1).click();
form.$buttons.find('.o_form_button_save').click();
assert.deepEqual(this.data.partner.records[0].timmy, [12, 14],
"should have added the second element to the many2many");
@@ -12311,13 +12311,13 @@ QUnit.module('relational_fields', {
// remove a m2m value by clinking on label
form.$buttons.find('.o_form_button_edit').click();
form.$('div.o_field_widget div.o_checkbox + label').eq(0).click();
form.$('div.o_field_widget div.custom-checkbox > label').eq(0).click();
form.$buttons.find('.o_form_button_save').click();
assert.deepEqual(this.data.partner.records[0].timmy, [14],
"should have removed the first element to the many2many");
assert.notOk(form.$('div.o_field_widget div.o_checkbox input').eq(0).prop('checked'),
assert.notOk(form.$('div.o_field_widget div.custom-checkbox input').eq(0).prop('checked'),
"first checkbox should be checked");
assert.ok(form.$('div.o_field_widget div.o_checkbox input').eq(1).prop('checked'),
assert.ok(form.$('div.o_field_widget div.custom-checkbox input').eq(1).prop('checked'),
"second checkbox should not be checked");
form.destroy();
@@ -12338,12 +12338,12 @@ QUnit.module('relational_fields', {
viewOptions: {mode: 'edit'},
});
form.$('div.o_field_widget div.o_checkbox input').eq(0).click();
form.$('div.o_field_widget div.o_checkbox input').eq(1).click();
form.$('div.o_field_widget div.custom-checkbox input').eq(0).click();
form.$('div.o_field_widget div.custom-checkbox input').eq(1).click();
form.$buttons.find('.o_form_button_save').click();
assert.notOk(form.$('div.o_field_widget div.o_checkbox input').eq(0).prop('checked'),
assert.notOk(form.$('div.o_field_widget div.custom-checkbox input').eq(0).prop('checked'),
"first checkbox should not be checked");
assert.notOk(form.$('div.o_field_widget div.o_checkbox input').eq(1).prop('checked'),
assert.notOk(form.$('div.o_field_widget div.custom-checkbox input').eq(1).prop('checked'),
"second checkbox should not be checked");
form.destroy();
@@ -193,7 +193,7 @@ QUnit.module('Views', {
// filters which has no value should show with string "Undefined" and should show at the last
assert.strictEqual($typeFilter.find('.o_calendar_filter_item:last').data('value'), false, "filters having false value should be displayed at last in filter items");
assert.strictEqual($typeFilter.find('.o_calendar_filter_item:last > span').text(), "Undefined", "filters having false value should display 'Undefined' string");
assert.strictEqual($typeFilter.find('.o_calendar_filter_item:last span').text(), "Undefined", "filters having false value should display 'Undefined' string");
var $attendeesFilter = $sidebar.find('.o_calendar_filter:has(h3:contains(attendees))');
assert.ok($attendeesFilter.length, "should display 'attendees' filter");
@@ -202,9 +202,9 @@ QUnit.module('Views', {
assert.strictEqual(calendar.$('.fc-event').length, 7,
"should display 7 events ('event 5' counts for 2 because it spans two weeks and thus generate two fc-event elements)");
calendar.$('.o_calendar_filter .o_checkbox input').first().click(); // Disable first filter
calendar.$('.o_calendar_filter .custom-checkbox input').first().click(); // Disable first filter
assert.strictEqual(calendar.$('.fc-event').length, 4, "should now only display 4 event");
calendar.$('.o_calendar_filter .o_checkbox input').eq(1).click(); // Disable second filter
calendar.$('.o_calendar_filter .custom-checkbox input').eq(1).click(); // Disable second filter
assert.strictEqual(calendar.$('.fc-event').length, 0, "should not display any event anymore");
// test search bar in filter
+7 -7
View File
@@ -165,7 +165,7 @@ QUnit.module('Views', {
assert.strictEqual(form.$('div.o_field_one2many table').length, 1,
"should render a one2many relation");
assert.strictEqual(form.$('tbody td:not(.o_list_record_selector) .o_checkbox input:checked').length, 1,
assert.strictEqual(form.$('tbody td:not(.o_list_record_selector) .custom-checkbox input:checked').length, 1,
"1 checkboxes should be checked");
assert.strictEqual(form.get('title'), "second record",
@@ -2102,10 +2102,10 @@ QUnit.module('Views', {
res_id: 1,
});
assert.strictEqual(form.$("label").length, 2, "should have rendered only two label");
assert.strictEqual(form.$("label").first().text(), "Product",
assert.strictEqual(form.$("label.o_form_label").length, 2, "should have rendered only two label");
assert.strictEqual(form.$("label.o_form_label").first().text(), "Product",
"one should be the one for the product field");
assert.strictEqual(form.$("label").eq(1).text(), "Bar",
assert.strictEqual(form.$("label.o_form_label").eq(1).text(), "Bar",
"one should be the one for the bar field");
assert.strictEqual(form.$('.firstgroup td').first().attr('colspan'), undefined,
@@ -4265,9 +4265,9 @@ QUnit.module('Views', {
assert.strictEqual(form.$('.oe_button_box').children().length, 2,
"button box should contain two children");
assert.strictEqual(form.$('.oe_button_box .oe_stat_button').length, 1,
assert.strictEqual(form.$('.oe_button_box > .oe_stat_button').length, 1,
"button box should only contain one button");
assert.strictEqual(form.$('.oe_button_box label').length, 1,
assert.strictEqual(form.$('.oe_button_box > label').length, 1,
"button box should only contain one label");
form.destroy();
@@ -6547,7 +6547,7 @@ QUnit.module('Views', {
'</form>',
});
assert.strictEqual(form.$el.text(), '{"foo":"My little Foo Value","bar":false}',
assert.strictEqual(form.$('.o_widget').text(), '{"foo":"My little Foo Value","bar":false}',
"widget should have been instantiated");
form.destroy();
+1 -1
View File
@@ -3235,7 +3235,7 @@ QUnit.module('Views', {
});
assert.verifySteps(['bar', 'res_currency'], "should have done 1 name_get by model in reference values");
assert.strictEqual(list.$('tbody td').text(), "Value 1USDEUREUR",
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector)').text(), "Value 1USDEUREUR",
"should have the display_name of the reference");
list.destroy();
});
@@ -1254,7 +1254,7 @@ body.editor_enable {
align-items: center;
font-size: 11px;
> .o_checkbox {
> .custom-control {
margin-right: $grid-gutter-width/4;
}
}
+12 -6
View File
@@ -14,16 +14,22 @@
<select id="ace-view-list" class="o_res_list"/>
<select id="ace-scss-list" class="o_res_list d-none"/>
<label class="o_include_option oe_include_bundles">
<div class="o_checkbox">
<input type="checkbox" class="js_include_bundles" t-att-checked="widget.options.includeBundles ? 'checked' : undefined"/><span/>
<div class="custom-control custom-checkbox">
<input type="checkbox" id="o_ace_view_editor_include_bundle"
class="custom-control-input js_include_bundles"
t-att-checked="widget.options.includeBundles ? 'checked' : undefined"/>
<label for="o_ace_view_editor_include_bundle"
class="custom-control-label">Include Asset Bundles</label>
</div>
Include Asset Bundles
</label>
<label class="o_include_option o_include_all_scss d-none">
<div class="o_checkbox">
<input type="checkbox" class="js_include_all_scss" t-att-checked="widget.options.includeAllSCSS ? 'checked' : undefined"/><span/>
<div class="custom-control custom-checkbox">
<input type="checkbox" id="o_ace_view_editor_include_all_scss"
class="custom-control-input js_include_all_scss"
t-att-checked="widget.options.includeAllSCSS ? 'checked' : undefined"/>
<label for="o_ace_view_editor_include_all_scss"
class="custom-control-label">Include All SCSS Files</label>
</div>
Include All SCSS Files
</label>
<div class="o_button_section">
<button data-action="save" type="submit" class="btn btn-primary">Save</button>
@@ -45,15 +45,15 @@ tour.register('main_flow_tour', {
content: _t('Go to inventory tab'),
position: 'top',
}, {
trigger: '.o_field_widget[name=route_ids] .o_checkbox + label:contains("Manufacture")',
trigger: '.o_field_widget[name=route_ids] .custom-checkbox > label:contains("Manufacture")',
content: _t('Check Manufacture'),
position: 'right',
}, {
trigger: '.o_field_widget[name=route_ids] .o_checkbox + label:contains("Buy")',
trigger: '.o_field_widget[name=route_ids] .custom-checkbox > label:contains("Buy")',
content: _t('Uncheck Buy'),
position: 'right',
}, {
trigger: '.o_field_widget[name=route_ids] .o_checkbox + label:contains("Make To Order")',
trigger: '.o_field_widget[name=route_ids] .custom-checkbox > label:contains("Make To Order")',
content: _t('Uncheck Make To Order'),
position: 'right',
}, {
@@ -109,7 +109,7 @@ tour.register('main_flow_tour', {
content: _t('Go to inventory tab'),
position: 'top',
}, {
trigger: '.o_field_widget[name=route_ids] .o_checkbox + label:contains("Make To Order")',
trigger: '.o_field_widget[name=route_ids] .custom-checkbox > label:contains("Make To Order")',
content: _t('Check Make To Order'),
position: 'right',
}, {