jQuery: Slide animation goes to far, then "jumps" to the right height - javascript

I've seen a few questions about a similar issue, but I haven't found a solution that makes sense to me yet. The problem is on the JSFiddle here: http://jsfiddle.net/twchapman/EEXjR/2/
Click on Portfolio to see the behavior.
The functions I wrote:
function changeTab(tab) {
active = tab;
$("#" + tab).slideDown(animspeed);
}
function change(tab) {
if (tab == active) return;
$("#" + active).slideUp(animspeed, function () {
changeTab(tab);
});
}
I'm only using Chrome, but I'm pretty sure you'll get this error on any browser: when the page loads, it slides the content div down, and clicking the links (only Portfolio actually works at the moment) will slide the current div up, then the correct one down.
It's working almost completely as intended, but with one minor issue: when the animations begin, the div's height "jumps", and it's momentarily taller while the animation takes place, then "jumps" to the correct size when finished.
The two common solutions I've found have suggested: 1. Add a width to the style of the div, which already exists, and 2. change the height/margin parameters of the slide function when it's called. To me, the second solution seems like it shouldn't be necessary, as I don't provide any options other than an animation length.
I'm hoping this is just me missing something and being silly, not a big problem with the way I'm doing things.

The problem comes from padding which at times can make jQuery animations jittery.
A fast solution for your problem is to leave your Js untouched and use a natural box model for your layout.
In your css just include:
* { -webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
I really suggest to read this Paul Irish blog post and to include this code in all your projects.
Here's a working demo: http://jsfiddle.net/gleezer/EEXjR/3/

Update your js.
function change(tab) {
if(tab == active) return false;
console.log(tab);
console.log(active);
if($("#" + active).length){ //check element is exists.
$("#" + active).slideUp(animspeed, function() {changeTab(tab)})
}else{
changeTab(tab);
}
}

Related

How to prevent body from scrolling with push-side menu

I am trying to properly implement a push-side menu plugin (Responsive Menu) into a wordpress theme. Based on SO #Congrim answer, I've managed to achieve a way to lock the body at scroll when push-menu is open (with all the elements including the header fixed) except the interactive links class=edge-ils edge-ils-with-scroll edge-ils-light which will still go Up at push-menu open.
I've saved this sequence into congrim.js file, I've enqueued the script into the theme in functions.php file:
function lockScroll() {
if ($('body').hasClass('lock-scroll')) {
$('body').removeClass('lock-scroll');
}
else {
$('body').addClass('lock-scroll');
}
}
/* I've implemented `onclick="lockScroll();"` in button element,
* using this sequence in the same congrim.js file:
*/
$(document).ready(function() {
$('#responsive-menu-pro-button').click(function() {
lockScroll();
});
});
Removing the jQuery wrap will not give any error in browser console (tested in Chrome) may be still a bad approach to wrapp the code like this in wordpress (?)
In these conditions, unfortunately, overflow: hidden; doesn't apply, at push-side menu open, I can't use this class in CSS file/section:
.lock-scroll {
overflow: hidden;
}
The code will allow me to use only
.lock-scroll {
position: fixed;
}
The question:
Is there any possibility to force the code to implement overflow: hidden;* OR any other a workaround in order to have the interactive links class=edge-ils edge-ils-with-scroll edge-ils-light not going up at push-side menu open, to remain fixed at the position the viewer is clicked before opening the menu?
Please focus on the interactive links issue only, the rest of the scene is fine (header and the logo are in place like it should be, the background pictures are acting like it should as well).
LE: *overflow: hidden; it looks like will produce an unwanted body shifting effect at menu open/close, during the show/hide scrollbar, which is not happening in this stage.
LE2: congrim.js file has been replaced with body-lock.min.js by Outsource WordPress, please see the solution below.
Website testpage here.
Please check the solution given below.
Step 1: Add this CSS .scroll-lock{position:fixed !important;}.
Step 2: Add this JS.
$(document).ready(function() {
var windowTop = 0;
var menuOpen = 0;
var offsetContainerList = 0;
$('#responsive-menu-pro-button').click(function() {
var offsetScrollList = $('.edge-ils-item-link:first').offset().top;
if ($('html').hasClass('scroll-lock')) {
$('#responsive-menu-pro-container').one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",
function(event) {
if (menuOpen==0) {
menuOpen = 1;
$('html').removeClass('scroll-lock');
$('.edge-ils-content-table').css('top', eval(offsetContainerList)-40+'px'); //change image container top position
$('html').scrollTop(windowTop); //scroll to original position
}
else {
menuOpen = 0;
}
});
}
else {
windowTop = $(window).scrollTop();
offsetContainerList = $('.edge-ils-content-table').offset().top;
$('html').addClass('scroll-lock');
$('.edge-ils-content-table').css('top', -offsetScrollList + 'px'); //change image container top position
}
});
});
That's it!
Please add the below code in your custom js file .
jQuery('#responsive-menu-pro-button').click(function(){
var menu_active = jQuery(this).hasClass('is-active');
if(menu_active){
jQuery('body').css('position','fixed');
}else{
jQuery('body').css('position','static');
}
});
I hope it helps you.
Thanks
Your scroll isn't a natural navigator-based scroll, you have a JS somewhere swapping classes to emulate a scroll (edge-appeared,edge-up,edge-down).
On the push-side menu opening, these classes are reset, overflow-hidden won't change that.
You need to find which JavaScript is swapping those classes and prevent it from doing so, I'd be glad to be of further help but you have so many JS files that it would take quite some time to go through all of these. If you succeed in making a Minimal, Complete, and Verifiable example please post it here.

Flexslider breaks jQuery accordion [duplicate]

I have a test page to better explain my problem. I have several items on a list (they're images on the test page); when I click on one of them, a corresponding slideshow, using flexslider, sldes down.
The problem is that, on page load, the slideshow shows all slides at once, at a much smaller size than intended. But then, if I switch the focus from the window (i.e. switch between browser tabs or move to another program and come back), the slideshow is now working and the slides are the proper size. This happens in mobile devices too.
When I check with firebug, there's an element.style rule applying to ul.slides:
transform: translate3d(-89px, 0px, 0px);
Which hides one of the slides. Additionally, there's another rule for the list items inside ul.slides that gives them their initial width, which is not even the same for all sliders so I don't understand where it is coming from.
Can someone take a look and suggest a fix? I've tried overriding the element.style rule but so far unsuccessfully.
I think I've figured it out, in principal at least...
.flexslider{display:none;} seems throw off the re-size function of Flexslider.
You could just remove it, but that makes for some ugly loading.
To avoid said ugly loading I put together a quick, work-around- jsFiddle
$(document).ready(function(){
$(".flexslider").css('display','block').slideUp();
});
There's a still a quick glitch while loading, but hopefully it will at least steer you in the right direction.
Another method I played with a bit was to try and force the re-size function like so-
$(".client").click(function () {
$('.flexslider').resize(); // Problematic but promising
var project = this.id;
var project_id = '#' + project + '-project';
var elem = $(".flexslider:visible").length ? $(".flexslider:visible"): $(".flexslider:first");
elem.slideUp('slow', function () {
$(project_id).slideDown('slow');
});
});
This sort of solved the mini-picture issue, but was spotty at best.

Issue with jQuery .fadeIn() queue

I'm having a strange issue with jQuery and a fading loop. Let's see a bit of code (here on JSFiddle: http://jsfiddle.net/4fcvze4m/1/):
$('.spin-block').each(function(index) {
$(this).delay(index * 200 + 800).fadeIn();
})
.spin-block {
display: none;
margin: 5px;
padding: 10px;
background: #a00000;
color: #fff;
}
<div class="spin-block">1</div>
<div class="spin-block">2</div>
<div class="spin-block">3</div>
<div class="spin-block">4</div>
<div class="spin-block">5</div>
<div class="spin-block">6</div>
<div class="spin-block">7</div>
<div class="spin-block">8</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
That's basically it.
So, sometimes (it's very random), one of this block don't show up, Mostly 5th or 6th. It can work perfectly 30 times a row and have this issue on the next refresh. I tried a workaround with this :
$('.spin-block')
.each(function(index) {
$(this).delay(index * 200 + 800).fadeIn();
})
.promise().done(function() {
console.log('debug');
$(this).fadeIn();
});
When everything is ok, the 'debug' log show off, but when there's one missing, the console remain empty, even if next .spin-block appears. And if i force some blocks not to show, then this workaround nicely works and fade in the remaining ones (after the end of the animation, but i don't care) :
var i = 800;
$('.spin-block')
.each(function() {
i += 200;
if (i > 1400) {
$(this).delay(i).fadeIn();
}
})
.promise().done(function() {
console.log('debug');
$(this).fadeIn();
});
There it is. Have you any idea of what's going on ? It's totally random, on any browser as far as i tested. Thank you!
Please note: This is not happening on the Fiddle I posted. I know it comes from my own JS file, but I don't have the possibility to put everything here. Besides, this is pretty much the first thing that happen in my init function.
I believe, the issue you are facing is due to the class of Divs being altered dynamically during run-time and the asynchronous nature of how jQuery animations work.
This JSFiddle explains the same. Essentially, it is the same set of Divs you had created initially. But instead of just animating them (iterating through $.each), I am introducing one more statement after the $.each which will remove the class associated with one of the Divs. See code below:
$(function () {
$('.spin-block').each(function (index) {
$(this).delay(index * 200 + 800).fadeIn(1000, fnCallback(index));
});
//Removing class dynamically for div 5 alone.
$('.spin-block').eq(4).removeClass('spin-block');
});
You would expect this to animate all Divs and then removeClass from the 5th Div. But what really happens is, animation starts, simultaneously Class "spin-block" is removed from Div 5, thus blocking Div5 from being animated!

How to have a div scrolled to the bottom automatically

I am making a chat-like interface which can be seen here (best viewed in Chrome right now):
http://qas.im/web/sms.php
The temporary username:password is temp_guest:password
My problem is that when you click one of the chats, it doesnt automatically scroll to the bottom when I use this code:
$(".messages").attr({ scrollTop: $(".messages").attr("scrollHeight") });
What could be wrong? The messages div has a css of:
.messages {
height:400px;
overflow: auto;
}
For people who are wondering: Page isnt HTML validated yet but I will be cleaning it up soon. Most of the page is auto-generated which is challenging to make the code look pretty ;P
If you are using jQuery 1.6 or later, use prop instead of attr.
Working example: http://jsfiddle.net/FishBasketGordo/PNwj3/
I found two issues.
The first is that you were trying to set all .message DIVs to the height of the first DIV, so if the first DIV was hidden, it would never work.
The second was that jQuery's attr function is only for node attributes.
This method works better, and scrolls all the divs correctly:
$(".messages").each(function(idx, node) { node.scrollTop = node.scrollHeight; });
Alternatively, you can improve performance by using this selector:
$(".messages:visible").each(function(idx, node) { node.scrollTop = node.scrollHeight; });
Which works on visible message nodes.

jCarousel with unknown content width

I am trying to use jCarousel plugin for jQuery in order to provide my website users with scrollable (horizontal) content.
The content I am mentioning is basically user defined <li> elements, styled so that they have a feel and look of a tab. so basically I am trying to achieve the same effect of the tabs in pageflakes.com. As you may imagine, the users are creating tabs and providing tab names by themselves..
jCarousel needs you to specify a fixed width for the content e.g., all their examples are based upon images that have fixed height and width. but in my case I have not control over what the user will name his/her tab...making it impossible for me to guess the width of the total container div.
I have tried using a silly method such as guessing the width programatically assuming each letter being approx 5 pixels and multiplying 5 with the length of the word they have given as a name for a tab. even in this case, i needed to manipulate the css file dynamically which I am not sure how to do and even if it is feasable to do so..
Any solutions appreciated...
<lu>
<li class='MyTab' id='578'>This is my tab</li>
<li class='MyTab' id='579'>of which I can</li>
<li class='MyTab' id='580'>never guess</li>
<li class='MyTab' id='581'><img src='img/bullet_key.png' /> The length of</li>
</lu>
The above html is produced programatically through ajax_tabs_output.aspx, loaded into a javascript array and the jCarousel takes care of the rest..
function outputTabsArray() {
$.ajax({
url: 'ajax_tabs_output.aspx',
type: 'get',
data: 'q=array',
async: false,
success: function(out)
{
tabs_array = out;
}
});
}// end outputTabsArray
function mycarousel_itemLoadCallback(carousel, state)
{
for (var i = carousel.first; i <= carousel.last; i++) {
if (carousel.has(i)) {
continue;
}
if (i > tabs_array.length) {
break;
}
carousel.add(i, mycarousel_getItemHTML(tabs_array[i-1]));
}
};
/**
* Item html creation helper.
*/
function mycarousel_getItemHTML(item)
{
return '<div class="MyTab" id="' + item.tab_id + "'>" + item.tab_name + '</div>';
};
$('#mycarousel').jcarousel({
size: tabs_array.length,
itemLoadCallback: {onBeforeAnimation: mycarousel_itemLoadCallback}
});
The closest thing to what you want is probably jscrollhorizontalpane. I've never used it so I can't vouch for it's effectiveness as a solution to this specific problem.
This sort of widget shouldn't be to hard to make if you want to attempt it. I'll break down the approximate method I would use:
Make sure to use plenty of wrappers.
<div class="scrollable">
<div class="window">
<div class="space">
<ul class="tabs">
<li class="tab">...</li>
<li class="tab">...</li>
<li class="tab">...</li>
</ul>
</div>
</div>
←
→
</div>
What we'll be doing is shifting the "space" element back and forth inside "window" element. This can be done by setting position:relative to "window" and position:absolute to "space" and then shift it about using left:-??px, but I'll use the scrollLeft property.
Add some CSS.
.window {
overflow : hidden;
width : 100%;
}
.space {
width : 999em; /* lots of space for tabs */
overflow : hidden; /* clear floats */
}
.tabs {
float : left; /* shrink so we can determine tabs width */
}
.tab {
float : left; /* line tabs up */
}
This is just the basic stuff that the technique needs. Some of this stuff could be applied by jQuery,
Add events to window resize.
$(window)
.resize(function () {
var sz = $('.window');
var ul = sz.find('ul');
if ( sz.width() < ul.width() ) {
$('.scrollable a.left, .scrollable a.right').show();
}
else {
$('.scrollable a.left, .scrollable a.right').hide();
}
})
.trigger('resize');
Add events to scroll buttons.
$('.scrollable a.left').hover(
function (e) {
var sz = $('.window');
sz.animate({ scrollLeft : 0 }, 1000, 'linear');
},
function (e) {
$('.window').stop();
});
$('.scrollable a.right').hover(
function (e) {
var sz = $('.window');
var margin = sz.find('ul').width() - sz.width();
sz.animate({ scrollLeft : margin }, 1000, 'linear');
},
function (e) {
$('.window').stop();
});
Done!
The widths could also be calculated by looping through the "tab" elements and summing upp outerWidth. This is unnecessary if you have full control but might be a better choice for a full standalone plugin.
From what I can tell, you're trying make JCarousel do something it was never designed to do. Based on what I read on the JCarousel website it appears to be an image rotator.
What it sounds like you want is a tabbed interface. See JQuery UI Tabs for a demo and documentation on how to implement it.
If I'm totally wrong and all you're looking for is a tutorial on how to do proper CSS tabs, have a look at:
http://unraveled.com/projects/css_tabs/
Soviut,
You are actually quite right! I am trying to make JCarousel do something it wasn't designed for.
However, I also wouldn't like to use a tab plugin or any similar stuf as I NEED FULL CONTROL over my output. Such as injecting more elements into the tabs when needed such as double clicking, loading and many other etc. etc.
Actually what I am looking for a way to scroll horizontally the content within a div with arrows on the left and right.. To be more precise, I need the exact same structure of the tabs seen in www.pageflakes.com
The user will be able to create tabs by clicking on a link (or any other element for that matter), they will be able to inline edit its name, whenever they have more tabs then the length of the div, the buttons will be visible allowing them to slide inside the div, I will have events bound to their load, click and double click events.
To summarize I have everything ready and working except for the sliding/scrolling part. Its only I have to get help from you guys regarding how to achieve this functionality..
Kind regards,
What you're looking for isn't tabs, but draggable panels. One example can be found here, called JQuery Portlets. The related blog entry about Portlets can be found here.
You may also want to look into JQuery UI's Draggable, Droppable, and Sortable plugins.

Categories