I'm playing around with a little jquery animation and trying to achieve a very specific effect.
If anyone remembers the old Xbox menus with the panes or 'blades' as they called them, I'm going for something like that using a series of left floating divs. When the page loads, one pane is active and has a large width, displays some information etc. while the other panes are condensed into a very small width. When a smaller pane is clicked on the active pane shrinks to a narrow width, and the clicked expands to display content.
Essentially the HTML looks like this:
<div class="pane active">
</div>
<div class="pane">
</div>
<div class="pane">
</div>
I'm currently using javascript (jquery) to define all the widths based on the window size so that the panes fill up the whole screen.
Here is the basic jquery event that handles the shrinking and expanding.
// $active is the current wide pane
// $(this) is the clicked pane
// activeWidth is a predefined constant
$active.animate( { 'width' : '100px' }, 200 );
$(this).animate( { 'width' : activeWidth }, 200);
The only problem I am having is occasionally during this animation, the shrink/grow appear to start at different times (I'm not sure) and create an unpleasant empty space to the far right of the page.
Is there a way to ensure that these two actions happen consistantly in sync? I considered replicating this using absolute positioning.
I'm at work so I can't upload a diagram, but I will try to later if it's too confusing.
The jQuery documentation says there's a callback function in the animate parameters. "This can be useful for stringing different animations together in sequence."
Not sure I'm 100% understanding your question, and without seeing more of your code, can you do something like:
$active.animate( { 'width' : '100px' }, 200, function(){
$(this).animate( { 'width' : activeWidth }, 200);
});
Related
How can I check (with jquery or vanilla js) that all images on a page are loaded, and that they have been rendered at their final, full height, and that their parent elements have adjusted to that height?
I'm implementing a scrollspy function using jquery - something that determines where a user is on a page and highlights their position in a nav, updating their position as they scroll. In order for this to work properly, I need to know the offset.top of each section on the page I want to spy on. If I calculate the offset.top too early, before all images are loaded and displaying at their full height, the offset().top calculation will be incorrect. I want to avoid running the offset().top calculation too many times.
Things i've tried that don't fulfill my needs:
$(document).ready() and $(window).onload() are both too early, as images may not have been rendered at their full height, therefore making the sections not rendered at their full height.
the imagesLoaded library. same problem as above, doesn't account for rendering of images to their full height.
Based on my experience I think it's not trivial. window.onload may help, but it's not reliable when images are loaded dynamically. In the past I was using some kind of hack to make it workable. Basically, I was using window.setInterval and checking if image is really available by looking at property naturalWidth (see: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement).
Here is an example of implementation: https://jsfiddle.net/yu8zr20h/
You are solving this issue in an incorrect way. You need to compare the current Y-value of the users window to the Y-value of all the components, or at least the containers containing the different nav values.
Imagine this is your html-code:
<div id="firstContainer">
<!-- Some content -->
</div>
<div id="secondContainer">
<!-- Some other content -->
</div>
Now you can check the height relative to the complete html page using
document.gelElementBtId('element-id').offsetTop
and the current height of the user using
scrollY
More information using this JSFiddle.
If you have image size metadata (e.g. Rails Active Storage provide it out of the box), you can write height to say dataset:
<img id="image" data-height="700" src="image.jpg" />
Then wait for it to be rendered (watch natural height):
let timer;
let image = document.getElementById("image");
function waitImage() {
if (image.naturalHeight < image.dataset.height) {
timer = setTimeout(function(){
showItems();
}, 300);
} else {
clearTimeout(timer);
useYourFullyRenderedImage();
}
}
I was wondering, for all you javascript and jquery guru's what would be my best way to tackle this problem. What I have is a navigation that is hidden via CSS to the bottom of the screen. I've managed to have it working as a toggle fine - which you can see here http://jsfiddle.net/olichalmers/Lby7vfdf/.
var body = $("body"); $("#menuBtn").click(function() {
body.toggleClass("showMenu");});
This obviously means that the menu slides up and down.
What my problem is is that I want to animate the menu up on the initial click, and then when you click the button again to close it I want the navigation window to slide up. Then when you click it again to open it, it is appearing from the bottom again. I've been trying to get my head around how this would work and what I think is that it would be two classes (one for hide menu, and one for show menu) which would be added and removed from the body. I have a jsfiddle here http://jsfiddle.net/olichalmers/twqd2yj0/
var body = $("body"); $("#menuBtn").click(function() {
if (body.hasClass("hideMenu")) {
body.removeClass("hideMenu").addClass("showMenu");
}
else if (body.hasClass("showMenu")) {
body.removeClass("showMenu").addClass("hideMenu");
}});
This is probably shocking in it's attempt to come to a solution to this problem. I'm using jquery but maybe it is a javascript solution using an event listener that is needed here? My jquery and javascript knowledge is patchy at best as i'm still in the midst of learning so please go easy if I appear very dumb!
Hope i've been clear enough. Thanks.
May I suggest a different approach?
Create your bottom menu in a separate DIV, located at very top of your HTML (directly under BODY tag). Make that DIV position: fixed -- that takes it out of the "flow" and positions it relative ot the viewport (the screen), not to any other divs or to the web page itself. Now, you can move it up/down based on some trigger.
Here is a code example:
jsFiddle Demo
HTML:
<div id="botttrig"></div>
<div id="bottmenu">The menu is here</div>
<div id="wrap">
<div id="content">
<p>Content goes here</p>
<p>Hover over small box at bottom left</p>
</div>
</div>
jQuery:
$('#botttrig').hover(
function(){
$(this).fadeOut();
$('#bottmenu').animate({
'bottom': '0px'
},500);
},
function(){
//do nothing on hover out
}
);
$('#bottmenu').hover(
function(){
//do nothing on hover in
},
function(){
$('#bottmenu').animate({
'bottom': '-80px'
},500);
$('#botttrig').fadeIn();
}
);
See this jsFiddle for another example. I removed the trigger box, and left the top 10px of the menu visible at screen bottom. Upon hover, slide the menu up. You may wish to increase the z-index on the #bottmenu div to always display it above the other DIVs on the page, so that it is always visible.
http://jsfiddle.net/twqd2yj0/4/
I've used slideToggle() and added display:none; to #navHold
So I have an interesting problem. I currently have a grid of four block elements, and I would like to enable some behavior to cause the div to grow when clicked on. The catch is, I am trying to animate it to the top level of the page, aka, I don't want it to dislocate the position of the other divs on the page.
It's difficult to explain, but I want it to kind of be like a modal window with the open animation originating from the element's location. Like a popup when it's clicked. Right now I am trying to do this in the click function:
$( "#cell" ).animate({
height:600, width:600, position:'fixed'
}, 1000, "linear", function(){ alert("all done"); });
This animates it bigger, but I was hoping to make it like an overlay. Has anyone seen anything like this, or a plugin that accomplishes this before?
Clone the element, absolutely position it over the original and animate the copy.
Press "Add to cart" and see this in action:
http://toys.scholarschoice.ca/products/Active-Play-536/12-Years-Old-Up-563/RipStik-Caster-Board-Silver-p46490/pstart1/
I tried to implement the idea of cloning and animate the clone..
See my DEMO
The bunch of code does seem to work, only thing is that the transition is not very smooth. Any Idea how to tweak up the code to make the effect more smooth? and also, when the image enlarges, all the content below and beside the image seems to be pushed away to make room for the enlargement, any idea how I can stop this and just make the image overlap the content around it on enlargement? Also, instead of inserting that code for each image every time I upload a new image and want that effect, how do I make the javascript code automatically apply to the new image instead of manually applying the javascript to it each time? Finally, how do I use this on videos/widgets instead of just images? (I’m using Dreamweaver CS5).
$("img").each(function() {
$.data(this, 'size', { width: $(this).width(), height: $(this).height() });
}).hover(function() {
$(this).stop().animate({ height: $.data(this,'size').height*1.2,
width: $.data(this,'size').width*1.2 });
}, function() {
$(this).stop().animate({ height: $.data(this,'size').height,
width: $.data(this,'size').width });
});
If you want the image to overlap any surrounding elements upon resize you will have to play with the CSS to position the element either relative, absolute, or fixed, then set the z-index of the image to a value higher than the surrounding elements.
Sounds maybe like you should look into a jQuery Lightbox plugin. As for the specific issue with the enlarged image pushing your content around, it needs to be removed from the document flow (using position attribute)... but that's just the tip of an iceberg. There's a lot of moving parts to the task you're trying to achieve, that's why using an existing javascript plugin would be best - IMO, of course.
You might want to check out http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/ and also http://line25.com/articles/rounding-up-the-top-10-jquery-lightbox-scripts .
I realize there's already been several questions like this, but I think my case is a little different.
I have an div that I am absolutely positioning and floating on top of the page, and I'm setting an overlay behind it to grey out the rest of the page. I have it working okay until you scroll up and down the page.
The problem is, when the div appears, it is still populating with ajax data. So the height and width of the bg overlay has already been set, but once all the data loads into the floating div, it sometimes pushing the page down so the height increases. So, I can't calculate the height and width of the window or document because the floating div might not be fully loaded yet, and once it does, it pushes the screen down further, causing the bg overlay to not cover the whole page.
So for example, in the code it's going something like:
loadBoxContent = function(){
..DO AJAX HERE..
..PUT CONTENT INTO FLOATING DIV..
$('#floatDiv').show()
$('#darkOverlay').height($(window).height());
}
I verified this by adding an alert, so that by the time I've clicked the alert, the bg overlay was able to calculate the true page size, and it looks fine.
Sorry, if this sounds confusing but hopefully you get what I'm trying to achieve. I'm assuming this isn't too difficult, but I haven't been able to figure it out.
Any help would be appreciated, I'm using jquery.
Thanks
Overlay ;)
** update, setting position of all corners to 0 instead of using width/height 100% **
$("<div/>")
.css({
position:"fixed", // ze trick
background:"#000",
opacity:.5,
top:0,
bottom: 0,
left:0,
right: 0,
zIndex: 2999 // everything you want on top, gets higher z-index
})
.appendTo("body");
Or put the above css settings in a css stylesheet (opacity needs cross browser hacks).
$("#dark-overlay").show();
Here is the solution :
JQuery Show Loading Plugin
Don't try to invent the wheel !!!
Here is a demo :
Loading Demo
Now you just need to create a main container div for your page and just ask this simple plugin to do it for you.
Maybe you want to read the plugin source and find how it works...