I have written this function to create a "reveal more" functionality for a card style layout. I originally wrote it to all be within a click function but then the scope changed and I needed to move the commands into their own function, and now the animation is very stuttery to more to ignore. I have a feeling that it has to do with the variable updating while animating and causing a conflict but I'm not sure how to bypass that or to set the variable as a constant after taking one height.
//This function removes the reveal more trigger and slides "new-deals" down to auto height
function revealMore() {
var containerHt = $("#new-deals").children().height; //set animation height for "reveal more" function
//Reveal More function which handles animating container height to that of contained elements and removes the reveal more trigger element
if (($("#new-deals").height) >= containerHt) {
$("#new-deals").animate({height: containerHt}, 400, function() {
$("#new-deals").css({height: 'auto'});
});
$("#new-deals").siblings('.reveal-more').remove();
}
}
$(".reveal-more a").click( function() {
revealMore();
return false;
});
There are a number of things:
Save your $("#new-deals") in a variable.
Use CSS Animations rather than jquery's animate
Use the tranzlateZ(0) hack (if you aren't using a lot of VRAM already).
Check out html5rocks for enlightenment.
Related
I'm using a tiny library called '$.scrollTo' to animate a scroll to a div element in my html. at the top of my page I have a fixed navgation bar.
at the end of the animation, I would like to have that div focused (for accessibility). if my div is to large, at the end of the animation, the fact that it gets focus - simply sends it a bit off the screen.
This does not happen with small divs.
here is my code (check jsfiddle below):
$('#buttonid').on("click", function() {
//fixed nav bar height (to compensate when scrolling)
var fixed_navbar_height = $("#navbar-id").height();
//the element to scroll to
var $go_to_selector = $("#topic2");
$.scrollTo($go_to_selector, {
duration: 1000,
offset: -fixed_navbar_height,
onAfter: function() {
//if you comment out this .focus it works as intended.
$go_to_selector.focus();
}
});
});
here is a JSFIDDLE example:
https://jsfiddle.net/dy35obpq/3/
obviously the onAfter messes it up, but i would like both the animation and the focus. Any ideas on how to implement a focus on a large div without letting it change the scroll bar ? suggestions are more than welcome.
Try this.
onAfter: function() {
$go_to_selector.focus();
$(window).scrollTop($($go_to_selector).offset().top - fixed_navbar_height);
}
I have simply added this line in your onAfter callback.
$(window).scrollTop($($go_to_selector).offset().top - fixed_navbar_height);
and it seems to have fixed the problem while still retaining focus. You might want to use css to disable the focus blue highlight.
I find that when I update a div's overflow-y property to scroll the change happens only for a moment (I can just barely see the scroll var flicker in and out), and then the div reverts to its original overflow-y: hidden status.
Here's the code. First, I create a bunch of div elements like so:
$('#toAppend').append("<div id = '"+divName+"' class = 'unselected' style = 'overflow-x:hidden; overflow-y:hidden; float:left;'></div>");
Later on, when a div is clicked, I want to expand it and add a scroll bar so I use the following in click():
div.css("overflow-y", "scroll");
When I then click on a div, I very fleetingly see the scroll bar and then it disappears. There is no other css or jQuery touching this overflow-y property. Why doesn't the change remain?
Working example here.
Here's what I've tried to trouble-shoot:
I already have CSS classes that correspond to the selected and unselected states that regulate scrolling, so I tried adjusting overflow-y to scroll vs hidden. This also did not show any results.
Even though jQuery can use overflow-y I also tried calling css("overflowY"... using camel case. This also made no difference.
There aren't any error messages in the browser, and all other related updates for click events are happening.
Here is a larger code sample covering most of what is done:
$(document).ready(function(){
// set up sizing variables
width = $('#toAppend').width()*.9;
height = $('#toAppend').height()*.9;
widthPer = width/pageArray.length;
heightPer = height*.2;
// generate 1 div for each element in pageArray
for(i = 1; i <= pageArray.length; i++){
var divName = "div_"+i
$('#toAppend').append("<div id = '"+divName+"' class = 'unselected' style = 'overflow-x:hidden; overflow-y:hidden; float:left;'></div>");
$("#"+divName).load(pageArray[i-1]).css("width", Math.round(widthPer*PORTION_DIV)).css("height", heightPer).css("background-color", COLORS[i-1])
.css('cursor', 'pointer').css("border-radius", BORDER_RADIUS)
// expand div user clicks on and collapse other sections
.click(function(event){
var div = "#div_"+event.currentTarget.id.slice(-1);
if($(div).hasClass("unselected") || $(div).hasClass("almostSelected")){
var shrinkString = ""
var widthPerSmall = Math.round((1-MULTIPLE_TO)*width/(pageArray.length - 1));
var divToShrink = "";
// generate string of all divs other than selected one to shrink them down simultaneously
for(ii = 1; ii <= pageArray.length; ii++){
if(ii !== Number(event.currentTarget.id.slice(-1))){
var divShrink = "#div_"+ii;
shrinkString = shrinkString + divShrink +", " ;
if($(divShrink).hasClass("selected")){
divToShrink = divShrink;
$(divToShrink).switchClass("selected", "unselected", SHORT_TIME)
}
}
}
// shrink elements in a given order with nested callbacks
shrinkString = shrinkString.slice(0, -2);
$(shrinkString)
.animate({ width: widthPerSmall, height: heightPer}, LONG_TIME, function(){
$(div).animate({width: Math.round(MULTIPLE_TO*width), height: height}, LONG_TIME, function(){
if(divToShrink.length > 1){
toShrink = divToShrink.slice(-1)
$(divToShrink).load(pageArray[toShrink-1])
.css("background-color", COLORS[toShrink-1])
}
})
.switchClass(["unselected", "almostSelected"], "selected", LONG_TIME)
.load(longPageArray[Number(event.currentTarget.id.slice(-1))-1 ]).attr("class", "selected")
.css("background-color", "white").css("border", BORDER+COLORS[Number(event.currentTarget.id.slice(-1))-1])
.css("overflow-y", "scroll");
})
// this should be called only for first click, when no elements are yet selected
if(divToShrink.length < 1) $(div).animate({width: Math.round(MULTIPLE_TO*width), height: height}, LONG_TIME).switchClass(["unselected", "almostSelected"], "selected", LONG_TIME).load(longPageArray[Number(event.curren\
tTarget.id.slice(-1))-1 ]).attr("class", "selected").css("background-color", "white").css("border", BORDER+COLORS[Number(event.currentTarget.id.slice(-1))-1]).css("overflow-y", "scroll");
}
})
}
You need to apply your css in the callback of your animate function for expanding divs, instead of chaining it after animate() is called like you are currently doing. Chaining jQuery animation methods adds those functions to the fx queue, but non-animated methods like css() do not get added to that queue. Instead they are fired immediately. Taking a peek at the jQuery source you can see that when animating elements, jQuery changes the overflow to hidden and then changes it back to what it thinks the original overflow properties are when it is done with the animation. In this case, because of the async chain, jQuery goes with its original inline style instead of the one set in chained css() method. As a rule of thumb, if you are calling any jQuery method that is not an animation, don't chain it but put it in the callback.
The relevant block of code needs to be changed to this:
$(div).animate({width: Math.round(MULTIPLE_TO*width),height: height},
LONG_TIME,
function(){
if(divToShrink.length > 1){
toShrink = divToShrink.slice(-1)
$(divToShrink).load(pageArray[toShrink-1])
.css("background-color", COLORS[toShrink-1])
}
//APPLY THIS IN CALLBACK
$(this).css("overflow-y", "scroll");
})
Working fiddle
While jQuery will change the overflow to hidden for the animation, as you found out originally, by chaining that method you actually can override that for the duration of the animation. So if that is important to you, you can continue chaining the method and add it to the callback. It looks like in your particular instance, there is a conflict with the other animation method that would cause the overflow to revert to hidden for its duration, so the overflow will flicker. So that's up to you whether you include both or just keep the one call in the callback of animated methods.
Also as a side note, I noticed that you always chain your jquery css() functions on the same elements. You know you can save all properties as an object and just pass that in as a parameter to save yourself all of those function calls?
I have I div or some other element which I load content into with:
$('#my_div').load('ajax.php',function(){
//Do random stuff.
}
However the height of the div will then change, causing the page to jump up and down, looking ugly.
Is there a way for it to animate the height when the new content is loaded or changed? I know one can do this with FluidMoveBehavior in C#.
How can I achieve the same effect with Javascript/jQuery?
Here's some Fiddle
When you want to create a height or width animation with jQuery you have to set a number indicating the desired size. I assume that you use height: auto in this case so you have to find a little workarround.
Get the height:
var autoHeight = $("#content").height("auto").height();
Animate to autoHeight:
$("#content").animate({height: autoHeight}, 1000);
And together:
var currentHeight = $("#content").height();
var autoHeight = $("#content").height("auto").height();
$("#content").height(currentHeight);
$("#content").animate({height: autoHeight}, 1000);
Stolen from here
What I do is the opposite. I animate the page to scroll to the top if not already BEFORE I call the load.
So that the top of any new dynamic content is always in view.
I know this isn't the answer you were looking for, but I've found it works best.
You could hide #my_div before the load(), and then slideDown() in the complete function:
$('#my_div').hide().load('ajax.php', function() {
$(this).slideDown();
});
Or, create a temporary element, hide it, append it, use its height to animate #my_div once the load is complete, and then remove it.
$('<span/>').hide().appendTo('body').load('ajax.php', function(text) {
$('#my_div').animate({ height: $(this).height() }, '800').html(text);
$(this).remove();
});
$(".carousel-inner img").load(function(){
var pic_height = $(this).height();
var should_height = $(this).parents('.item').height();
var pad = (should_height - pic_height ) / 2;
$(this).css('margin-top',pad);
});
This function uses javascript to vertically center the image to its parent div.
I tried doing this immediately after .carousel(). However, I realize that only the first image gets vertically centered, and the rest of them get screwed up because the images haven't "loaded" yet (therefore making pic_height 0).
My solution is to call this function immediately after the carousel goes to the next slide.
However, I'm unfamiliar with the bootstrap javascript file. Where do I add this function? How do I make it trigger this function?
I do not want a css solution. Because of my requirements in css, a pure css solution will not work. (I have tried every trick in the book for pure css vertical align, but my situation won't work.)
I think you could position each images on dom ready like this :
$(".carousel-inner img").each(function(i, e){
var pic_height = $(e).height();
var should_height = $(e).parents('.item').height();
var pad = (should_height - pic_height ) / 2;
$(e).css('margin-top',pad);
});
If you want to trigger it on slide, bootstrap carousel provides the following events :
slide : This event fires immediately when the slide instance method is
invoked.
slid : This event is fired when the carousel has completed its slide transition.
Translated to jQuery it'll be :
$('.carousel').on('slide', function(e) { /* your code */ });
See the effect in the photos in the article here:
http://www.popsci.com/science/article/2012-11/and-after-images-show-hurricane-sandys-devastation
Does anyone have any idea how that's done? I suppose I could make two frames with adjustable width within a fixed frame, but what about the handle? And the way the frame line and handle brighten and enlarge when you mouse over? Hover event, to be sure, but what kind of hover event?
It is very simple. You have 2 DIVs with the 2 different images (as background-image in css) overlapping eachother (In e.g absolute positioning.) (Perhaps the "Before" picture above)
Then you have a slider and when dragged it decreases the overlapping DIV's width, making the underlaying DIV show!
This functionallity can be found in a jQuery plugin called "Before/After"
Link: jQuery BEFORE / AFTER
You could of course just write your own that isn't dependant on jQuery UI.
;(function($){
$.fn.slidingThingamajig = function () {
return this.each(function(){
var $this = $(this);
$this.find('.handle')
.css({cursor:'ew-resize'}) // Here's your fancy cursor with directional arrows
.on('mousedown', function(e) {
$this.addClass('resizable');
$this.parents().on('mousemove', function (e) {
$('.resizable').css({width:e.pageX - $('.resizable').offset().left});
}).on('mouseup', function(e) {
$('.resizable').removeClass('resizable');
});
e.preventDefault();
});
});
}
})(jQuery);
You would probably need to tweak this a little, but it's mostly all there.