diff --git a/stock_location_tray/static/src/js/stock_location_tray.js b/stock_location_tray/static/src/js/stock_location_tray.js
index 6921184a71d4..e05ed3cc027a 100644
--- a/stock_location_tray/static/src/js/stock_location_tray.js
+++ b/stock_location_tray/static/src/js/stock_location_tray.js
@@ -1,249 +1,270 @@
odoo.define('stock_location_tray.tray', function (require) {
-"use strict";
-
-var core = require('web.core');
-var KanbanRecord = require('web.KanbanRecord');
-var basicFields = require('web.basic_fields');
-var field_registry = require('web.field_registry');
-var DebouncedField = basicFields.DebouncedField;
-
-/**
-* Shows a canvas with the Tray's cells
-*
-* An action can be configured which is called when a cell is clicked.
-* The action must be an action.multi, it will receive the x and y positions
-* of the cell clicked (starting from 0). The action must be configured in
-* the options of the field and be on the same model:
-*
-*
-*
-*/
-var LocationTrayMatrixField = DebouncedField.extend({
- className: 'o_field_location_tray_matrix',
- tagName: 'canvas',
- supportedFieldTypes: ['serialized'],
- events: {
- 'click': '_onClick',
- },
-
- cellColorEmpty: '#ffffff',
- cellColorNotEmpty: '#4e6bfd',
- selectedColor: '#08f46b',
- selectedLineWidth: 5,
- globalAlpha: 0.8,
- cellPadding: 2,
-
- init: function (parent, name, record, options) {
- this._super.apply(this, arguments);
- this.nodeOptions = _.defaults(this.nodeOptions, {});
- this.clickAction = 'clickAction' in (options || {}) ? options.clickAction : this.nodeOptions.click_action;
- },
-
- isSet: function () {
- if (Object.keys(this.value).length === 0) {
- return false;
- }
- if (this.value.cells.length === 0) {
- return false;
- }
- return this._super.apply(this, arguments);
- },
-
- start: function () {
- // Setup resize events to redraw the canvas
- this._resizeDebounce = this._resizeDebounce.bind(this);
- this._resizePromise = null;
- $(window).on('resize', this._resizeDebounce);
-
- var self = this;
- return this._super.apply(this, arguments).then(function () {
- if (self.clickAction) {
- self.$el.css('cursor', 'pointer');
- }
- // _super calls _render(), but the function
- // resizeCanvasToDisplaySize would resize the canvas
- // to 0 because the actual canvas would still be unknown.
- // Call again _render() here but through a setTimeout to
- // let the js renderer thread catch up.
- self._ready = true;
- return self._resizeDebounce();
- });
- },
-
- _onClick: function (ev) {
- if (!this.isSet()) {
- return;
- }
- if (!this.clickAction) {
- return;
- }
- var width = this.canvas.width,
- height = this.canvas.height,
- rect = this.canvas.getBoundingClientRect();
-
- var clickX = ev.clientX - rect.left,
- clickY = ev.clientY - rect.top;
-
- var cells = this.value.cells,
- cols = cells[0].length,
- rows = cells.length;
-
- // we remove 1 to start counting from 0
- var coordX = Math.ceil(clickX * cols / width) - 1,
- coordY = Math.ceil(clickY * rows / height) - 1;
- // if we click on the last pixel on the bottom or the right
- // we would get an offset index
- if (coordX >= cols) { coordX = cols - 1; }
- if (coordY >= rows) { coordY = rows - 1; }
-
- // the coordinate we get when we click is from top,
- // but we are looking for the coordinate from the bottom
- // to match the user's expectations, invert Y
- coordY = Math.abs(coordY - rows + 1);
-
- var self = this;
- this._rpc({
- model: this.model,
- method: this.clickAction,
- args: [[this.res_id], coordX, coordY]
- })
- .then(function (action) {
- self.trigger_up('do_action', {action: action});
- });
- },
+ "use strict";
- /**
- * Debounce the rendering on resize.
- * It is useless to render on each resize event.
- *
- */
- _resizeDebounce: function(){
- clearTimeout(this._resizePromise);
- var self = this;
- this._resizePromise = setTimeout(function(){
- self._render();
- }, 20);
- },
-
- destroy: function () {
- $(window).off('resize', this._resizeDebounce);
- this._super.apply(this, arguments);
- },
+ var basicFields = require('web.basic_fields');
+ var field_registry = require('web.field_registry');
+ var DebouncedField = basicFields.DebouncedField;
/**
- * Render the widget only when it is in the DOM.
- * We need the width and height of the widget to draw the canvas.
- *
- */
- _render: function () {
- if (this._ready) {
- return this._renderInDOM();
- }
- return $.when();
- },
+ * Shows a canvas with the Tray's cells
+ *
+ * An action can be configured which is called when a cell is clicked.
+ * The action must be an action.multi, it will receive the x and y positions
+ * of the cell clicked (starting from 0). The action must be configured in
+ * the options of the field and be on the same model:
+ *
+ *
+ *
+ */
+ var LocationTrayMatrixField = DebouncedField.extend({
+ className: 'o_field_location_tray_matrix',
+ tagName: 'canvas',
+ supportedFieldTypes: ['serialized'],
+ events: {
+ 'click': '_onClick',
+ },
- /**
- * Resize the canvas width and height to the actual size.
- * If we don't do that, it will automatically scale to the
- * CSS size with blurry squares.
- *
- */
- resizeCanvasToDisplaySize: function(canvas) {
- // look up the size the canvas is being displayed
- var width = canvas.clientWidth;
- var height = canvas.clientHeight;
-
- // If it's resolution does not match change it
- if (canvas.width !== width || canvas.height !== height) {
- canvas.width = width;
- canvas.height = height;
- return true;
- }
-
- return false;
- },
+ cellColorEmpty: '#ffffff',
+ cellColorNotEmpty: '#4e6bfd',
+ selectedColor: '#08f46b',
+ selectedLineWidth: 5,
+ globalAlpha: 0.8,
+ cellPadding: 2,
- /**
- * Resize the canvas, clear it and redraw the cells
- * Should be called only if the canvas is already in DOM
- *
- */
- _renderInDOM: function () {
- this.canvas = this.$el[0];
- var canvas = this.canvas;
- var ctx = canvas.getContext('2d');
- this.resizeCanvasToDisplaySize(ctx.canvas);
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.save();
- if (this.isSet()) {
- var selected = this.value.selected || [];
- var cells = this.value.cells;
- this._drawMatrix(canvas, ctx, cells, selected);
- }
- },
+ init: function (parent, name, record, options) {
+ this._super.apply(this, arguments);
+ this.nodeOptions = _.defaults(this.nodeOptions, {});
+ if ('clickAction' in (options || {})) {
+ this.clickAction = options.clickAction;
+ } else {
+ this.clickAction = this.nodeOptions.click_action;
+ }
+ },
- /**
- * Draw the cells in the canvas.
- *
- */
- _drawMatrix: function (canvas, ctx, cells, selected) {
- var colors = {
- 0: this.cellColorEmpty,
- 1: this.cellColorNotEmpty,
- };
-
- var cols = cells[0].length;
- var rows = cells.length;
- var selectedX, selectedY;
- if (selected.length) {
- selectedX = selected[0];
- // we draw top to bottom, but the highlighted cell should
- // be a coordinate from bottom to top: reverse the y axis
- selectedY = Math.abs(selected[1] - rows + 1);
- }
-
- var padding = this.cellPadding;
- var w = ((canvas.width - padding * cols) / cols);
- var h = ((canvas.height - padding * rows) / rows);
-
- ctx.globalAlpha = this.globalAlpha;
- // again, our matrix is top to bottom (0 is the first line)
- // but visually, we want them bottom to top
- var reversed_cells = cells.slice().reverse();
- for (var y = 0; y < rows; y++) {
- for (var x = 0; x < cols; x++) {
- ctx.fillStyle = colors[reversed_cells[y][x]];
- var fillWidth = w;
- var fillHeight = h;
- // cheat: remove the padding at bottom and right
- // the cells will be a bit larger but not really noticeable
- if (x === cols - 1) {fillWidth += padding;}
- if (y === rows - 1) {fillHeight += padding;}
- ctx.fillRect(
- x * (w + padding), y * (h + padding),
- fillWidth, fillHeight
- );
- if (selected && selectedX === x && selectedY === y) {
- ctx.globalAlpha = 1.0;
- ctx.strokeStyle = this.selectedColor;
- ctx.lineWidth = this.selectedLineWidth;
- ctx.strokeRect(x * (w + padding), y * (h + padding), w, h);
- ctx.globalAlpha = this.globalAlpha;
+ isSet: function () {
+ if (Object.keys(this.value).length === 0) {
+ return false;
+ }
+ if (this.value.cells.length === 0) {
+ return false;
+ }
+ return this._super.apply(this, arguments);
+ },
+
+ start: function () {
+ // Setup resize events to redraw the canvas
+ this._resizeDebounce = this._resizeDebounce.bind(this);
+ this._resizePromise = null;
+ $(window).on('resize', this._resizeDebounce);
+
+ var self = this;
+ return this._super.apply(this, arguments).then(function () {
+ if (self.clickAction) {
+ self.$el.css('cursor', 'pointer');
}
+ // _super calls _render(), but the function
+ // resizeCanvasToDisplaySize would resize the canvas
+ // to 0 because the actual canvas would still be unknown.
+ // Call again _render() here but through a setTimeout to
+ // let the js renderer thread catch up.
+ self._ready = true;
+ return self._resizeDebounce();
+ });
+ },
+
+ _onClick: function (ev) {
+ if (!this.isSet()) {
+ return;
}
- }
- ctx.restore();
- }
-});
+ if (!this.clickAction) {
+ return;
+ }
+ var width = this.canvas.width,
+ height = this.canvas.height,
+ rect = this.canvas.getBoundingClientRect();
+
+ var clickX = ev.clientX - rect.left,
+ clickY = ev.clientY - rect.top;
+
+ var cells = this.value.cells,
+ cols = cells[0].length,
+ rows = cells.length;
+
+ // We remove 1 to start counting from 0
+ var coordX = Math.ceil(clickX * cols / width) - 1,
+ coordY = Math.ceil(clickY * rows / height) - 1;
+ // If we click on the last pixel on the bottom or the right
+ // we would get an offset index
+ if (coordX >= cols) {
+ coordX = cols - 1;
+ }
+ if (coordY >= rows) {
+ coordY = rows - 1;
+ }
+
+ // The coordinate we get when we click is from top,
+ // but we are looking for the coordinate from the bottom
+ // to match the user's expectations, invert Y
+ coordY = Math.abs(coordY - rows + 1);
+
+ var self = this;
+ this._rpc({
+ model: this.model,
+ method: this.clickAction,
+ args: [[this.res_id], coordX, coordY],
+ })
+ .then(function (action) {
+ self.trigger_up('do_action', {action: action});
+ });
+ },
+
+ /**
+ * Debounce the rendering on resize.
+ * It is useless to render on each resize event.
+ *
+ */
+ _resizeDebounce: function () {
+ clearTimeout(this._resizePromise);
+ var self = this;
+ this._resizePromise = setTimeout(function () {
+ self._render();
+ }, 20);
+ },
+
+ destroy: function () {
+ $(window).off('resize', this._resizeDebounce);
+ this._super.apply(this, arguments);
+ },
+
+ /**
+ * Render the widget only when it is in the DOM.
+ * We need the width and height of the widget to draw the canvas.
+ *
+ * @returns {Promise}
+ */
+ _render: function () {
+ if (this._ready) {
+ return this._renderInDOM();
+ }
+ return $.when();
+ },
+
+ /**
+ * Resize the canvas width and height to the actual size.
+ * If we don't do that, it will automatically scale to the
+ * CSS size with blurry squares.
+ *
+ * @param {jQueryElement} canvas - the DOM canvas to draw
+ * @returns {Boolean}
+ */
+ resizeCanvasToDisplaySize: function (canvas) {
+ // Look up the size the canvas is being displayed
+ var width = canvas.clientWidth;
+ var height = canvas.clientHeight;
+
+ // If it's resolution does not match change it
+ if (canvas.width !== width || canvas.height !== height) {
+ canvas.width = width;
+ canvas.height = height;
+ return true;
+ }
+
+ return false;
+ },
+
+ /**
+ * Resize the canvas, clear it and redraw the cells
+ * Should be called only if the canvas is already in DOM
+ *
+ */
+ _renderInDOM: function () {
+ this.canvas = this.$el[0];
+ var canvas = this.canvas;
+ var ctx = canvas.getContext('2d');
+ this.resizeCanvasToDisplaySize(ctx.canvas);
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.save();
+ if (this.isSet()) {
+ var selected = this.value.selected || [];
+ var cells = this.value.cells;
+ this._drawMatrix(canvas, ctx, cells, selected);
+ }
+ },
+
+ /**
+ * Draw the cells in the canvas.
+ *
+ * @param {jQueryElement} canvas - the DOM canvas to draw
+ * @param {Object} ctx - the canvas 2d context
+ * @param {List} cells - A 2-dimensional list of cells
+ * @param {List} selected - A list containing the position (x,y) of the
+ * selected cell (can be empty if no cell is selected)
+ */
+ _drawMatrix: function (canvas, ctx, cells, selected) {
+ var colors = {
+ 0: this.cellColorEmpty,
+ 1: this.cellColorNotEmpty,
+ };
+
+ var cols = cells[0].length;
+ var rows = cells.length;
+ var selectedX = null,
+ selectedY = null;
+ if (selected.length) {
+ selectedX = selected[0];
+ // We draw top to bottom, but the highlighted cell should
+ // be a coordinate from bottom to top: reverse the y axis
+ selectedY = Math.abs(selected[1] - rows + 1);
+ }
+
+ var padding = this.cellPadding;
+ var padding_width = padding * cols;
+ var padding_height = padding * rows;
+ var w = (canvas.width - padding_width) / cols;
+ var h = (canvas.height - padding_height) / rows;
+
+ ctx.globalAlpha = this.globalAlpha;
+ // Again, our matrix is top to bottom (0 is the first line)
+ // but visually, we want them bottom to top
+ var reversed_cells = cells.slice().reverse();
+ for (var y = 0; y < rows; y++) {
+ for (var x = 0; x < cols; x++) {
+ ctx.fillStyle = colors[reversed_cells[y][x]];
+ var fillWidth = w;
+ var fillHeight = h;
+ // Cheat: remove the padding at bottom and right
+ // the cells will be a bit larger but not really noticeable
+ if (x === cols - 1) {
+ fillWidth += padding;
+ }
+ if (y === rows - 1) {
+ fillHeight += padding;
+ }
+ ctx.fillRect(
+ x * (w + padding), y * (h + padding),
+ fillWidth, fillHeight,
+ );
+ if (selected && selectedX === x && selectedY === y) {
+ ctx.globalAlpha = 1.0;
+ ctx.strokeStyle = this.selectedColor;
+ ctx.lineWidth = this.selectedLineWidth;
+ ctx.strokeRect(x * (w + padding), y * (h + padding), w, h);
+ ctx.globalAlpha = this.globalAlpha;
+ }
+ }
+ }
+ ctx.restore();
+ },
+ });
-field_registry.add('location_tray_matrix', LocationTrayMatrixField);
+ field_registry.add('location_tray_matrix', LocationTrayMatrixField);
-return {
- LocationTrayMatrixField: LocationTrayMatrixField
-};
+ return {
+ LocationTrayMatrixField: LocationTrayMatrixField,
+ };
});