Make room between divs when clicking a div to show hidden content - javascript

What I want to do is add functionality such that if I click any div bar, space opens up below it to allow me to see a hidden div. Clicking the original bar will re-hide the hidden div and remove the expanded space between the div bars.
When the hidden divs are hidden the layout looks like this:
When a div bar is clicked, the layout expands so that the hidden div is visible between the rows of div bars. The space between the bars expands to make room for the hidden div. (Blue "Hidden 2")
This is not a duplicate of another question out there because all of the other questions were more narrow and do not address the functionality I am trying to achieve with divs.
.bar {
width: 400px;
height: 30px;
border: solid 1px #aaa;
border-radius: 8px;
padding: 20px;
font-size: 24px;
margin: 15px;
background-color: #ccc;
z-index: -2;
}
.hidden-data {
display: none;
width: 350px;
height: 70px;
border: solid 1px #aaa;
border-radius: 8px;
padding: 20px;
font-size: 24px;
margin: 15px;
background-color: #e6eeff;
z-index: 1;
}
<div class="bar" id="bar1">Bar 1</div>
<div class="hidden-data" id="hidden1">Hidden 1</div>
<div class="bar" id="bar2">Bar 2</div>
<div class="hidden-data" id="hidden2">Hidden 2</div>
<div class="bar" id="bar3">Bar 3</div>
<div class="hidden-data" id="hidden3">Hidden 3</div>
<div class="bar" id="bar4">Bar 4</div>
<div class="hidden-data" id="hidden4">Hidden 4</div>
I have seen solutions that use < ul > < li > and solutions that use checkboxes, but I am using neither. (And I could get neither to work with my divs)
I have seen solutions that use spans, but those only support one row. If you add more than one row, then both rows respond to the click.
https://jsfiddle.net/tzfa81cp/73/
I saw a solution that uses < summary > < details > which looks like it is an all text version of the functionality I want, but this seems like it may not be supported by most browsers. (And I couldn't get it to work with divs.)
http://jsfiddle.net/thurstanh/emtAm/2/
A CSS solution would be great if there is one, but am definitely open to a JavaScript solution. I am new to jQuery
To reiterate the question:
I want to be able to click Bar 1 and have a box "Hidden 1" open below it, moving the other div bars down to make room. Then to close the hidden div, I click Bar 1 again. (or click an x in the hidden div).
How can this be done?
My codepen is here:
https://codepen.io/Chris_Nielsen/pen/xWNmYy

The Summary/Detail solution is toggling due to built in functionality - something div's do not have out of the box.
A jQuery solution would be simple, something like:
$(function() {
$(".bar").click(function() {
$(this).next(".hidden-data").toggle();
});
});

I have seen simple solutions to this problem using Javascript. In theory, you could have a div set up to display, ":hover" (sp?), but I have never seen it in practice. Worth exploring?

Related

Getting two divs to share one background image

So I'm trying to get two individual divs which are close in proximity to share one background image but I'm not sure if this is possible. I've uploaded two pictures, the second being designed for a smaller screen (just to further explain what I mean) http://imgur.com/a/2dypd . I can't imagine two separate background images would work as they wouldn't line up when resizing the window.
The only solution I can think of is creating two plain white divs to overlay on one single div but that seems like a dodgy way to go about it. I'm not expecting a hunk of code to be written for me, maybe just explain if it's possible and a reference so I can learn. Cheers.
Based on #cale_b's comment, you can set the same background to both div's and then use the background-position property to do the delusion of background sharing.
Then you can use media queries to make it look good in mobile too.
Here you've got a simple example that looks like the one you posted:
#wrapper {
width: 800px;
font-family: sans-serif;
}
#top {
height: 200px;
margin-bottom: 20px;
background-image: url("https://placekitten.com/800/400");
background-position: 0 0;
line-height: 150px;
color: #FFF;
font-size: 32px;
text-indent: 50px;
}
#bottom {
width: 500px;
height: 100px;
background-image: url("https://placekitten.com/800/400");
background-position: 0 -220px;
}
#bottom ul {
list-style: none;
}
#bottom ul li {
display: inline-block;
list-style: none;
padding: 0 10px;
line-height: 50px;
color: #000;
font-size: 24px;
}
<div id="wrapper">
<div id="top">
I'm a banner
</div>
<div id="bottom">
<ul>
<li>I'm</li>
<li>a</li>
<li>menu</li>
</ul>
</div>
</div>
As I understand, you want to use only one image copy of one image over two div and you dont want to use any overlay.
So you can do the following:
On the bottom div, use background-position-y:-100px or any other desired value. This way you push the image upwards.
This looks promising so far, but you will face an issue with the size of the background size specially if you are making a responsive web page.
I would say that background-size:100% 100%for both div would do the job yet it will make the image stretching (unless you go really responsive).
I still recommend using an overlay or even a ready made image. But if you insist on using two div then the above steps should be enough while you have to make your design suitable for this image.
N.B. keep in mind that you might need to use background-repeat:no-repeat

Slide DIV's from left or right using buttons and jQuery

I'm trying to create a function that can slide div's from left or right based on what step you are in the process.
This is my basic structure:
<button type="submit" id="button1">Go to Step 1</button>
<button type="submit" id="button2">Go to Step 2</button>
<button type="submit" id="button3">Go to Step 3</button>
<div id="container">
<div id="div1">Text 1</div>
<div id="div2">Text 2</div>
<div id="div3">Text 3</div>
</div>
Using jQuery I have this, but it's not what I want:
$('#div1').animate({'width': 0}, 500,function(){ // Slides DIV to left
$('#div1').css('display','none');
$('#div1').css('width', 1100); // Set the correct with on DIV again
$('#div2').fadeIn('slow'); // Fade in new DIV
});
What I'm after is when I'm in Step 1 and press button two (Go to Step 2) I want div2 to slide in from the right (inside the container-div). When I'm in Step 3 and press button one (Go to Step 1) I want div1 to slide in from the left (inside the container-div) without seeing div2 on the way over. I'we looked at different jQuery sliders but they all handle pictures.
Here is an example that does something along the lines what I what to achieve but does not have the left/right slide functionality: http://jsfiddle.net/andrewwhitaker/2uV2h/ (source: How to Slide div's off/on page using jQuery). Please ask questions if something is unclear :) Thanks in advanced.
JSFIDDLE: https://jsfiddle.net/t5qnw5v5/3/
nkwinder already posted an answer with a jQuery plugin, but I went ahead and cut jQuery completely out of the question, I don't know if you prefer that, but if you want that solution, it is here https://jsfiddle.net/3ydpa3oL/ , I may have even modified your jsfiddle, no idea how does that page work.
What I did:
I put another element inside of #container, so that it contains all of the .boxes and named it #slider.
<div id="container">
<div id="slider"> <!-- NEW ELEMENT NEEDED -->
<div id="div1" class="boxes">Text 1</div>
<div id="div2" class="boxes">Text 2</div>
<div id="div3" class="boxes">Text 3</div>
</div>
</div>
.boxes
{
width: 50px; // CAUSE I DID NOT WANT TO MESS AROUND TOO MUCH
height: 20px; // CAUSE I DID NOT WANT TO MESS AROUND TOO MUCH
font-size: 1em; // CAUSE I DID NOT WANT TO MESS AROUND TOO MUCH
float: left; // SO THAT THEY SLIDE LEFT AND RIGHT
}
#container
{
width: 50px; // WINDOW EFFECT
height: 20px; // WINDOW EFFECT
display: block;
overflow: hidden; // WINDOW EFFECT
}
#slider
{
position: relative;
width: 200px; // ENCLOSE .boxes
transition: left 1s; // NO JQUERY
}
#div1 {
background-color: green;
}
#div2 {
background-color: blue;
}
#div3 {
background-color: orange;
}
All of the .boxes HAVE TO be always visible, and the container HAS TO have an overflow property set to hidden, so that everything outside of its size is clipped. #slider is there to make float:left work, otherwise the .boxes the size of #container and do not behave very well.
Now it is easy to have a nice animation on the divs with a simple transition property on #slider, because we just move this element around and because #container clips everything outside of it, we get a nice effect of sliding .boxes.
Bare in mind that this approach forces you to write some additional code ( not provided by me ) to adjust the size of #slider, otherwise float:left is not going to behave correctly and the .boxes will appear on top of each other, which will ruin the effect. You could probably use display:flex to fix that, if you can use CSS3 freely.
I would recommend to use http://jquery.malsup.com/cycle2/demo/non-image.php
You can slide div's not only images. You don't have to implement sliding with custom code.

Capturing an event through a DOM layer that contains other event listeners

tldr; I want to have a button's event captured (click) even though it's under a DOM layer.
Here's my problem, I have a DOM layer that's relatively positioned and has a z-index set higher than 1, let's just say 2. That DOM layer is above the button (Button A) I'd like to have triggered when clicked. The reason that DOM layer is above the button (Button A) in question, is that the button (ShoreMore) across from it has another event that when clicked, opens a drawer of other little links.
Here's what I've tried:
I tried adding pointer-events: none; to the DOM layer above my button. problem is that while it now allows the button to be pressed, the DOM layer with the button that opens the drawer of other link no longer works. Suggested by this SO question.
I also came across this little trick found on this website. It essentially, hides the mask and rechecks the user's click coordinates and fires the event that is found within the coordinate. However, I found myself unsatisfied with the results, as I'm often given DOM that's unhelpful too specific or too broad based on the user's click. (e.g. getting the icon, text next to the icon, etc. of the Button).
For illustration purposes, here's what I have:
Here's my code:
HTML
<div id="drawer" class="drawer">
<div id="shield" class="shield"></div>
<div id="expander" class="expander">
<div class="inner">
<ul>
<li>links</li>
<li>links</li>
<li>links</li>
<li>links</li>
<li>links</li>
</ul>
<div id="tab" class="tab" >
<i class="icon"></i> Show More
</div>
</div>
</div>
</div>
<span id="btnA" class="btn">
<i class="icon"></i>
<span>Button A</span>
</span>
CSS
.drawer {
position: relative;
height: 0;
z-index: 2;
margin-bottom: .5em;
}
.expander {
position: relative;
height: 28px;
transition: height .2s ease;
overflow: hidden;
}
.inner {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
margin-bottom: 28px;
}
I didn't include the javascript, but "Button A" and "Show More" have a click listener. They both work, but Button A is confirmed to work if pointer-events: none; is added to the CSS of the class "expander."
EDIT: spelling
One possible solution is to use more absolute positioning.
The problem you're running into is that HTML elements, no matter their shape, end up as rectangles when rendered. Your blue outlined layer has a complex shape that's not strictly rectangular, but HTML doesn't care - it expands the layer's shape into a big rectangle to cover the parent element and all of its children elements, as you've correctly drawn in your diagram.
Absolute positioning helps prevent that from happening. Instead of leaving space for an element in the document flow, absolute positioning sort of pops the element out and positions it relative to its parent. The result is an element that doesn't expand the borders of its parent element, because it essentially takes up zero space in the normal document flow.
Consider the following example:
$(function(){
function slideDown(){
this.innerHTML = "Close";
$("#tray").animate({top: "50px"});
$("#higher-button").off("click").on("click", slideUp);
}
function slideUp(){
this.innerHTML = "Show More";
$("#tray").animate({top: "0px"});
$("#higher-button").off("click").on("click", slideDown);
}
$("#higher-button").on("click", slideDown);
$("#lower-button").on("click", function(){
alert("Lower button clicked.");
});
});
* {
margin: 0;
padding: 0;
text-align: center;
line-height: 50px;
}
#box {
position: absolute;
top: 20px;
left: 20px;
}
#lower-button {
width: 200px;
height: 50px;
background-color: #cccccc;
position: absolute;
top: 50px;
}
#higher-button {
width: 200px;
height: 50px;
background-color: #888888;
position: absolute;
top: 50px;
left: 200px;
}
#tray {
width: 400px;
height: 50px;
background-color: #aaaaaa;
position: absolute;
}
#mask {
position: absolute;
width: 400px;
height: 50px;
background-color: #dddddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box">
<div id="lower-button">Button A</div>
<div id="tray">
<div id="higher-button">Show More</div>
</div>
<div id="mask">Mask</div>
</div>
Absolute positioning lets you easily layer and position elements in a way that avoids them taking up excess space.
The caveat to all this is that absolute positioning can be pretty messy. Since it removes elements from the normal document flow, they don't take up any space, and it can wreak havok with your layouts. So use absolute positioning sparingly, for cases like this where you're building a UI element that you probably don't need taking up space in the layout anyway.
As always there are dozens of ways to solve this problem and this is only one possibility, but I hope it helps you figure out your own solution. Good luck!
Edit: Note you don't necessarily need to make all of the UI elements absolutely positioned, only the ones you need in order to manage the document flow. For example, the parent UI element could still be relatively positioned, and you just "pop out" the individual UI components. You still need to manually manage the size of the parent UI container, because absolutely positioned elements take up zero space in the flow. jsfiddle.net/v2646v41
One easy solution would be to change the z-index of Button A. When the drawer is closed, set it higher than the drawer's div, and when Show More is clicked, set the z-index underneath, then back above after the drawer has slid back under the mask.

How can I make my tree view elements overflow past the parent div's width?

I am using bootstrap-treeview to try to make a nice treeview within my MVC project. This control is available on NuGet so its easy to get started with it. The left hand div shows the tree and the right hand div shows the content of each element when clicked:
<body>
<div id="tree" style="position:absolute; width: 20%; height: 100%; overflow: scroll"></div>
<div id="content" class="list-group-item node-tree" style="position: absolute; left: 20%; width: 80%; height: 100%">This is where content goes once you click on a file or folder element.</div>
</body>
There is a slight problem, though. The content of the div with the ID = tree gets cut off:
Ideally, I would like these list elements to overflow to the right, beyond the size of the div with the ID = tree, as you can tell, because I have set overflow: scroll, so I do not want any text to wrap to a new line.
On runtime, it appends list elements as follows...
These list elements seem to have the following CSS:
.list-group-item {
position: relative;
display: block;
padding: 10px 15px;
margin-bottom: -1px;
background-color: #fff;
border: 1px solid #ddd;
}
I have tried adding white-space: nowrap; to this CSS, which makes the text do what I want (and overflow with a scrollbar), but the background and border of each list element stay at the width of the parent (which is not what I want; I want them to also overflow all scrollable width just like I did with the text)!
What can I do to make each element of this list properly overflow past the bounds of the parent div they all exist under?
Edit: I've tried putting overflow:visible on all parent levels as well, but it did not work. It removed the vertical scroll bar and kept all list item background borders still restricted to the width of the tree div. I also found that setting width = 10000px on the .list-group-item CSS partially gives me what I want as well, but obviously this makes the backgrounds too wide and the scroll bar becomes too elongated. I want the width of all list elements to be equal to the width of the widest overflowing content.
I figured it out. I had to change the display to table-row-group and I had to add white-space: nowrap:
.list-group-item {
position: relative;
display: table-row-group;
padding: 10px 15px;
margin-bottom: -1px;
background-color: #fff;
border: 1px solid #ddd;
white-space: nowrap;
}
Add overflow:visible to the parent element(s). You may need this at multiple levels, as each parent element could potentially restrict the content.

Grid of photos - multiple select/highlight? Toggle?

I've a grid of photos. What I need is the user to be able to click on the photos of people they want to invite to an event. Upon first click I'd like it to alter the CSS/styling (for example add a border or change transparency) then on second click revert back to original style. So toggle I guess.
So that a user can click say three images and those three would have a green border showing they've been selected. Then if he'd like to deselect he simply click again and it reverts back to the original style.
How is this possible? CSS? Javascript? JQuery?
So far all I've got is the table of photos:
HTML
<div class="user">john</div>
<div class="user">doe</div>
<div class="user">larry</div>
<div class="user">sergey</div>​
CSS
.user {border: 1px solid #ededed; cursor: pointer; width: 100px; padding: 10px; margin-bottom: 10px}
.active {border: 1px solid #0066cc; background: #eeeeee;}​
jQuery
$('.user').on('click', function() {
$(this).toggleClass('active');
});​
Fiddle - http://jsfiddle.net/qgGne/

Categories