I have a text in a table that shows a popup text onmouseover, and this popup disappears 1 second after onmouseout.
I want this popup not to disappear if the mouse is moved over the popup (that is, if the mouse is moved away from the original table text but over the popup). An example of what i want to achieve can be seen in http://www.pnas.org/content/current , scroll down a little bit and place the mouse over an article title.
Can I include a function on the popup to prevent its closing?
I know that almost everything can be achieved, but I'm an newbie amateur, so dont waste your time if the solution is complex.
My code for the popup:
var popup;
function lopen() {
if (this.element == null) {
this.element = document.createElement('div');
this.element.id = "myPopup";
this.element.innerHTML = "new text";
this.element.style = "position: absolute; top: 650px; left: 400px; width: 200px; height: 200px; background-color: #ccc;";
}
document.body.appendChild(this.element);
}
var timeoutID;
function delayedlclose() {
timeoutID = window.setTimeout(lclose, 1000);
}
function lclose () {
document.body.removeChild(this.element);
}
The link for displaying the popup is in a html table:
<tr><td><a onmouseover="lopen()" onmouseout="delayedlclose()">Show</td></tr>
you could move your onmouseout event handler from the <a> to the <div id='myPopup'>
Related
We have a message view in our app where we on initial rendering load a list of messages which are then rendered, going from <div>Loading ....</div> to [<Message>,<Message>,...,<InputBox>] (pseudo-jsx). Upon loading, the view is extended to many times the screen length, so we need to scroll to the bottom onLoad(). This is bothersome :
lazy loading images in the older parts of the conversation won't work, as we "scroll past" them, triggering loading
there should be no need to do scrollTo(99999): we want to start a freshly loaded page on the bottom!
So how can I have the initial "scroll position" of a container be the bottom of the container? This seems like a quite basic thing.
The following contrived example is designed to show you one possible solution by emulating your scenario. If I have this wrong please correct me.
(React example linked at bottom)
Ten images are loaded into individual <div> elements. To emulate network/loading delay each <div><img></div> is loaded every 1/2 second. Notice that nothing is visible while this happens other than the "Loading..." placeholder. Five seconds later, after all are loaded, a custom event is fired to indicate the loading is complete. The very last image will be dark blue rather than the light blue of the others.
An event handler responds to the custom event by removing the "Loading..." indicator, scrolling to the bottom <div> and finally setting visibility of the entire section to visible.
Note the <div>s just appear and the <section> has been scrolled to the bottom. The bottom <div> is the dark blue one.
const container = document.querySelector('section');
const divsToAdd = 10
let divCounter = 0;
const interval = setInterval(addDiv, 500);
document.addEventListener('panelLoadComplete', () => {
document.querySelector('section span:first-child').remove();
document.querySelector('section div:last-child').scrollIntoView();
container.style.visibility = 'visible';
});
function addDiv() {
const div = document.createElement('div');
const img = document.createElement('img');
div.style.display = 'inherit';
div.appendChild(img);
container.appendChild(div);
if (divCounter === divsToAdd) { // is last - dark blue
img.src = "https://via.placeholder.com/100/0000ff"
} else {
img.src = "https://via.placeholder.com/100/0088ff"
}
if (++divCounter > divsToAdd) {
clearInterval(interval);
document.dispatchEvent(new CustomEvent('panelLoadComplete'));
}
}
section {
visibility: hidden;
}
section span:first-child {
visibility: visible;
}
section>div:first-child {
background-color: lightblue;
width: 100px;
height: 100px;
}
section>div:last-child {
background-color: darkblue;
width: 100px;
height: 100px;
}
<section>
<span>Loading... (patience: this takes ~5 seconds)</span>
</section>
Finally, a simple React version:
React Example StackBlitz
I tried to disable the graph by not allowing the cells on graph with follow code.
graph.setCellsSelectable(false);
but it is not working, still can select cell, (only disabled resizing)
And for the toolbar to be disabled, I tried to remove or replace ondrag event, is that correct? In theory I think mxgraph has their own event handler for dragging of toolbar item.
mx_toolbar.appendChild(
mxUtils.button("Disable/Enable", function() {
document.querySelectorAll('.toolbar > button').addEventListener(function (e) {
e.preventDefault()
return false;
});
}
)
Hope your help. I dont mind as long as it is working solution.
Thanks
Instead of removing or modifying the event handler, you can simply overlay the area you want to disable along with css.
var toolbarContainer = document.querySelector(".toolbar");
var overlay = document.querySelector(".toolbar-overlay")
if (!overlay) {
overlay = document.createElement('div')
overlay.className = 'toolbar-overlay'
toolbarContainer.appendChild(overlay)
} else {
overlay.parentNode.removeChild(overlay)
}
Here is css for the overlay div
.toolbar-overlay {
position: absolute;
top: 0;
height: 100%;
width: 100%;
opacity: 0.4;
background: #e1e1e1;
}
Note: You should make sure the parent div of the overlay div must positioned as relative to make this css working!
I'm running this plugin in WordPress that makes pretty image maps with shapes over images. It uses JS/jQuery extensively. I've used a custom script to show/hide a div when I click a shape. This particular div is stacked above the div that contains the image map. It appears and disappears just fine, but when I mouse over it and/or click on it, for some weird reason the hovers and clicks get through the higher stacked div down to the map div while still working on the popover one. Here's a simplified version of how things are set up:
function toggle_visibility(id) {
var e = document.getElementById(id);
if (e.style.opacity == '1')
setTimeout(() => {
e.style.opacity = '0';
}, this.animationDelay + 2),
setTimeout(() => {
e.style.zIndex = '-30';
}, 400);
else
e.style.zIndex = '999999999',
setTimeout(() => {
e.style.opacity = '1';
}, this.animationDelay + 2);
}
.city {
position: relative;
}
#ipano {
position: fixed;
min-width: 90vw;
left: 5vw;
top: 50%;
transform: translateY(-50%);
opacity: 0;
z-index: -30;
}
<div class="city">
// map code
</div>
<div id="ipano">
//popup code
</div>
The map plugin allows me to assign onClick code to any shape defined, so I added this to make a click on the shape reveal the hidden div like so: toggle_visibility('ipano'); javascript:event.preventDeafult();.
But even if I remove my custom script for revealing the #ipano div, the problem still persists. You can see it in action here.
I think this is somehow due to the map script and how it handles the mapping of the overlay map regions (with an .svg), but I can't put my finger on it.
I've tried changing the divs' order, removing the preventDefault bit, and adding pointer-events: none; to some and all the map's elements, but that didn't help. How's that even possible?
Any suggestions in the right direction greatly appreciated, thank you!
The idea is that when users mouse over each name in the list, the div with id preview will have background image. The first a does not have a problem, but when I added the href, JavaScript keep firing the hover event. What is the problem here?
HTML
<ul>
<li><a>John</a></li>
<li>Sam</li>
<li>Tom</li>
</ul>
<div id="preview"></div>
JavaScript
jQuery(function() {
var names = $('a');
var bg = document.getElementById('preview');
names.hover(
changeBackground, handlerOut
);
function changeBackground(e) {
console.log('hover');
var image = 'http://londonalley.com/wp-content/uploads/2014/08/creativesUS3bb-1920x1080.jpg';
if (bg.style.cssText.length == 0) {
bg.style.cssText = builtStyle(image);
bg.style.display = "block";
}
}
function builtStyle(image) {
return "width: 100%;height: 100%;opacity: .6;position: absolute;top:0px;left: 0px;z-index: 101;opacity:.9: 1;display: block;visibility: visible;background-image: url(" +
image + ");"
}
//handle mouse leaves
function handlerOut() {
console.log('out');
if (bg.style.cssText) {
bg.style.cssText = "";
}
}
});
JSfiddle: https://jsfiddle.net/rattanak22/q96a6dz4/
Solution: Simply change your z-index css in the builtStyle function from 101 to -1
z-index: -1;
Note: You have specified opacity twice in your CSS.
The problem is you are setting background image as absolutely positioned without z-index. So when you hover over "a" tag, changeBackground function assigns an background image which is absolutely positioned with no z-index. That will bring image on top above all, like one more layer above "a" tag. As this new layer comes up, mouse cannot reach "a" tag which triggers hoverOut, and the cycle continues for every mouse moment.
function builtStyle(image) {
return "width: 100%;height: 100%;opacity: .6;position: absolute;top:0px;left: 0px;z-index: -1;opacity:.9: 1;display: block;visibility: visible;background-image: url(" +
image + ");"
}
https://jsfiddle.net/pradosh987/9p0pjtd4/
I have assigned -1 z-index to background image and that works.
After looking at your site, simply, change your css rules to:
#content-wrapper {
position: relative;
z-index: 102;
overflow: hidden;
}
#preview{
pointer-events: none;
}
I have 2 elements, the first one (at the top) has the following CSS properties:
header {
position: relative;
height: 100%;
width: 100%;
background-color: black;
}
This makes it in the size of the browser's viewport, what I did on purpose because I wanted that result. I also had to give the html, body element the CSS property's for this to work (filling the screen with the first element):
html, body {
height: 100%;
width: 100%;
}
The second element I have looks like this:
#content {
display: none;
position: relative;
height: 1500px;
width: 100%;
background-color: yellow;
}
This element is underneath the first one.
As you can see, this element is hidden. That's because when I click on the button on the first element (which you can see in the jsFiddle) it shows the #content element, scrolls to that, and hides the element where we came from (header) when it's done scrolling.
Which works perfectly, I've got the function here:
var showScrollHide = function(showTime, element, eleTime, hide, hideTime, func) {
var _ele = $(element),
_hide = $(hide);
_ele.fadeIn(showTime, function() {
$('html, body').animate({
scrollTop: _ele.offset().top
}, eleTime, function() {
_hide.fadeOut(hideTime, func ? func : null);
});
});
};
I'm calling that function by this piece of code:
$('.exploreBtn').on('click', function() {
showScrollHide(500, content, 1000, header, 250, function() {
$(window).scrollTop(0);
$('.scrollBackBtn').fadeIn();
});
});
In the snippet above I had to call $(window).scrollTop(0); otherwise it would scroll down the page a bit when it was done scrolling. Also I displayed the scroll back button now, but that is the problem.
When I'm on the second element, and the element above it is hidden by the function above. And I try to use the same function to scroll it back up which means:
Show the element above
Scroll to it
Fade out the element we came from
It only gives me a fade to the element I'm trying to scroll to.
When I removed all the code from the function, and only used this:
$('header').fadeIn();
It just did the same and automatically faded the screen to that element we have just faded in. Which means it scrolls up, but not with any animation or what so ever.
Here is a jsFiddle to show what I'm doing
Btw, I already fixed this issue with the help of #Loktar with this piece of code, but I'm still not sure if its the right way to do it:
$('.scrollBackBtn').on('click', function() {
$(window).scrollTop(0);
$(header).slideDown();
});
If I am understanding it correctly the following should work.
_scrollBackBtn.on('click', function() {
_window.scrollTop(0);
$(header).slideDown();
});
Live Demo