Flyer53 / jsPanel4

A JavaScript library to create highly configurable floating panels, modals, tooltips, hints/notifiers/alerts or contextmenus for use in backend solutions and other web applications.
https://jspanel.de/
Other
313 stars 57 forks source link

Hover of iframe bring into focus. #185

Closed MadTomT closed 2 years ago

MadTomT commented 2 years ago

Hi, I asked about this on one of my other tickets, and we didn't think it was possible. I think I've got it working using the following:

    $("body").on('mouseover', "div[id^='jsPanel_']", function() {
        $('#' + this.id).css('z-index', 110)
    })
    $("body").on('mouseleave', "div[id^='jsPanel_']", function() {
        $('#' + this.id).css('z-index', 100)
    })

All my panels DIVs have an index starting jsPanel_ I'm only opening 4 panels, so a z-index of 110 is more than enough, just thought I'd post this in case it's helps someone.

Flyer53 commented 2 years ago

@MadTomT Well, if that works for you it's fine with me. But it's a customized solution for your use case that doesn't necessarily work in other use cases. However, I would recommend another approach in your case: Instead of attaching two handlers to document.body I would attach a single handler to each panel like:

jsPanel.create({
  callback: function(panel) {
    panel.addEventListener('mouseover', ()=>{
      panel.front();
    });
  }
});

Seems to work just as well ...

MadTomT commented 2 years ago

Thanks, that seems to work as well :)

Flyer53 commented 2 years ago

@MadTomT Since a mouseover doesn't necessarilly mean you want to front the panel I tried to find a better solution and created a very simple example using the BroadcastChannel API to exchange messages between documents in different browing contexts.

See the demo here ...

It of course works only if all relevant documents share the same origin according to the Same-origin policy! And it requires a browser supporting the BroadcastChannel API which excludes IE.

MadTomT commented 2 years ago

Hi, That is really helpful thanks.

The demo is creating the panel using let iframeHostPanel = jsPanel.create({ then using iframeHostPanel.front(); to bring the panel to the front.

I'm creating multiple panels using jsPanel.create({ is there anyway to target an individual panel by ID and bring it to front ?

Thanks

MadTomT commented 2 years ago

I think I've got this working using window['panel_' +Id ] = jsPanel.create({ and window[ clickedframe ].front() So far it seems to be bring the correct window to the front :)

Flyer53 commented 2 years ago

Let's assume you create a panel with a specific ID like:

jsPanel.create({
    id: 'panel_1',
    // rest od config ...
});

Now when this panel_1 has an iframe this iframe has to post a message which could be (assuming the BroadcastChannel object is "bc"):

bc.postMessage('panel_1');

So the message which is received by the host document gives you the id of the panel in question and in the host document you can use a handler like

bc.onmessage = (event) => {
    // event.data contains 'panel_1'
    document.querySelector(`#${event.data}`).front();
    // or
    // document.getElementById(event.data).front();
}
MadTomT commented 2 years ago

Thanks, that has helped. I do have the id for each panel so that works really well :)