expanding an inline-block jumps to above row - javascript

I have a series of articles
<section>
<article>1</article>
<article>2</article>
<article>3</article>
....
<article>999</article>
<section>
arranged in a grid of three per row
section {
position: relative
}
article {
display: inline-block;
width: 33%;
}
and I want that they expand horizontally to fully occupy its row when clicked.
so I create an expanded class
.expanded {
position:absolute;
left:0px;
width: 100%;
}
and apply it on click
$("article").click(function(){
$(this).toggleClass("expanded");
});
I am almost there, as you can see in the fiddle here http://jsfiddle.net/aqw339r0/1/
When I click on any of the articles they expand to the full width of the row; but the problem is that when I click the first article of a row (except the first row) it "jumps" to the row immediately above.
I have tried changing the position and display attributes of both article and .expanded but I cannot get the behavior I need. For example: When I change the position:absolute of .expanded, the blocks 5 and 6, "jump" to the row below. Similar when I remove display:inline-block and change to float:left.
Do you have any ideas of why this happens and how to correct it?

Using the solution from #Rick (minus the css top edit) and then toggling an additional element to keep other elements in place, this should do what is needed: Fiddle
$("article").click(function() {
$(this).toggleClass("expanded");
if ($(this).hasClass("expanded"))
{
$(this).before("<article class='blank'> </article>");
}
else
{
$(this).prevAll('.blank').first().remove();
}
});
To explain further, when the element is clicked:
if ADDING the class 'expanded', then this will also add a blank article element (before) as a placeholder to keep the flow consistent. This is important because when the element with class 'expanded' becomes position: absolute it is removed from the normal flow of the content.
if REMOVING the class 'expanded', then this will also remove the blank article placeholder element. The prevAll function looks through all previous elements with the class 'blank' and then takes the first() one and removes it. Because it was inserted 'before', this is guaranteed to remove the correct blank article placeholder.

When position:absolute is set on an <article> element, that takes it out of the normal content flow, and causes the offset. We can correct it by adding an empty <article> as a placeholder when the click triggers, and removing it when click again.
var open = false;
jQuery("article").click(function () {
open = !open;
if (open) {
$(this).addClass("expanded");
$(this).before("<article class='holder'> </article>");
} else {
$("article").removeClass("expanded");
$(".holder").remove();
}
});
p.s. I'm not that good at jQuery, any suggestions are welcome.
jsfiddle

I can't think of a pure CSS solution, but since you're using jQuery anyway, simply hard-code the expanded element's top:
$("article").click(function() {
$(this).css('top', $(this).position().top);
$(this).toggleClass("expanded");
});
Fiddle
The top style will be ignored once the expanded class is removed.

Try this
<section>
<article>1</article>
<article>2</article>
<article>3</article>
</section>
<section>
<article>4</article>
<article>5</article>
<article>6</article>
<section>
<section>
<article>7</article>
<article>8</article>
<article>9</article>
</section>
section {
position:relative;
}
article {
width: 30%;
min-width: 200px;
min-height: 200px;
display: inline-block;
border: 1px solid black;
}
.expanded {
width: 100%;
background-color:#eef;
left:0px;
top:0;
position:absolute;
transition: 0.2s linear;
}
// if you want others to close while expanding
$("article").click(function(){
$('article').removeClass("expanded");
$(this).toggleClass("expanded");
});
// esle if you want everything to be expanded
$("article").click(function(){
$(this).toggleClass("expanded");
});

Related

Change image on click of mouse by passing class name from one element to the next

I have a situation where I want to change the background image when I click the mouse. I want to remove the class from one element and add the same class to the next element. Then based on that particular class name, I want to perform fadeIn and fadeOut using jquery. However, only the first image is changed when I use the class. When I click the second image, it wont change. But when I replace the class with div, background image changes on each click until it reaches the last image. Can anyone help me understand what I am missing. Thank you.
$(function(){
$("div").not(".active").hide();
$(".active").click(function(){ //When I change .active to div, it works.
$(this).fadeOut(function(){
$(this).removeClass("active");
$(this).next().addClass("active");
$(this).next().fadeIn()
})
})
})
body, html{
height: 100%;
width:100%;
background-color: yellow;
}
#one{
background:url("../Images/one.jpg") fixed center no-repeat;
width:100%;
height: 100%;
}
#two{
background:url("../Images/two.jpg");
width:100%;
height: 100%;
}
#three{
background:url("../Images/three.jpg");
width:100%;
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="one" class="active"></div>
<div id="two"></div>
<div id="three"></div>
</body>
You need to use on() instead of click() because you are adding the class dynamically.
$(function(){
$("div").not(".active").hide();
$("body").on('click', '.active', function(){ //When I change .active to div, it works.
$(this).fadeOut(function(){
$(this).removeClass("active");
$(this).next().addClass("active");
$(this).next().fadeIn()
})
})
})
Maybe you need to use .delegate
change your code like this:
$('body').delegate('.active', 'click', function() {
$(this).fadeOut(function() {
$(this).removeClass("active");
$(this).next().addClass("active");
$(this).next().fadeIn()
})
})
or you change bind the click on body to judge the e.target
see the details here delegate
You may do it like this:
first add specific class .bg-div to these divs because targeting ALL divs with this $("div") is so generic and it'll hide everything other than the active one, in case you have other divs they'll be hidden.
hide all divs with class .bg-div except the one which has .active.
on click event, you can still target bg-div div because there's only one which has .active class, since all other bgDivs are hidden already from the previous step. fadeOut() this one.
increase the counter index by one.
now if the value of index equals the length -number - of bgDivs, then reset the coutner to 0, this is for when you're showing the last bg-div.
fadeIn() the next div.
jsFiddle 1
$(function() {
var bgDivs = $(".bg-div"),
index = 0;
bgDivs.not(".active").hide();
bgDivs.on('click', function() {
$(this).fadeOut('fast');
index += 1;
// if the counter value is less than the number of bgDivs, keep this value
// else, set it to 0 and start over because we're on the last div
index = (index < bgDivs.length) ? index : 0;
$(bgDivs[index]).fadeIn('fast');
});
})
body,
html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
background-color: yellow;
}
.bg-div {
width: 100%;
height: 100%;
}
#one {
background: url("//dummyimage.com/1000x700?text=one") fixed center no-repeat;
background-size: cover;
}
#two {
background: url("//dummyimage.com/1000x700?text=two") fixed center no-repeat;
background-size: cover;
}
#three {
background: url("//dummyimage.com/1000x700?text=three") fixed center no-repeat;
background-size: cover;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
<div id="one" class="bg-div active"></div>
<div id="two" class="bg-div"></div>
<div id="three" class="bg-div"></div>
</body>
Update 1:
You'd notice there's a moment where the horizontal scrollbar appears when while switching the background div, this is because these divs are stacked under each others but when hidden there's no problem, the problem only appears the moment you switch the background div, to fix this add these lines to your .bg-div CSS:
position:absolute;
top:0;
left:0;
jsFiddle 2
Update 2:
You can totally get rid of .active class and don't rely on it if you add generic display:none; to your .bg-div CSS, then in the #one rule add display:block. by doing this you no more need this line:
bgDivs.not(".active").hide();
jsFiddle 3
This is useful not only because of less code, but also the background divs other than the first one will be hidden when the page first load from the beginning since it's in the CSS and not wait until your js script to hide them

JQuery - Darken contents of any element i hover over containing a certain class

I want to create a hover over event that darkens any element with the class "hover-change".
I don't want to simply change the background color of the triggered element because I want to darken everything (icons, text, background). A solution I have seen online is to overlay another div on top of the selected that is grey/transparent, and when you hover over/out the element, this overlay becomes visible/invisible.
This solution wont work because I dynamically create divs, and I want to attach this functionality to many different elements.
A high level example of what I expect would be nice solution would be:
$(".hover-change").on("mouseover",function(e) {
$(e.target).css( /*make entire element darker*/ );
});
$(".hover-change").on("mouseout",function(e) {
$(e.target).css( /*make entire element normal colour*/ );
});
I can't overlay a "hidden dark transparent pane" over EVERY element because I am dynamically creating the html with handlebars.
Thanks heaps to anyone that can help me out! :)
I can't overlay a "hidden dark transparent pane" over EVERY element because I am dynamically creating the html with handlebars.
Actually you can, just do it, dynamically.
for example:
$('.item').on("mouseover", function(){
$(this).append('<div class="overlay"></div>')
})
$('.item').on("mouseout", function(){
$('.overlay', this).remove();
})
.item {
display: inline-block;
position:relative;
border: 1px solid rgba(0,0,0,.125);
background-color: rgba(253,253,253,1);
margin: 2px;
width: 40px;
height: 40px;
text-align:center;
}
.overlay {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
background-color: rgba(0,0,0,.75);
width: 100%;
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item">
text
</div>
<div class="item">
text
</div>
<div class="item">
text
</div>
<div class="item">
text
</div>
This solution wont work because I dynamically create divs
So you may need to delegate the event.
You can make these changes.
$("body").on("mouseover",'.hover-change',function(e) {
$(e.target).css( /*make entire element darker*/ );
});
$("body").on("mouseout",'.hover-change',function(e) {
$(e.target).css( /*make entire element normal colour*/ );
});
$(document).on("mouseover",".hover-change",function(e) {
$(e.target).css( /* make entire element darker */ );
});
$(document).on("mouseout",".hover-change",function(e) {
$(e.target).css( /* make entire element normal colour */ );
});
This should work on all elements present in the DOM at the time of execution of this script, and also on any elements added in the future.

Hide portion of element offscreen and push & reveal on click

I'm building a responsive page that, when viewed on mobile, includes some popular behaviors.
I have an element that includes text and a link. The text portion needs to cover 100% of the width of the viewport and when clicked/tapped the link should push the text content left and reveal the link.
Fiddle: http://jsfiddle.net/Flignats/0n0fwm20/
HTML:
<div id="container">
<div id="block-one">
I'm a bunch of informational text.
</div>
<div id="block-two">
I'm a link!
</div>
</div>
CSS:
#container {
width: 100%;
height: 100px;
}
#block-one {
float: left;
width: 75%;
height: 100px;
background-color: #626366;
}
#block-two {
float: left;
width: 25%;
height: 100px;
background-color: #969696;
}
#block-two a {
color: blue;
}
How can I have block-one span the full width of the screen, block-two hidden off the screen, and, on click, animate (the margin?) block-two into view with block-one pushed to the left?
My apologies if I missed a clear example on site, most other questions were more complex.
I'd prefer not to build a jquery mobile page, though the push and reveal panels would accomplish this action. I'm also using Angular if nganimate is preferred over javascript.
Here is pure css solution: http://jsfiddle.net/3wcfggmf/
I've used trick with label and checkbox:checked to recognize if element is clicked or not.
input:checked + #block-one {
width: 75%;
}
If I didn't understand you correctly please let me know and I'll modify this PURE css solution for you :)
I forked your fiddle here with a working example: http://jsfiddle.net/90gm224q/
Added CSS to yours:
#container * { transition: width .4s; }
#container.clicked #block-one { width:25%; }
#container.clicked #block-two { width:75%; }
The JS:
var container = document.getElementById('container'),
link = document.getElementById('block-two').getElementsByTagName('a')[0];
link.onclick = function() {
container.className = 'clicked';
return false;
}
Assuming I understood your question correctly, you can play with the CSS values for width to achieve your desired effect.
You could accomplish this via CSS transistions and a JavaScript class toggle.
Demo - http://jsfiddle.net/Leh5t9t6/
In my demo, clicking #block-one toggles a class which fires the CSS transision. I included a pure JavaScript and jQuery version in the demo (you mentioned you'd prefer not use jQuery).
I also edited the styles slightly to accommodate the off-screen link.
Pure Javascript
var element = document.getElementById('block-one');
element.addEventListener('click', function () {
this.classList.toggle('reveal');
}, false);
jQuery
$('#block-one').on('click', function(){
$(this).toggleClass('reveal');
});

How to make a partially hidden div?

I want to make a half shown div in a page, like a footer. When I click it I want it to slide up. The div will contain information on it.
I achieved this somehow, but my problem is that the div does not get really hidden it just changes the position.
You can find the demo here: http://jsfiddle.net/8ZFMJ/394/
var clicked=false;
$(".two").on('click', function(){
if(clicked)
{
clicked=false;
$(".two").css({"bottom": -430});
}
else
{
clicked=true;
$(".two").css({"bottom": "-200px"});
}
});
I had a similar problem a while ago, in fact I think it was my first stackoverflow question. Unfortunately it got poorly received.
Anyway, the problem is currently that you are just changing the position of the div - that's what .bottom does. I think what you want to do is change the height, see this JSFiddle in which I managed to switch the div between states (no animation yet).
It makes simple use of css's overflow-y: hidden; to hide the div's contents when it is small, and all the JS does is toggle between heights:
if(clicked)
{
$(".two").css("height", 10);
}
else
{
$(".two").css("height", 250);
}
clicked = !clicked;
clicked = !clicked just flips the boolean state of the variable.
Now, to add the animation, we can use jQuery's .animate and produce this beautiful Fiddle
Basically, all we had to do in between is use animate instead of css. Simple, really.
TL;DR
final JSFiddle
.two must be absolute positioned inside .container that must be relative positioned. Then you just change the bottom with a negative value and that will hide the footer.
CSS:
html, body { height: 100%; }
.container {
position: relative;
height: 100%;
overflow: hidden;
}
.two {
position: absolute;
background-color: yellow;
width: 100%;
height:250px;
bottom: -200px;
transition: bottom 1s;
}
jQuery:
var clicked=false;
$(".two").on('click', function(){
if(clicked)
{
clicked=false;
$(".two").css({"bottom": "-200px"});
}
else
{
clicked=true;
$(".two").css({"bottom": 0});
}
});
http://jsfiddle.net/8ZFMJ/398/

How can I .slidetoggle a div the .length of a string in another div

I have a label where if you hover over it, it should expand the length of the text inside. I would like to slide the div next to it the width of the label (depending on the length of the word). Here is the JS Fiddle: http://jsfiddle.net/5s69j/1/
I want to use the .length to slide the div next to it because I don't want to hardcode it.
I ultimately want to have the title div visible at all times if there is a label or not. If there IS a label then I want the title to be to the right of the label at all times. If there ISN'T a label then I don't want space before the title, which is why I'm not using margin.
Here I'm trying to set a hover function on the labels to slide the title the length of label. And I think that I need something to calculate the length of a string. Let me know if I'm missing something obvious.
$(function(){
var stuff = $(".labels").length;
$('.labels').hover(function{
$(".title").slideToggle(stuff, function() {
});
});
});
Thank you so much!
Check this, here is solution without js
HTML
<div class="labels">
<div class="new"></div>
<div class="firstlabel">label label</div>
</div>
<div class="title">title goes here</div>`
* {
transition: all .5s ease;
}
.labels {
float: left;
overflow: hidden;
max-width: 20px;
color: #7cbf50;
background-color: #7cbf50;
}
.firstlabel {
white-space: nowrap;+
}
.labels:hover {
max-width: 500px;
}
.labels:hover .firstlabel {
color: #fff;
}
or see the following
http://jsfiddle.net/5s69j/8
JSFiddle - let me know if you want anything changed. You just needed to have them display: inline-block; and remove the absolute positioning.
DEMO Check this.
display:inline-block
Use the above. It ll solve your problem

Categories

Resources