How can I ensure this CSS transition animates - javascript

I have an image carousel built using knockout & jquery.
To animate the slides I really want to use CSS transitions and NOT jquery animate.
I have this nearly working but I have an issue.
In the code below, the 'slideRight' part doesn't work, however the else part works fine. What's happening is the transition to margin-left 0 is being skipped, even though the transition class has been added.
if (slideRight) {
$(requestedElement).insertBefore(currentElement);
slideContainer.css('margin-left', -$(self.carousel).width());
slideContainer.addClass('transition');
slideContainer.css('margin-left', 0);
} else {
$(requestedElement).insertAfter(currentElement);
slideContainer.addClass('transition');
slideContainer.css('margin-left', -$(self.carousel).width());
}
I've created a JSFiddle here: http://jsfiddle.net/vnw57nx0/2/
As you'll see in the fiddle, the carousel transitions nicely between slides going right to left.
But if you find this line in the javascript:
self.setIndex(self.currentIndex() + 1);
and change it to:
self.setIndex(self.currentIndex() - 1);
the slides should cycle in reverse.
They do, but they're not being animated.
Interestingly, if I debug the script and step through it works fine.
This made me think it was a timing issue and maybe I need to use a callback function but jquery .insertBefore, .css and .addClass are all synchronous.
Any ideas how I can fix this code that works if I debug but doesn't if I don't?

It seems that the browser doesn't make a transition when you revert a style value within the same context. You need to do it in a new context using something like setTimeout:
if (slideRight) {
$(requestedElement).insertBefore(currentElement);
slideContainer.css('margin-left', -$(self.carousel).width());
setTimeout(function() {
slideContainer.addClass('transition');
slideContainer.css('margin-left', 0);
});
} else {
http://jsfiddle.net/vnw57nx0/3/
I found this question because of the Knockout tag, and although you've got Knockout references in your question, the problem has nothing to do with Knockout. In fact, your code is very anti-Knockout since you're using jQuery selectors within your "view model" and using observables where none are needed or even useful.

Related

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.

Skrollr.js Plugin Not Parallaxing Inside Bootstrap Carousel - Fiddle Provided

I am having a problem with the SKrollr.js plugin for Parallax and smooth scrolling. Everything works fine except Bootstrap carousel's, and im sure any carousel for that matter. It's clearly a display:none problem when the plugin is setting itself up on load and can't see any of the .item classes. But I can't figure out how on earth to get Skrollr to see all of the slides/.item classes when it's rendering.
I even tried this kinda stuff. My Skrollr markup isn't the problem that code always works for me.
Skrollr Markup
data-10p-top-bottom="background-position-y: 100%;" data-bottom-top="background-position-y: 0%;"
CSS
.displaying {
display: block !important;
}
JS
var sk = skrollr.init({
forceHeight: false,
beforerender: function(data) {
$(".item").addClass('displaying');
},
render: function(data) {
$(".item").removeClass('displaying');
}
});
EDIT
I made a JSFiddle for it here or you can see it fullscreen for debugging here
Sorry I was being vague and general because I know my HTML is solid. Check the fiddle. The slider functions just fine it's Skrollr not being able to see the hidden slides at runtime that is the problem. I just need a better solution to solve this.
I'm guessing that you need to do a refresh since I notice it works if I resize the browser.
Try this code:
setTimeout(function () {
skrollr.get().refresh();
}, 0);
You can change the timeout to 1000 if necessary to ensure everything loads.

Successive background-color animation request failing with jQuery 1.6.1

I'm trying to "flash" an input box by changing the background color briefly and then reverting back to the original bg color using jquery to indicate an error and grab the users attention.
Here's a fiddle to demonstrate what I'm trying to do.
I have to use jquery version 1.6.1. In the fiddle demo, it's using 1.6.4 and the color of the input box never changes at all. Actually, it doesn't work even with 1.11. In my local tests with my code, the input box changes red with the first animation call, but fails to do anything for the second animation call (to revert the bg color back to white). It just stays red.
I'm using very similar code to do the same thing in another site, except using jquery 1.11 and it works fine.
Is this just a compatibility issue? Is there some way I can make this work properly with version 1.6.1 ?
Here's the code:
function flashInputBox(id) {
var input = $('#'+id);
input.focus();
input.stop(true).animate({'background-color': '#EC8686'}, 350, function() {
input.stop(true).animate({'background-color': '#FFFFFF'}, 1000);
});
}
I forgot to mention that I'm using jQuery UI v1.8.18
The problem is properly replicated now in this fiddle (same code, just added jQuery UI 1.8.18).
Do you need to use jQuery? If not, this is way easier in CSS using key frames. If it is, skip my CSS explanation.
CSS
This still uses jQuery, but it gives the animation job to CSS, making your code more legible. I set this up in jsFiddle if you want to check it out: jsFiddle Example
First, setup a keyframe:
#keyframes pulse{
from {
background: #ec8686;
}
to {
background: #ffffff;
}
}
#-webkit-keyframes pulse{
from {
background: #ffffff;
}
to {
background: #ec8686;
}
}
and attach it to your existing input:
#my-input{
...
-webkit-animation: pulse 5s infinite;
-webkit-animation-play-state: paused;
...
}
Then the jQuery becomes a matter of letting the animation play for a few seconds:
function doIt() {
$("#my-input").css("-webkit-animation-play-state", "running");
setTimeout(function() {
$("#my-input").css("-webkit-animation-play-state", "paused");
}, 5000);
}
Also, you don't even need the jQuery to trigger the animation. The button click can directly trigger a CSS animation, however I figured you have some sort of code to check what's in the box for accuracy, so that why I kept your old function.
Note that this keyframe ends suddenly, so you can totally have a 0%, 50%, 100% keyframe instead.
Now for the raw jQuery way:
jQuery
For your jQuery, its much easier just to either specify your input directly (aka $("#my-input-name")), or if its just one input, I got it working just by using the following code instead:
function doIt() {
...
input.stop().animate({'background-color': '#EC8686'}, 350, function() {
// just say input here //
input.animate({'background-color': '#FFFFFF'}, 1000);
});
}
Colors aren't numeric values, so they can't be animated. From the jQuery documentation for .animate, emphasis mine:
All animated properties should be animated to a single numeric value, except as noted below; most properties that are non-numeric cannot be animated using basic jQuery functionality (For example, width, height, or left can be animated but background-color cannot be, unless the jQuery.Color() plugin is used). Property values are treated as a number of pixels unless otherwise specified. The units em and % can be specified where applicable.
If you don't want to (or can't) use the jQuery.Color plugin, you'll need to animate the color "manually", e.g. by setting an interval and changing the color at each step.

Custom jQuery/JavaScript Slider bugging out when I click on arrows/navigation

I'm working on creating my own responsive JavaScript/jQuery slider. It seems to be working pretty awesome for the most part, however, when I click on the arrows or navigation circles the timeout / animations seem to bug out. It is not consistent. When the arrows/nav circles are clicked, it should just reset the timeout and go to the corresponding slide.
For example if you click on a nav circle when it gets to the last slide it quickly goes right back to the first slide without the 5000 pause.
Here is the fiddle with all the code: http://jsfiddle.net/23712cwb/2/
Why is the timing bugging out like that? How do I fix it? As you can see I added clearTimeout($timeout); to the top of the nextSlide() function, but that didn't totally resolve it and I'm unsure this is the correct approach to the problem. However, before I added this line of code it was even more buggy.
Also if anyone has any tips they can give me or suggestions on how to make this even better that would be awesome. I am not very familiar with jQuery plugins so I am just kind of winging it here.
I figured it out. This code was causing the issue:
$('.slider .slides li .caption, .slider .slide-arrows li, .slider .slide-nav').mouseout(function () {
$timeout = setTimeout(function () { nextSlide('right', $slides, $height, $caption_speed, $slide_speed, 'null'); }, $slide_speed);
});
So every time I took my mouse off of the arrows or nav or caption it was doubling up on executing the nextSlide function.
I removed that code and it's all gravy now.
Actually, your code doesn't work on Firefox, because he is less forgiving than Chrome about errors.
You should define the functions captionActive and nextSlide you use outside of $(document).ready block
With your example it gave me this error on the console :
captionActive is not defined
Working fiddle
Edit : I guess you should be careful with the scope of $timeout : as you use it in the block document.ready and in functions, you should make use of global variables and work with window.$timeout instead of $timeout
That might solve some of your problems.

jQueryui animation with inital undefined height

See the following fiddle:
[edit: updated fiddle => http://jsfiddle.net/NYZf8/5/ ]
http://jsfiddle.net/NYZf8/1/ (view in different screen sizes, so that ideally the image fits inside the %-width layouted div)
The image should start the animation from the position where it correctly appears after the animation is done.
I don't understand why the first call to setMargin() sets a negative margin even though the logged height for container div and img are the very same ones, that after the jqueryui show() call set the image where I would want it (from the start on). My guess is that somehow the image height is 0/undefined after all, even though it logs fine :?
js:
console.log('img: ' + $('img').height());
console.log('div: ' + $('div').height());
$('img').show('blind', 1500, setMargin);
function setMargin() {
var marginTop =
( $('img').closest('div').height() - $('img').height() ) / 2;
console.log('marginTop: ' + marginTop);
$('img').css('marginTop', marginTop + 'px');
}
setMargin();
Interesting problem...after playing around with your code for a while (latest update), I saw that the blind animation was not actually firing in my browser (I'm testing on Chrome, and maybe it was firing but I wasn't seeing it as the image was never hidden in the first place), so I tried moving it inside the binded load function:
$('img').bind('load', function() {
...
$(this).show('blind', 500);
});
Now that it was animating, it seemed to 'snap' or 'jump' after the animation was complete, and also seemed to appear with an incorrect margin. This smacks of jQuery not being able to correctly calculate the dimensions of something that hadn't been displayed on the screen yet. On top of that, blind seems to need more explicit dimensions to operate correctly. So therein lies the problem: how to calculate elements' rendered dimensions before they've actually appeared on the screen?
One way to do this is to fade in the element whose dimensions you're trying to calculate very slightly - not enough to see yet - do some calculations, then hide it again and prep it for the appearance animation. You can achieve this with jQuery using the fadeTo function:
$('img').bind('load', function() {
$(this).fadeTo(0, 0.01, function() {
// do calculations...
}
}
You would need to work out dimensions, apply them with the css() function, blind the image in and then reset the image styles back to their original states, all thanks to a blind animation that needs these dimensions explicitly. I would also recommend using classes in the css to help you manage things a little better. Here's a detailed working example: jsfiddle working example
Not the most elegant way of doing things, but it's a start. There are a lot more easier ways to achieve seemingly better results, and I guess I just want to know why you're looking to do image blinds and explicit alignment this way? It's just a lot more challenging achieving it with the code you used...anyways, hope this helps! :)

Categories