jsPlumb handling elements in a scrollable div container - javascript

I am using jsPlumb to connect a bunch of divs (much like a flow chart). All of the divs are contained in one parent div which is scrollable. Sort of like the code below, but with more divs inside the container div.
<div style="height:500px;width:500px;overflow:auto" id="container">
<div id="node1"></div>
<div id="node2"></div>
<div id="node3"></div>
<div id="node4"></div>
<div id="node5"></div>
</div>
My problem is that if I scroll the div, the connecting lines generated by jsPlumb just stay in place and don't scroll with the divs that they are supposed to be connected to. I've tried using jsPlumb.repaint() but still no luck. It appears jsPlumb is not taking into account the scroll offset of the caontainer div. Is there some way to fix this? I really want to avoid having to move the divs being connected out of the container div into the body since this would entail some very annoying css/html recoding.

It turns out that simply using jsPlumb.repaintEverything(); redraws the lines in the correct positions. jsPlumb.repaint() seems to be for repainting the lines for a specific element. For example, jsPlumb.repaint('div_id_goes_here');

Your question/answer helped me. Let me extend it with the code I used:
$('#container').scroll(
function(){
jsPlumb.repaintEverything();
}
)
This will cause the connections to be repainted as you scroll the container. On IE, it has a little delay depending on the scenario (child nodes move and then the connections move).

Related

How can I check, if all divs are fully visible inside an other div?

I have a div, called "wrapper", with responsive height and overflow-y auto (so scroll enabled). Inside this div are lots of other divs, called "box". So, for example, if there are 3 divs inside the wrapper and I see them all fully, nothing should happen. But if any of this divs inside the wrapper are not fully visible (on page load and page resize), an other div (called "button") should fadeIn.
I just found this post, but it doesn´t solve my problem:
stackoverflow post
HTML:
<div class="wrapper">
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
</div>
<div class="button">
My Button
</div>
My fiddle:
HTML + CSS
How can I check, if all divs are fully visible inside an other div (on page load and page resize)?
#
UPDATE:
My problem is, that "viewport" doesnt work for me, because the script has also to check what happens outside the viewport (dynamically). The height of my divs is responsive and so not every time all of it is in the viewport ...
... but for me, I found an other solution. Now I check the height of my main div (my main content) and if this div is smaller than the "wrapper" div, I will fadeIn the "button" div.
You can try this my friend"
if ($(".wrapper div").css('visibility') === 'hidden') {
// ...
}
When hosting your HTML:
Right click on your wrapper and inspect element
Hover over the first div inside of the wrapper, and it should become highlighted
Check to see if that div is visible on the page
Continue the above steps for every div in your wrapper
This seems to solve a problem that's the same as, or very similar to, the problem you're describing:
zeusdeux/isInViewport
The "examples" folder includes various examples where DIVs react to whether or not they are contained within a defined viewport div.
EDIT: After reading comments on the question, this seems to be the best resource for reading up on the general problem and solutions (even though isInViewport looks very useful as well):
How to tell if a DOM element is visible in the current viewport?

Is there a way to detect resize/zoom in all Ancestor DOM elements using Javascript?

I have a DOM element which contains a chart
<div id="plot1" class='plot-chart'></div>
This DIV can be nested in multiple DIVs
<div id="one" style="width:100%;height:100%;zoom:0.9;">
<div id="two">
<div id="three">
<div id="plot1" class='plot-chart'></div>
</div>
</div>
</div>
</div>
I need a way to detect any changes to size/zoom to all the ancestors(parents) of the plot DIV so I can zoom or resize it accordingly.
window.onresize
this works to detect any change to the overall browser window, but there maybe instances where DIV two or DIV three maybe changed without the window itself being manipulated. The Chart DIV is the one which I am creating and can be placed in any location, so calling a function from the outside when a resize happens is not a solution.
To simplify the question, is there any way to detect changes to any of the parent DIV's of my object so I can call a function internally?
So the short answer is "no". However, if you have any control over the cases where those container divs would be resized, then they could trigger custom events, (for instance, using jQuery) that your chart could listen to and react appropriately.
Hope this helps!
No, but you can easily use Twitter's Bootstrap to do resizing.
You can use the Grid System in BootStrap for this!

Divs too wide when hiding/showing

I have two divs that contain two other divs each. One containing DIV's display is set to none. I have a button that toggles the containing DIVs so I can alternately hide/show the containing div and thus the two divs inside. The inside DIVs are set the 49% width, floated left/right. Problem I have is the fist time the visible DIV is hidden and the hidden one displayed the inside two divs are way too wide. If I resize the width of the browser just a tiny bit with my mouse they are the desired size and any time I toggle the visibility from here on out all is fine. If I reload the page it is wrong on the first toggle. Works the same in IE 10 and Chrome so don't think a browser issue.
The inner two divs both contain high charts that are generated and rendered to the inner divs I want them to be side by side and almost (99%) the width of my page.
Here is snipped of my DIVs to be hidden and shown that contain the inner DIVs with highcharts
<div id="highChartsNG" style="width:99%;display:none;">
<div id="FillRateHigh" style="border:2px solid black;width:49%;float:left;"></div>
<div id="WaitTimeHigh"style="border:2px solid black;width:49%;float:right;"></div>
</div>
<div id="LowChartsPEAK" style="width:99%">
<div id="FillRateLow" style="border:2px solid black;width:49%;float:left;"></div>
<div id="WaitTimeLow"style="border:2px solid black;width:49%;float:right;" ></div>
</div>
This is a snippet of the javascript function I call on a button click to toggle on/off on the display of two containing DIVs
document.getElementById("highChartsNG").style.display = "none";
document.getElementById("LowChartsPEAK").style.display = "block";
Fiddle showing problem, see comment of mine below on how to reproduce http://jsfiddle.net/rplace/UTTz4/1/
Okay, after hours of searching I finally found the problem (I think). I was determined to find the solution =).
The problem is multiple-fold.
The first problem was the display:none; property on the second chartcontainer. For some reason the widths calculated for the charts and their containers were incorrect for the hidden div. So I removed the property from the HTML, and instead hid it dynamically with document.getElementById("LowChartsPEAK").style.display = "none"; in the JS right after the chart rendering functions. If you do this, your SVG's will fit your containers already, although the last one has a slight shift.
Apparently HighChart doesn't like percentage-based parent containers. When you go to your updated fiddle , run the fiddle with both:
<div id="wrapper" style="width: 800px;">
<div id="wrapper" style="width: 100%;">
Open the console and check the results (container name - SVG width - container width). When the wrapper is given a pixel width, all container widths are equal (as it should be). Now check the wrapper with percentage width: your last SVG will be about 6 to 20 pixels smaller. The only solution I have found for eliminating that small shift in the last container, is that somewhere a top container must have a pixel-width.
EDIT: pt's and em's also work. It's only % that causes problems
If you are hiding DIV, you should be aware that browser won't calculate %-based widths with display:none. Then if browser won;t calculate DIV, then also Highcharts are not able to do it ;)
Check this FAQ - when showing chart update his size or call reflow().

Hide child <div>s as parent div shrinks?

I am trying to write a zoom in/out feature on a web app I am making using the jqueryUI slider.
I am having difficulty handling when my parent div shrinks too much, and cramps its child containers.
<div class="puck originator inline-block" style="width: 310.5px; left: 0px;">
<div class="conflicted inline-block originator">
<div class="right-number">I should stay</div>
<div class="left-number">I should stay</div>
<div class="middle-number">I Should disapper</div>
</div>
</div>
Here is the relevant section of code I have
http://jsfiddle.net/aQKwE/
Basically I have the parent div (class 'puck') that is being shrunk using a jquery slider. For this code I just used a text box, but same idea.
When I shrink that div, the containing divs stick around and are very garbled.
I want to be able to remove the middle child div when it becomes to cramped, leaving the left and right child divs to occupy all the space
Furthermore, if it becomes to cramped yet after that, I want to remove the right div, leaving only the left.
Finally I want to be able to remove all contents so that nothing more than the background of the parent shows.
Is there a way to do this easily, preferably through CSS? I don't want to write more javascript code to set 'display:none' on each child div, since it seems like some CSS rules should handle this.
Any ideas?
There's not really any logic built into CSS to handle something like this. You can set rules based on viewport size, but that won't help in this case.
I updated your jsfiddle with this code so you can test it and see what you think, but essentially I just added some checks in your javascript function to hide based on the width submitted.
var newwidth = $('#text').val();
$(".middle-number").show();
$(".right-number").show();
if (newwidth < 280) {
$(".middle-number").hide();
}
if (newwidth < 180) {
$(".right-number").hide();
}
$('.puck').css('width',newwidth);

HTML "overlay" which allows clicks to fall through to elements behind it [duplicate]

This question already has answers here:
HTML/CSS: Make a div "invisible" to clicks?
(5 answers)
Closed 7 years ago.
I'm trying to overlay a element on top of a webpage (to draw arbitrary graphics), and I've come to the point where I can stack it inside of a element on top of everything, but this prevents the user from clicking on any links/buttons/etc.
Is there a way to have its content float on top of everything (it's semi-transparent, so you can still see what is behind) and have the user interact with the layer below it?
I've found a lot of information on the DOM event model, but none of it addresses the problem where the buttons and other "native" controls never seem to get the clicks in the first place.
A silly hack I did was to set the height of the element to zero but overflow:visible; combining this with pointer-events:none; seems to cover all the bases.
.overlay {
height:0px;
overflow:visible;
pointer-events:none;
background:none !important;
}
Add pointer-events: none; to the overlay.
Original answer: My suggestion would be that you could capture the click event with the overlay, hide the overlay, then refire the click event, then display the overlay again. I'm not sure if you'd get a flicker effect though.
[Update] Exactly this problem and exactly my solution just appeared in this post: "Forwarding Mouse Events Through Layers". I know its probably a little late for the OP, but for the sake of somebody having this problem in the future, I though I would include it.
For the record an alternative approach might be to make the clickable layer the overlay: you make it semi-transparent and then place the "overlay" image behind it (somewhat counterintuitively, the "overlay" image could then be opaque). Depending on what you're trying to do, you might well be able to get the exact same visual effect (of an image and a clickable layer semi-transparently superimposed on top of each other), while avoiding clickability problems (because the "overlay" is in fact in the background).
In case anyone else is running in to the same problem, the only solution I could find that satisfied me was to have the canvas cover everything and then to raise the Z-index of all clickable elements. You can't draw on them, but at least they are clickable...
My team ran into this issue and resolved it very nicely.
add a class "passthrough" or something to each element you want clickable and which is under the overlay.
for each ".passthrough" element append a div and position it exactly on top of its parent. add class "element-overlay" to this new div.
The ".element-overlay" css should have a high z-index (above the page's overlay), and the elements should be transparent.
This should resolve your problem as the events on the ".element-overlay" should bubble up to ".passthrough". If you still have problems (we did not see any so far) you can play around with the binding.
This is an enhancement to #jvenema's solution.
The nice thing about this is that
you don't pass through ALL events to ALL elements. Just the ones you want. (resolved #jvenema's argument)
All events will work properly. (hover for example).
If you have any problems please let me know so I can elaborate.
You can use an overlay with opacity set in order to the buttons/anchors in the back stay visible, but once you have that overlay over an element, you can't click it.
Generally, this isn't a great idea. Taking your scenario, if you had evil intentions, you could hide everything underneath your "overlay". Then, when a user clicks on a link they think should take them to bankofamerica.com, instead it triggers the hidden link which takes them to myevilsite.com.
That said, event bubbling works, and if it's within an application, it's not a big deal. The following code is an example. Clicking the blue area pops up an alert, even though the alert is set on the red area. Note that the orange area does NOT work, because the event will propagate through the PARENT elements, so your overlay needs to be inside whatever element you're observing the clicks on. In your scenario, you may be out of luck.
<html>
<head>
</head>
<body>
<div id="outer" style="position:absolute;height:50px;width:60px;z-index:1;background-color:red;top:5px;left:5px;" onclick="alert('outer')">
<div id="nested" style="position:absolute;height:50px;width:60px;z-index:2;background-color:blue;top:15px;left:15px;">
</div>
</div>
<div id="separate" style="position:absolute;height:50px;width:60px;z-index:3;background-color:orange;top:25px;left:25px;">
</div>
</body>
</html>
How about this for IE?:
onmousedown: Hide all elements which could overlay the event. Because display:none visibility:hidden not realy works, push the overlaying div out of the screen for a fixed number of pixels. After a delay push back the overlaying div with the same number of pixels.
onmouseup: Meanwhile this is the event you like to fire.
//script
var allclickthrough=[];
function hidedivover(){
if(allclickthrough.length==0){
allclickthrough=getElementsByClassName(document.body,"clickthrough");// if so .parentNode
}
for(var i=0;i<allclickthrough.length;i++){
allclickthrough[i].style.left=parseInt(allclickthrough[i].style.left)+2000+"px";
}
setTimeout(function(){showdivover()},1000);
}
function showdivover(){
for(var i=0;i<allclickthrough.length;i++){
allclickthrough[i].style.left=parseInt(allclickthrough[i].style.left)-2000+"px";
}
}
//html
<span onmouseup="Dreck_he_got_me()">Click me if you can.</span>
<div onmousedown="hidedivover()" style="position:absolute" class="clickthrough">You'll don't get through!</div>
I was having this issue when viewing my website on a phone. While I was trying to close the overlay, I was pretty much clicking on anything under the overlay. A solution that I found working for myself is to just add a tag around the entire overlay

Categories