事件处理程序在动态内容上也无法正常工作,即使使用事件委托。

huangapple go评论61阅读模式
英文:

Event handler not working on dynamic content even with event delegation

问题

I have two ModalPopups
The first one opens and has a Tooltip text that the user can view for more detail with the "mouseenter" event listener.
Once the user clicks to close the modal through one of three buttons, the second ModalPopup opens with another Tooltip text. The Tooltip text on "mouseenter" does not work in this second ModalPopup.
This is an entirely new Modalpopup although I have tried using the same modal and it still doesn't work.

So the flow is:
User clicks button -> loading -> ModalPopup with tooltip -> User clicks 1 button out of 3 options -> Modalpopup closes -> loading -> ModalPopup number 2 with tooltip -> etc...

So it's loading dynamic content, then using delegation to set the tooltip listeners, then closing/deleting that content, then loading more dynamic content afterwards, and trying to again use delegated tooltip listeners for the second time.

I've tried removing the tooltip altogether on each modal load, unbinding everything on modal load before rebinding, unbinding in the tooltip code before rebinding, and etc.

Interestingly, when the second modalpopup opens, if I "Inspect Element" using chrome, the tooltips start working again.

Tootip Code:

(function ($) {
    'use strict';
    $.fn.extend({
        jqToolTip: function () {
            var opts = {
                tooltipDiv: 'tooltipbox',
                tooltipFadeOut: 'tooltipFadeOut',
                tooltipBoxTop: 'tooltipbox-top',
                tooltipBoxRight: 'tooltipbox-right',
                tooltipBoxLeft: 'tooltipbox-left',
                tooltipBoxBottom: 'tooltipbox-bottom',
                tooltipBoxRed: 'tooltipbox-red',
                tooltipBoxBottomRed: 'tooltipbox-bottom-red',
                tooltipBoxTopRed: 'tooltipbox-top-red',
                tooltipBoxLeftRed: 'tooltipbox-left-red',
                tooltipBoxRightRed: 'tooltipbox-right-red'
            };
            const classSelector = $(this).attr("class").split(/\s+/).find(x => x.includes("tooltip"));

            $(document.body).on('mouseenter', `.${classSelector}`, function (e) {
                var color = $(this).data("tooltip-color");
                var arrowOffsetx = $(this).data("tooltip-arrow-offset-x");
                var arrowOffsety = $(this).data("tooltip-arrow-offset-y");
                var helptext = $(this).data("tooltip");
                var direction = $(this).data("tooltip-direction");
                if (direction == null) direction = 'right';
                var top = $(this).offset().top;
                var left = $(this).offset().left;
                var offsetX = $(this).data("tooltip-offset-x");
                if (offsetX == null) offsetX = 0;
                var offsetY = $(this).data("tooltip-offset-y");
                if (offsetY == null) offsetY = 0;
                //console.log(top,left,$(this).width());
                var cssAdd = '';
                var cssColorAdd = '';
                $('..' + opts.tooltipDiv).removeClass(opts.tooltipFadeOut + ' '
                    + opts.tooltipBoxBottom + ' '
                    + opts.tooltipBoxRight + ' '
                    + opts.tooltipBoxTop + ' '
                    + opts.tooltipBoxLeft + ' '
                    + opts.tooltipBoxRed + ' '
                    + opts.tooltipBoxBottomRed + ' '
                    + opts.tooltipBoxTopRed + ' '
                    + opts.tooltipBoxLeftRed + ' '
                    + opts.tooltipBoxRightRed).html(helptext);
                switch (direction) {
                    case 'top': // top
                        top = top - 48 + offsetY;
                        left = left + $(this).width() / 2 - 25 + offsetX;
                        cssAdd = opts.tooltipBoxTop;
                        cssColorAdd = opts.tooltipBoxTopRed;
                        break;
                    case 'right': // right
                        top = top + $(this).height() / 2 - 13 + offsetY;
                        left = left + $(this).width() + 20 + offsetX;
                        cssAdd = opts.tooltipBoxRight;
                        cssColorAdd = opts.tooltipBoxRightRed;
                        break;
                    case 'bottom': // bottom
                        top = top + $(this). height() + 14 + offsetY;
                        left = left + $(this).width() / 2 - 28 + offsetX;
                        cssAdd = opts.tooltipBoxBottom;
                        cssColorAdd = opts.tooltipBoxBottomRed;
                        break;
                    case 'left': // left
                        top = top + $(this).height() / 2 - 13 + offsetY;
                        left = left - $('.' + opts.tooltipDiv).width() - 16 + offsetX;
                        cssAdd = opts.tooltipBoxLeft;
                        cssColorAdd = opts.tooltipBoxLeftRed;
                        break;
                }
                //console.log(left);
                if (color == 'red') {
                    $('.' + opts.tooltipDiv).addClass(opts.tooltipBoxRed);
                    $('.' + opts.tooltipDiv).addClass(cssColorAdd);
                }
                if (typeof(arrowOffsetx) != "undefined" && arrowOffsetx.length > 0) {
                    $('.' + opts.tooltipDiv)
                        .addClass('tooltipBoxArrowOffsetX')
                        .append('<style>.tooltipBoxArrowOffsetX::after,.tooltipBoxArrowOffsetX::before{left:' + arrowOffsetx + ' !important;}</style>')
                }
                if (typeof (arrowOffsety) != "undefined" && arrowOffsety.length > 0) {
                    $('.' + opts.tooltipDiv)
                        .addClass('tooltipBoxArrowOffsetY')
                        .append('<style>.tooltipBoxArrowOffsetY::after,.tooltipBoxArrowOffsetY::before{left:' + arrowOffsety + ' !important;}</style>');
                }
                $('.' + opts.tooltipDiv).addClass(cssAdd).css({ left: left, top: top }).fadeIn();
            })
            $(document.body).on('mouseleave', `.${classSelector}`, function (e) {
                $('.' + opts.tooltipDiv).addClass(opts.tooltipFadeOut);
            })
            $(document.body).on('click', `.${classSelector}`, function (e) {
                var ishide = $(this).data("tooltip-onclickhide") == '1';
                if (ishide) $('.' + opts.tooltipDiv).addClass(opts.tooltipFadeOut);
            })

            return this;
        },
    })
})(jQuery);
英文:

I have two ModalPopups
The first one opens and has a Tooltip text that the user can view for more detail with the "mouseenter" event listener.
Once the user clicks to close the modal through one of three buttons, the second ModalPopup opens with another Tooltip text. The Tooltip text on "mouseenter" does not work in this second ModalPopup.
This is an entirely new Modalpopup although I have tried using the same modal and it still doesn't work.

So the flow is:
User clicks button -> loading -> ModalPopup with tooltip -> User clicks 1 button out of 3 options -> Modalpopup closes -> loading -> ModalPopup number 2 with tooltip -> etc...

So it's loading dynamic content, then using delegation to set the tooltip listeners, then closing/deleting that content, then loading more dynamic content afterwards, and trying to again use delegated tooltip listeners for the second time.

I've tried removing the tooltip altogether on each modal load, unbinding everything on modal load before rebinding, unbinding in the tooltip code before rebinding, and etc.

Interestingly, when the second modalpopup opens, if I "Inspect Element" using chrome, the tooltips start working again.

Tootip Code:

(function ($) {
&#39;use strict&#39;;
$.fn.extend({
jqToolTip: function () {
var opts = {
tooltipDiv: &#39;tooltipbox&#39;,
tooltipFadeOut: &#39;tooltipFadeOut&#39;,
tooltipBoxTop: &#39;tooltipbox-top&#39;,
tooltipBoxRight: &#39;tooltipbox-right&#39;,
tooltipBoxLeft: &#39;tooltipbox-left&#39;,
tooltipBoxBottom: &#39;tooltipbox-bottom&#39;,
tooltipBoxRed: &#39;tooltipbox-red&#39;,
tooltipBoxBottomRed: &#39;tooltipbox-bottom-red&#39;,
tooltipBoxTopRed: &#39;tooltipbox-top-red&#39;,
tooltipBoxLeftRed: &#39;tooltipbox-left-red&#39;,
tooltipBoxRightRed: &#39;tooltipbox-right-red&#39;
};
const classSelector = $(this).attr(&quot;class&quot;).split(/\s+/).find(x =&gt; x.includes(&quot;tooltip&quot;));
$(document.body).live(&#39;mouseenter&#39;, `.${classSelector}`, function (e) {
var color = $(this).data(&quot;tooltip-color&quot;);
var arrowOffsetx = $(this).data(&quot;tooltip-arrow-offset-x&quot;);
var arrowOffsety = $(this).data(&quot;tooltip-arrow-offset-y&quot;);
var helptext = $(this).data(&quot;tooltip&quot;);
var direction = $(this).data(&quot;tooltip-direction&quot;);
if (direction == null) direction = &#39;right&#39;;
var top = $(this).offset().top;
var left = $(this).offset().left;
var offsetX = $(this).data(&quot;tooltip-offset-x&quot;);
if (offsetX == null) offsetX = 0;
var offsetY = $(this).data(&quot;tooltip-offset-y&quot;);
if (offsetY == null) offsetY = 0;
//console.log(top,left,$(this).width());
var cssAdd = &#39;&#39;;
var cssColorAdd = &#39;&#39;;
$(&#39;.&#39; + opts.tooltipDiv).removeClass(opts.tooltipFadeOut + &#39; &#39;
+ opts.tooltipBoxBottom + &#39; &#39;
+ opts.tooltipBoxRight + &#39; &#39;
+ opts.tooltipBoxTop + &#39; &#39;
+ opts.tooltipBoxLeft + &#39; &#39;
+ opts.tooltipBoxRed + &#39; &#39;
+ opts.tooltipBoxBottomRed + &#39; &#39;
+ opts.tooltipBoxTopRed + &#39; &#39;
+ opts.tooltipBoxLeftRed + &#39; &#39;
+ opts.tooltipBoxRightRed).html(helptext);
switch (direction) {
case &#39;top&#39;: // top
top = top - 48 + offsetY;
left = left + $(this).width() / 2 - 25 + offsetX;
cssAdd = opts.tooltipBoxTop;
cssColorAdd = opts.tooltipBoxTopRed;
break;
case &#39;right&#39;: // right
top = top + $(this).height() / 2 - 13 + offsetY;
left = left + $(this).width() + 20 + offsetX;
cssAdd = opts.tooltipBoxRight;
cssColorAdd = opts.tooltipBoxRightRed;
break;
case &#39;bottom&#39;: // bottom
top = top + $(this).height() + 14 + offsetY;
left = left + $(this).width() / 2 - 28 + offsetX;
cssAdd = opts.tooltipBoxBottom;
cssColorAdd = opts.tooltipBoxBottomRed;
break;
case &#39;left&#39;: // left
top = top + $(this).height() / 2 - 13 + offsetY;
left = left - $(&#39;.&#39; + opts.tooltipDiv).width() - 16 + offsetX;
cssAdd = opts.tooltipBoxLeft;
cssColorAdd = opts.tooltipBoxLeftRed;
break;
}
//console.log(left);
if (color == &#39;red&#39;) {
$(&#39;.&#39; + opts.tooltipDiv).addClass(opts.tooltipBoxRed);
$(&#39;.&#39; + opts.tooltipDiv).addClass(cssColorAdd);
}
if (typeof(arrowOffsetx) != &quot;undefined&quot; &amp;&amp; arrowOffsetx.length &gt; 0) {
$(&#39;.&#39; + opts.tooltipDiv)
.addClass(&#39;tooltipBoxArrowOffsetX&#39;)
.append(&#39;&lt;style&gt;.tooltipBoxArrowOffsetX::after,.tooltipBoxArrowOffsetX::before{left:&#39; + arrowOffsetx + &#39; !important;}&lt;/style&gt;&#39;)
}
if (typeof (arrowOffsety) != &quot;undefined&quot; &amp;&amp; arrowOffsety.length &gt; 0) {
$(&#39;.&#39; + opts.tooltipDiv)
.addClass(&#39;tooltipBoxArrowOffsetY&#39;)
.append(&#39;&lt;style&gt;.tooltipBoxArrowOffsetY::after,.tooltipBoxArrowOffsetY::before{left:&#39; + arrowOffsety + &#39; !important;}&lt;/style&gt;&#39;);
}
$(&#39;.&#39; + opts.tooltipDiv).addClass(cssAdd).css({ left: left, top: top }).fadeIn();
})
$(document.body).live(&#39;mouseleave&#39;, `.${classSelector}`, function (e) {
$(&#39;.&#39; + opts.tooltipDiv).addClass(opts.tooltipFadeOut);
})
$(document.body).live(&#39;click&#39;, `.${classSelector}`, function (e) {
var ishide = $(this).data(&quot;tooltip-onclickhide&quot;) == &#39;1&#39;;
if (ishide) $(&#39;.&#39; + opts.tooltipDiv).addClass(opts.tooltipFadeOut);
})
return this;
},
})
})(jQuery);

答案1

得分: 1

"mouseenter"和"mouseleave"事件的事件委托只能在捕获阶段执行。

用以下代码替换:

document.body.addEventListener('mouseenter', function(e) {
	if (e.target.matches(`.${classSelector}`)) {
		// 在这里编写代码
		// 使用e.target代替this
	}
}, true);

对于"mouseleave"事件也是相同的。

英文:

Event delegation for "mouseenter" and "mouseleave" events can only be done in the capturing phase.

Replace

$(document.body).live(&#39;mouseenter&#39;, `.${classSelector}`, function (e){}

with

document.body.addEventListener(&#39;mouseenter&#39;, function(e) {
	if (e.target.matches(`.${classSelector}`)) {
		// code here
		// use e.target instead of this
	}
}, true);

The same applies for "mouseleave".

huangapple
  • 本文由 发表于 2023年2月24日 08:31:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75551619.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定