[ADD]:Added Upstream patch for barcodes
This commit is contained in:
parent
f26524e7dd
commit
1617df3efc
@ -53,7 +53,7 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
|
||||
navigator.userAgent.match(/iPod/i) ||
|
||||
navigator.userAgent.match(/BlackBerry/i) ||
|
||||
navigator.userAgent.match(/Windows Phone/i);
|
||||
this.isChromeMobile = isMobile && window.chrome;
|
||||
this.isChromeMobile = isMobile && navigator.userAgent.match(/Chrome/i);
|
||||
|
||||
// Creates an input who will receive the barcode scanner value.
|
||||
if (this.isChromeMobile) {
|
||||
@ -61,13 +61,17 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
|
||||
name: 'barcode',
|
||||
type: 'text',
|
||||
css: {
|
||||
'position': 'absolute',
|
||||
'opacity': 0,
|
||||
'position': 'fixed',
|
||||
'top': '50%',
|
||||
'transform': 'translateY(-50%)',
|
||||
'z-index': '-1',
|
||||
},
|
||||
});
|
||||
// Avoid to show autocomplete for a non appearing input
|
||||
this.$barcodeInput.attr('autocomplete', 'off');
|
||||
}
|
||||
|
||||
this.__removeBarcodeField = _.debounce(this._removeBarcodeField, this.inputTimeOut);
|
||||
this.__blurBarcodeInput = _.debounce(this._blurBarcodeInput, this.inputTimeOut);
|
||||
},
|
||||
|
||||
handle_buffered_keys: function() {
|
||||
@ -230,7 +234,7 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
|
||||
this.max_time_between_keys_in_ms);
|
||||
}
|
||||
// if the barcode input doesn't receive keydown for a while, remove it.
|
||||
this.__removeBarcodeField();
|
||||
this.__blurBarcodeInput();
|
||||
}
|
||||
},
|
||||
|
||||
@ -245,21 +249,22 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
|
||||
var barcodeValue = this.$barcodeInput.val();
|
||||
if (barcodeValue.match(this.regexp)) {
|
||||
core.bus.trigger('barcode_scanned', barcodeValue, $(e.target).parent()[0]);
|
||||
this.$barcodeInput.val('');
|
||||
this._blurBarcodeInput();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the temporary input created to store the barcode value.
|
||||
* If nothing happens, this input will be removed, so the focus will be lost
|
||||
* and the virtual keyboard on mobile devices will be closed.
|
||||
* Removes the value and focus from the barcode input.
|
||||
* If nothing happens, the focus will be lost and
|
||||
* the virtual keyboard on mobile devices will be closed.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_removeBarcodeField: function () {
|
||||
_blurBarcodeInput: function () {
|
||||
if (this.$barcodeInput) {
|
||||
// Reset the value and remove from the DOM.
|
||||
this.$barcodeInput.val('').remove();
|
||||
// Close the virtual keyboard on mobile browsers
|
||||
// FIXME: actually we can't prevent keyboard from opening
|
||||
this.$barcodeInput.val('').blur();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -146,10 +146,10 @@ FormController.include({
|
||||
* @param {Object} activeBarcode: options sent by the field who use barcode features
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
_barcodeSelectedCandidate: function (candidate, record, barcode, activeBarcode) {
|
||||
_barcodeSelectedCandidate: function (candidate, record, barcode, activeBarcode, quantity) {
|
||||
var changes = {};
|
||||
var candidateChanges = {};
|
||||
candidateChanges[activeBarcode.quantity] = candidate.data[activeBarcode.quantity] + 1;
|
||||
candidateChanges[activeBarcode.quantity] = quantity ? quantity : candidate.data[activeBarcode.quantity] + 1;
|
||||
changes[activeBarcode.fieldName] = {
|
||||
operation: 'UPDATE',
|
||||
id: candidate.id,
|
||||
@ -283,6 +283,9 @@ FormController.include({
|
||||
function (reserved) {return barcode.indexOf(reserved) === 0;});
|
||||
var hasCommand = false;
|
||||
var defs = [];
|
||||
if (! $.contains(target, self.el)) {
|
||||
return;
|
||||
}
|
||||
for (var k in self.activeBarcode) {
|
||||
var activeBarcode = self.activeBarcode[k];
|
||||
// Handle the case where there are several barcode widgets on the same page. Since the
|
||||
@ -306,6 +309,8 @@ FormController.include({
|
||||
}
|
||||
return self.alive($.when.apply($, defs)).then(function () {
|
||||
if (!prefixed) {
|
||||
// remember the barcode scanned for the quantity listener
|
||||
self.current_barcode = barcode;
|
||||
// redraw the view if we scanned a real barcode (required if
|
||||
// we manually apply the change in JS, e.g. incrementing the
|
||||
// quantity)
|
||||
@ -321,6 +326,9 @@ FormController.include({
|
||||
_quantityListener: function (event) {
|
||||
var character = String.fromCharCode(event.which);
|
||||
|
||||
if (! $.contains(event.target, this.el)) {
|
||||
return;
|
||||
}
|
||||
// only catch the event if we're not focused in
|
||||
// another field and it's a number
|
||||
if (!$(event.target).is('body, .modal') || !/[0-9]/.test(character)) {
|
||||
@ -355,9 +363,10 @@ FormController.include({
|
||||
title: _t('Set quantity'),
|
||||
buttons: [{text: _t('Select'), classes: 'btn-primary', close: true, click: function () {
|
||||
var new_qty = this.$content.find('.o_set_qty_input').val();
|
||||
var values = {};
|
||||
values[activeBarcode.quantity] = parseFloat(new_qty);
|
||||
return self.model.notifyChanges(activeBarcode.candidate.id, values).then(function () {
|
||||
var record = self.model.get(self.handle);
|
||||
return self._barcodeSelectedCandidate(activeBarcode.candidate, record,
|
||||
self.current_barcode, activeBarcode, parseFloat(new_qty))
|
||||
.then(function () {
|
||||
self.update({}, {reload: false});
|
||||
});
|
||||
}}, {text: _t('Discard'), close: true}],
|
||||
|
@ -18,6 +18,9 @@ var BarcodeParser = Class.extend({
|
||||
// only when those data have been loaded
|
||||
load: function(){
|
||||
var self = this;
|
||||
if (!this.nomenclature_id) {
|
||||
return;
|
||||
}
|
||||
var id = this.nomenclature_id[0];
|
||||
rpc.query({
|
||||
model: 'barcode.nomenclature',
|
||||
|
@ -404,4 +404,136 @@ QUnit.test('specification of widget barcode_handler', function (assert) {
|
||||
barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = delay;
|
||||
delete fieldRegistry.map.test_barcode_handler;
|
||||
});
|
||||
|
||||
QUnit.test('specification of widget barcode_handler with keypress and notifyChange', function (assert) {
|
||||
assert.expect(6);
|
||||
var done = assert.async();
|
||||
|
||||
var delay = barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms;
|
||||
barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = 0;
|
||||
|
||||
this.data.order.onchanges = {
|
||||
_barcode_scanned: function () {},
|
||||
};
|
||||
|
||||
// Define a specific barcode_handler widget for this test case
|
||||
var TestBarcodeHandler = AbstractField.extend({
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
this.trigger_up('activeBarcode', {
|
||||
name: 'test',
|
||||
fieldName: 'line_ids',
|
||||
notifyChange: false,
|
||||
setQuantityWithKeypress: true,
|
||||
quantity: 'quantity',
|
||||
commands: {
|
||||
barcode: '_barcodeAddX2MQuantity',
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
fieldRegistry.add('test_barcode_handler', TestBarcodeHandler);
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'order',
|
||||
data: this.data,
|
||||
arch: '<form>' +
|
||||
'<field name="_barcode_scanned" widget="test_barcode_handler"/>' +
|
||||
'<field name="line_ids">' +
|
||||
'<tree>' +
|
||||
'<field name="product_id"/>' +
|
||||
'<field name="product_barcode" invisible="1"/>' +
|
||||
'<field name="quantity"/>' +
|
||||
'</tree>' +
|
||||
'</field>' +
|
||||
'</form>',
|
||||
mockRPC: function (route, args) {
|
||||
assert.step(args.method);
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
res_id: 1,
|
||||
viewOptions: {
|
||||
mode: 'edit',
|
||||
},
|
||||
});
|
||||
_.each(['1','2','3','4','5','6','7','8','9','0','Enter'], triggerKeypressEvent);
|
||||
// Quantity listener should open a dialog.
|
||||
triggerKeypressEvent('5');
|
||||
|
||||
setTimeout(function () {
|
||||
var keycode = $.ui.keyCode.ENTER;
|
||||
|
||||
assert.strictEqual($('.modal .modal-body').length, 1, 'should open a modal with a quantity as input');
|
||||
assert.strictEqual($('.modal .modal-body .o_set_qty_input').val(), '5', 'the quantity by default in the modal shoud be 5');
|
||||
|
||||
$('.modal .modal-body .o_set_qty_input').val('7');
|
||||
|
||||
$('.modal .modal-body .o_set_qty_input').trigger($.Event('keypress', {which: keycode, keyCode: keycode}));
|
||||
assert.strictEqual(form.$('.o_data_row .o_data_cell:nth(1)').text(), '7',
|
||||
"quantity checked should be 7");
|
||||
|
||||
assert.verifySteps(['read', 'read']);
|
||||
|
||||
form.destroy();
|
||||
barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = delay;
|
||||
delete fieldRegistry.map.test_barcode_handler;
|
||||
done();
|
||||
});
|
||||
});
|
||||
QUnit.test('barcode_scanned only trigger error for active view', function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
this.data.order_line.fields._barcode_scanned = {string: 'Barcode scanned', type: 'char'};
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'order',
|
||||
data: this.data,
|
||||
arch: '<form>' +
|
||||
'<field name="_barcode_scanned" widget="barcode_handler"/>' +
|
||||
'<field name="line_ids">' +
|
||||
'<tree>' +
|
||||
'<field name="product_id"/>' +
|
||||
'<field name="product_barcode" invisible="1"/>' +
|
||||
'<field name="quantity"/>' +
|
||||
'</tree>' +
|
||||
'</field>' +
|
||||
'</form>',
|
||||
archs: {
|
||||
"order_line,false,form":
|
||||
'<form string="order line">' +
|
||||
'<field name="_barcode_scanned" widget="barcode_handler"/>' +
|
||||
'<field name="product_id"/>' +
|
||||
'</form>',
|
||||
},
|
||||
res_id: 1,
|
||||
intercepts: {
|
||||
warning: function (event) {
|
||||
assert.step(event.name);
|
||||
}
|
||||
},
|
||||
viewOptions: {
|
||||
mode: 'edit',
|
||||
},
|
||||
});
|
||||
|
||||
form.$('.o_data_row:first').click();
|
||||
|
||||
// We do not trigger on the body since modal and
|
||||
// form view are both inside it.
|
||||
function modalTriggerKeypressEvent(char) {
|
||||
var keycode;
|
||||
if (char === "Enter") {
|
||||
keycode = $.ui.keyCode.ENTER;
|
||||
} else {
|
||||
keycode = char.charCodeAt(0);
|
||||
}
|
||||
return $('.modal').trigger($.Event('keypress', {which: keycode, keyCode: keycode}));
|
||||
}
|
||||
_.each(['O','-','B','T','N','.','c','a','n','c','e','l','Enter'], modalTriggerKeypressEvent);
|
||||
assert.verifySteps(['warning'], "only one event should be triggered");
|
||||
form.destroy();
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user