Просмотр исходного кода

Pointer popups: place them unscaled and keep them 8px inside the window (#5840)

dolPopupAjax positions a popup a second time once its content has loaded.
On a fast server that happens before the show animation starts, while
.bx-popup-inactive still scales the popup to 0.75. jQuery UI's .position()
moves the element through .offset(), which measures the transformed box,
so the popup landed 1/8 of its width further left and 1/8 of its height
higher than intended: the reactions popup on the Timeline item page went
42px past the left edge of the window, and item menus covered their own
buttons.

_dolPopupSetPosition now lays the popup out without its transform while
placing it, keeps it at least 8px from the window's left and right edges
when it is narrower than the window, and uses the same placement on window
resize (that used 'flip none', which let a centred popup leave the window
again).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Andrey Yasko 1 неделя назад
Родитель
Сommit
72d0c2b22d
1 измененных файлов с 31 добавлено и 16 удалено
  1. 31 16
      inc/js/jquery.dolPopup.js

+ 31 - 16
inc/js/jquery.dolPopup.js

@@ -893,6 +893,7 @@
             if (o.pointer != false) {                
                 
                 var yOffset = 8;
+                var xMargin = 8; // min distance from the window's left and right edges
                 var ePointAt = typeof o.pointer.el == 'string' ? $(o.pointer.el) : o.pointer.el;
                 if (!ePointAt)
                     ePointAt = $('body');
@@ -904,27 +905,41 @@
                 if (undefined == aOffsetPointer[0] || undefined == aOffsetPointer[1])
                     aOffsetPointer = [0, 0];
 
-                $el.position({
-                    of: ePointAt,
-                    my: o.pointer.align + '+' + parseInt(aOffset[0]) + ' top+' + yOffset + '+' + parseInt(aOffset[1] - 0),
-                    at: o.pointer.align + ' bottom',
-                    collision: 'fit none'
-                });
-
-                $el.find('.bx-popup-box-pointer').css('display', 'block').position({
-                    of: ePointAt,
-                    my: 'center+' + (parseInt(aOffsetPointer[0]) + parseInt(aOffset[0])) + ' top+' + yOffset + '+' + (parseInt(aOffsetPointer[1]) + parseInt(aOffset[1]) + 0),
-                    at: 'center bottom'
-                });
+                var fPosition = function() {
+                    // .position() moves the popup through .offset(), which measures the transformed box,
+                    // so while the show animation scales the popup it would land up and to the left
+                    // of its place: lay it out unscaled until it is placed
+                    var oStyle = $el.get(0).style;
+                    var sTransition = oStyle.transition, sTransform = oStyle.transform;
+                    $el.css({transition: 'none', transform: 'none'});
 
-                $(window).on('resize.popupPointer', function() {
                     $el.position({
                         of: ePointAt,
-                        my: o.pointer.align + '+' + parseInt(aOffset[0]) + ' top+' + yOffset + '+' + parseInt(aOffset[1]),
+                        my: o.pointer.align + '+' + parseInt(aOffset[0]) + ' top+' + yOffset + '+' + parseInt(aOffset[1] - 0),
                         at: o.pointer.align + ' bottom',
-                        collision: 'flip none'
+                        collision: 'fit none'
                     });
-                });
+
+                    // 'fit' only keeps the popup inside the window, flush with its edge
+                    var iWindowLeft = $(window).scrollLeft();
+                    var iLeftMin = iWindowLeft + xMargin;
+                    var iLeftMax = iWindowLeft + $(window).width() - xMargin - $el.outerWidth();
+                    var iLeft = $el.offset().left;
+                    if (iLeftMin <= iLeftMax && (iLeft < iLeftMin || iLeft > iLeftMax))
+                        $el.offset({left: Math.min(Math.max(iLeft, iLeftMin), iLeftMax)});
+
+                    $el.find('.bx-popup-box-pointer').css('display', 'block').position({
+                        of: ePointAt,
+                        my: 'center+' + (parseInt(aOffsetPointer[0]) + parseInt(aOffset[0])) + ' top+' + yOffset + '+' + (parseInt(aOffsetPointer[1]) + parseInt(aOffset[1]) + 0),
+                        at: 'center bottom'
+                    });
+
+                    $el.css({transition: sTransition, transform: sTransform});
+                };
+
+                fPosition();
+
+                $(window).on('resize.popupPointer', fPosition);
 
             } else if (o.position == 'fixed' || o.position == 'absolute') {
                 var bCenterHor = o.left != undefined && o.left == 'center';