How to adjust a floating div based on its height and surroundings? - javascript

Disclaimer: The following code is using the rubuxa plugin for JS sortables.
Javascript:
function qs(expr){return document.querySelector(expr)}
var container = qs('.ITEST');
var sort = Sortable.create(container, {
animation: 350,
draggable: ".draggable",
});
CSS:
.draggable{
color: #fff;
margin: 1px;
float: left;
display: inline-block;
}
.ITEST{
width:425px;
height:400px;
margin:auto;
border:1px solid grey
}
http://jsfiddle.net/g8o0upLq/9/
The problem lies when dragging the red squares, they move correctly, but they do not stack vertically ontop of each other but horizontally. This creates unwanted extra white space underneath. I have tried to set the same height for all divs, but with no luck.

i just saw your post through Rubaxa's Github.
Anyways, there is no way you can achieve this with pure CSS. Even with Flexbox i can't think of a way you can do this.
For accomplish this behaviour you need some way of javascript to calculate absolute positioning.
The Library http://packery.metafizzy.co/ does a good job for this. It uses 'jQuery UI draggable' or 'Draggabilly' which uses absolute positioning.
The downside, i don't think there is a way to make this happen with Rubaxa's Sortable...

Related

Why does will-change:opacity treat fixed elements differently than will-change:transform in chrome?

I am trying to optimize the scrolling of my web app. I have data tables with tons of data, and scrolling gets pretty bad. I added will-change: transform to the data table but it broke my table headers that are position: fixed (I make them fixed to allow them to scroll with the viewport). The elements don't move with the viewport at all, they just stay stuck in the flow of the document.
But by chance I discovered that if I use will-change:opacity instead, my fixed headers are fine. Can someone explain this behavior? I haven't been able to find any documentation that says they should act differently.
Here is a code pen with an example of what I am talking about. Toggle between the values, and scroll in blue div.
https://codepen.io/bkfarns/pen/aLYgrN
Here is the basic code from the pen too:
html:
<div class="container">
<div class="fixed">should be position: fixed</div>
<div class="too-tall">div that is too tall</div>
</div>
css:
.container {
margin-left: 100px;
background-color: blue;
width:400px;
height:300px;
overflow: auto;
will-change: transform;//changing this to opacity fixes the issue
}
.fixed {
background-color: grey;
position: fixed;
margin-left: 150px;
margin-top: 100px;
}
.too-tall {
background-color: red;
width: 90px;
height: 600px;
}
The whole point of will-change is to make all possible changes that browser would have to apply when the specified property will change in advance, reducing the time needed for the change itself. Effectively it means that by specifying will-change:transform you make the element transformed (though visually it stays in the same position), and descendants of the transformed elements can't be fixed per the CSS Transforms spec. Opacity doesn't have such effect, so will-change:opacity doesn't break fixed positioning.
Also, will-change per se doesn't have any "optimization magic", it only optimizes the changes of the specified properties. Some properties force the elements to the composite layers that theoretically can be processed by the GPU more efficiently, but if there is too many such elements it may have the opposite effect. For optimizing scrolling, probably other strategies would be more efficient.

Controlling the direction of JavaScript .show() / .toggle()?

I'm using JavaScript's .toggle() to have this appear/ disappear:
{
display: none;
position: fixed;
top: 100px;
right: 0;
left: 0;
background: rgba(0,0,0,0.75);
padding: 15px;
}
However, over the duration of the animation it starts from the top-left corner and expands out to the bottom-right corner of the div.
Ideally, I'd like to start it from the both top corners and expand downwards to both bottom corners evenly.
I thought the CSS transition-origin property might have an effect, but it doesn't seem to be the case.
Any ideas? Thanks in advance. :)
I would start a height of 0 and the animate the height property.
function toggle() {
var el = document.getElementsByTagName('div')[0];
if (el.className) {
el.className = '';
} else {
el.className = 'grow';
}
}
div {
background-color: black;
width:200px;
height: 0;
}
.grow {
height: 200px;
transition: height 2s;
}
<button onclick="toggle()">Toggle</button>
<div></div>
I don't know much about jQuery's toggle method, so I looked in the docs, and sure enough it gives some helpful info. (This is a gentle hint that before coming to StackOverflow you should try solving the problem on your own, including looking at any relevant documentation online).
The .toggle() method animates the width, height, and opacity of the
matched elements simultaneously.
The documentation doesn't give any info about customizing how toggle does its animation, so it looks like you're stuck. If I'm understanding you correctly, it seems like you want the element to animate only the height and not the width, so it stays the same width as it toggles and just animates the height. I don't see any way of doing that with jQuery's toggle.
BUT WAIT! It looks like jQuery has another method called slideToggle which does exactly what you want. It's just like toggle except it only animates the height and keeps the width the same. Hooray!
http://api.jquery.com/slidetoggle/
Moral of the story: if you're using a third party Javascript library like jQuery, you really need to get comfortable finding the information you need in the online documentation my friend. :)

Creating a InfoBox window above a marker with the stub in the correct place

I've been working from the InfoBox documentation and this post here to try to get an InfoBox looking almost the same as a standard InfoWindow as a starting point for some slight cosmetic changes.
As you can see in this fiddle the 'stub' that connects the InfoBox to the marker is still positioned at the top of the InfoBox.
I've tried to use backgroundPosition (commented out when you first open the fiddle) as follows in the boxStyle parameter, but it doesn't work.
boxStyle: {
backgroundImage: "url('https://directory.fsf.org/w/extensions/SemanticDrilldown/skins/down-arrow.png')",
backgroundRepeat: "no-repeat",
/*backgroundPosition: "center bottom",*/
opacity: 0.75,
width: "280px"
},
How can I move the stub down to the bottom center rather than the top left?
Add it with an :after selector to the infobox. Like this
#infobox:after{
content: "";
position: absolute;
bottom: -15px;
left: 125px;
border-width: 15px 15px 0;
border-style: solid;
border-color: #333 transparent;
display: block;
width: 0;
}
See Demo
p.s. I didn't remove the old one from your JS. That's why you'll see it in the screen still.
Supporting documentation per OP's request
There is plenty of documentation of CSS selector specifically the :before and :afterselectors. Some of it, and probably the most basic information will be found in w3schools.
SmashingMagazine also has a lot more detialed information and usefulness of this concept.
By hacking the element with a selector you can also style according to behaviors. such as :hover, :focus, :active, :inactive, :empty, and :blank
The actual triangle is built by drawing a small rectangle using borders and clipping one side of the borders. See this link in CSS tricks on how to build a CSS triangle.
As far as choosing :before or :after, there isn't a definite explanation as to which one you should use. Depending which one you use you will have to reposition accordingly. In some specific situations such as adding a font awesome icon via CSS selectors, it would make sense to add it to the :before selector if it is going to precede the element it is being attached to or use the :after selector if it's going to proceed the element instead
You need to set the background position on .infoBox and change the margin-top to margin-bottom on #infobox.
.infoBox {
background-position: center bottom;
}
#infobox {
margin-bottom: 8px;
}
See updated fiddle

d3.js static graph scrolling

I am trying to implement the following example
http://bl.ocks.org/mbostock/4566102
For large graphs, I just want the graph to not get cut-off and allow scrolling, once user drags it outside the current border.
I tried adding the overflow:scroll property to the svg element, but that doesn't seem to work.
I am new at this javascript/d3.js programming and would be glad if someone can point out the error or just guide me in the right direction.
What about making the svg large enough, but wrapping it into a smalle div with overflow: auto?
html
<div class="outer">
<div class="inner">
<svg></svg>
</div>
</div>
css:
.outer {
width: 400px;
height: 300px;
overflow: auto;
}
.inner {
width: 800px;
height: 600px;
}
svg {
display: block;
width: 100%;
height: 100%;
}
Demo
You can drag the red circle out of the visible area.
I'm afraid this will not be possible without javascript intervention. The svg root element must have a defined width and height, and it won't adapt at any extent to its contents.
If you are going for google, your question is more about svg than about d3.
I think the only possibility is to use javascript, in order to increase the sizes of svg when one object goes behind it. In this way, though, i can't figure out how to make it work for the left side, it becomes complicated.
I think it's better to tackle the problem with the solutions that d3 can offer you, like the zoom behaviour suggested above. And generally if you are new in this field i can suggest you to think the interaction before going for the implementation, picking examples from the d3 gallery in order to better understand what you really want.

Trouble making a facebook like div with triangle on top

on facebook if you hover over something with a lot of likes a div pops up showing everyone who likes the post. i was wondering if anyone could mimic the div in css and explain how i can do it. there is a picture below showing what i mean. i know you have to use a :after in css but im not sure how to position the triangle and all that.
Here is some code i found somewhere else:
#pointed {
position: relative;
margin: 0 auto;
width: 200px;
height: 200px;
background-color: white;
}
#pointed:after,
#pointed::after {
position: absolute;
top: 100%;
left: 50%;
margin-left: -50%;
content: '';
width: 0;
height: 0;
border-top: solid 150px red;
border-left: solid 100px transparent;
border-right: solid 100px transparent;
}
The code you pasted there has the gist of it down. You can see a working JSFiddle here that makes it more like what you're going for.
There are two parts to this problem, I think. The first part is making the triangle. The second part is positioning the triangle.
Making the Triangle
The borders on the pseudoelement are responsible for that triangle we're seeing. If you're not sure how that's happening, take a look at this great answer that explains it quite well, I think.
Positioning the Triangle
The key to positioning involves making the child appear outside of the parent. We can do this by setting absolute positioning on the child. However, if we do this without changing the parent at all, the absolute positioning will be set relative to the window.
What we want here is positioning the child relative to the parent. We can do this by setting the parent element's positioning to anything other than static, which is the default value. In the code you pasted, you can see they set it to relative. For more about positioning, the working docs are pretty explanatory, I think. Another great resource can be found on CSS Tricks.
Anyway, we want our child to be just outside the parent. Accordingly, if we have a 5px high triangle, the child's CSS for positioning should look something like:
position: absolute;
top: -5px;
This will make it appear like its attached to the top, as you can see in the above JSFiddle.
After you've positioned it vertically the way you want it to, set its left positioning to get it where you want along the horizontal.
Though of course you must ask yourself if it's worth reinventing the wheel—tooltips come with Bootstrap Jquery.

Categories