When hovering elements they display the content in a bubble.
..the tooltips shows on a tap since there is no hover. But a tap like a click triggers links etc. I go around this by making tooltipster take over the href
of the element and display it inside the tooltip on a ad hoc created element like "Click here for more detail".
That works without a problem.
I have elements on the site without href
or <a>
made by js addeventlistener. This is sometimes done before tooltipster is activated in js and sometimes after and sometimes even with ajax.
So, just like taking over the click/tap by href
before, how do I make tooltipster take over the eventlistener?
This is not necessarily tooltipster specific. I can do that part. The question is rather, how to transfer eventlisteners in the first place?
Do I set a certain class on these elements and put the eventlisteners in a js Map? If so, then how do I transfer it to an element inside the tooltip without losing its target?
All help really appreciated!
There is code below, but it's not necessarily relevant:
isTouch = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)
$('.tooltip' + (isTouch?':not(.ajx)':''))
.tooltipster({
debug:true,
animation: 'grow',
interactive:true,
repositionOnScroll:true,
contentAsHTML : true,
//trackOrigin:true, //performance!
delay: 200,
trigger: 'custom',
triggerOpen: {
click: true,
mouseenter: true,
tap: true
},
triggerClose: {
mouseleave: true,
click: true,
tap: true
}
})
/***** Don't open tooltips of parents ****/
//click (parent events comes after child)
.has('.tooltip')
.tooltipster('option' , 'functionBefore' , (inst, helper) => { //console.log('functionBefore', helper)
if (helper.event && !helper.event.target?.isEqualNode(helper.origin))
return false;//console.log(helper.event)//.stop()
})
//hover (child events comes after parent)
.children('.tooltip')
.tooltipster('option' , 'functionBefore' , (inst, helper) => { //console.log('functionBefore', helper)
$(helper.origin).parents('.tooltip').tooltipster('close')
})
.tooltipster('option' , 'functionAfter' , (inst, helper) => { //console.log('functionAfter', helper)
//If hover out on or via parent
if (helper.event.relatedTarget?.classList.contains('tooltip'))
$(helper.event.relatedTarget).tooltipster('open')
})
The only solution I found was with capturing events and setting a class on the relevant html elements.
Explanation in code comments.
isTouch = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)
$tooltippeds = $('.tooltip' + (isTouch?':not(.noTouchTt)':'') )
.tooltipster({
debug:true,
animation: 'grow',
interactive:true,
repositionOnScroll:true,
contentAsHTML : true,
//trackOrigin:true, //performance!
delay: 200,
trigger: 'custom',
triggerOpen: {
click: true,
mouseenter: true,
tap: true
},
triggerClose: {
mouseleave: true,
click: true,
tap: true
}
})
//***Make touch not trigger events or follow links by capturing via the parent, and put the event in a new element in the tooltip
if (isTouch) {
//Capture via class tooltipMore except when an ancestor is an <a>, then via parent of the latter
$tooltippeds.parents('a').add($tooltippeds.not('a .tooltip').filter('[tooltipMore]')).parent().each((i,el) => {
//Evade creating it twice since tooltip elements share parents
if($(el).closest('[hasTouchClickPrevent]').length>0) return
el.setAttribute('hasTouchClickPrevent',true)
//Prevent the click event on child except when..
el.addEventListener('click',(e) => { console.log('tooltip click parent > ', window.tooltipMoreClicked)
if( !$(e.target).closest('.tooltip').length || //..child without tooltip
e.target.classList.contains('noTouchTt') || //..specifically denied with class 'noTouchTt' (can still be child)
window.tooltipMoreClicked || //..triggered from inside tooltip "more" element
e.target==e.currentTarget //..if the parent itself has a click event
) return true
e.preventDefault()
e.stopImmediatePropagation()
}, true) //capture!
})
$tooltippeds.filter('[tooltipMore], a .tooltip')
//Put the event on a new element inside the tooltip and trigger with original target when clicked
.tooltipster('option', 'functionFormat', (instance, helper, content) => { //console.log('functionFormatBefore', content)
$or = $(helper.origin)
$content = $.parseHTML( content + '<a class="more">' + ($or.attr('tooltipMore')??'Click for details') + '</a>' )
$($content).filter('.more').on('click', e => {
window.tooltipMoreClicked=true
evt = new PointerEvent(e.originalEvent.type, e)//clone event to get ctrlKey etc
helper.origin.dispatchEvent(evt) //jquery trigger() is NO solution since it doesn't bubble up for tooltips inside <a>
window.tooltipMoreClicked = false
})
return $content
})
The tag tooltipMore shouldn't be needed if javascript or jQuery had a function to detect if any elements have eventlisteners.