From ccea563abbbae48b7b914f5b12e59b02e167d486 Mon Sep 17 00:00:00 2001
From: jvm-odoo <jvm@odoo.com>
Date: Thu, 9 Jul 2020 13:17:13 +0000
Subject: [PATCH] [FIX] web: fix zoomodoo attachToTarget/dashboard compatible

Issue

    - Install Employees & Dashboard
    - Add employees to kanban
    - Dashboard
    - Hover an employee picture

    There is only the picture visible
    on the page, the remaining space is white.

Cause

    I found several issues.

    1. The pictures are not shown on hover in employees
        But they are on dashboard.

    2. $attach = all `.content` and on dashboard there is
        2 `.content` so the flyout is append 2 times

    3. The move method is trigerred on hover too, it hides
        the flyout if we are not in it. But with attachToTarget
        we are not in it so it's hidden all time.

    4. If everything above is solved, the image is shown but
        not at the correct position because the flyout base
        position is not top 0, left 0

Solution

    1. Reduce the minimum required size to 128px
    2. use closest instead of parents
    3. Don't hide if we have the option attachToTarget
    4. Calculate the flyout offset and replace it correctly
       and set it to position fixed to handle scrolling

OPW-2291493

closes odoo/odoo#54333

X-original-commit: 2c6d692ee40c97d2ae63da64db7623702948407e
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
Signed-off-by: Jason Van Malder (jvm) <jvm@odoo.com>
---
 .../web/static/src/js/fields/basic_fields.js  |  4 +++-
 addons/web/static/src/js/libs/zoomodoo.js     | 23 +++++++++++++++----
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 0a58d9e48957..590b2a3b2414 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -1912,7 +1912,9 @@ var FieldBinaryImage = AbstractFieldBinary.extend({
                     attach: '.o_content',
                     attachToTarget: true,
                     onShow: function () {
-                        if(this.$zoom.height() < 256 && this.$zoom.width() < 256) {
+                        var zoomHeight = Math.ceil(this.$zoom.height());
+                        var zoomWidth = Math.ceil(this.$zoom.width());
+                        if( zoomHeight < 128 && zoomWidth < 128) {
                             this.hide();
                         }
                         core.bus.on('keydown', this, this.hide);
diff --git a/addons/web/static/src/js/libs/zoomodoo.js b/addons/web/static/src/js/libs/zoomodoo.js
index a372c1686dc5..07da384c298d 100644
--- a/addons/web/static/src/js/libs/zoomodoo.js
+++ b/addons/web/static/src/js/libs/zoomodoo.js
@@ -84,8 +84,8 @@ ZoomOdoo.prototype._init = function () {
         this.$flyout = $('<div class="zoomodoo-flyout" />');
 
         var $attach = this.$target;
-        if (this.opts.attach !== undefined && this.$target.parents(this.opts.attach).length) {
-            $attach = this.$target.parents(this.opts.attach);
+        if (this.opts.attach !== undefined && this.$target.closest(this.opts.attach).length) {
+            $attach = this.$target.closest(this.opts.attach);
         }
         $attach.parent().on('mousemove.zoomodoo touchmove.zoomodoo', $.proxy(this._onMove, this));
         $attach.parent().on('mouseleave.zoomodoo touchend.zoomodoo', $.proxy(this._onLeave, this));
@@ -120,8 +120,8 @@ ZoomOdoo.prototype.show = function (e, testMouseOver) {
     }
 
     var $attach = this.$target;
-    if (this.opts.attach !== undefined && this.$target.parents(this.opts.attach).length) {
-        $attach = this.$target.parents(this.opts.attach);
+    if (this.opts.attach !== undefined && this.$target.closest(this.opts.attach).length) {
+        $attach = this.$target.closest(this.opts.attach);
     }
 
     // Prevents having multiple zoom flyouts
@@ -132,6 +132,19 @@ ZoomOdoo.prototype.show = function (e, testMouseOver) {
     if (this.opts.attachToTarget) {
         this.opts.beforeAttach.call(this);
 
+        // Be sure that the flyout is at top 0, left 0 to ensure correct computation
+        // e.g. employees kanban on dashboard
+        this.$flyout.css('position', 'fixed');
+        var flyoutOffset = this.$flyout.offset();
+        if (flyoutOffset.left > 0) {
+            var flyoutLeft = parseFloat(this.$flyout.css('left').replace('px',''));
+            this.$flyout.css('left', flyoutLeft - flyoutOffset.left + 'px');
+        }
+        if (flyoutOffset.top > 0) {
+            var flyoutTop = parseFloat(this.$flyout.css('top').replace('px',''));
+            this.$flyout.css('top', flyoutTop - flyoutOffset.top + 'px');
+        }
+
         if(this.$zoom.height() < this.$flyout.height()) {
              this.$flyout.css('height', this.$zoom.height() + 'px');
         }
@@ -296,7 +309,7 @@ ZoomOdoo.prototype._move = function (e) {
     var xl = Math.ceil(pl * rw);
 
     // Close if outside
-    if (xl < 0 || xt < 0 || xl > dw || xt > dh || lx > (offset.left + this.$target.outerWidth())) {
+    if (!this.opts.attachToTarget && (xl < 0 || xt < 0 || xl > dw || xt > dh || lx > (offset.left + this.$target.outerWidth()))) {
         this.hide();
     } else {
         var top = xt * -1;
-- 
GitLab