So, I am going to actually kill two birds with one stone. First off, I am trying to trigger an alert once the slider moves left to a specific degree. For example, once it goes to, let’s say, the 3rd slide I would like for it to trigger an alert. Also, I need help with the cycling of the slider. I want the slider to cycle like a rotation (360), but instead at the end of the cycle it slides all the way back to the start. View the Codepen to have a better understanding of what I mean. Thank you for your time. Your help is much appreciated.
Live Codepen
var W = $('#image_rotator').width(),
N = $('#slider .slide').length,
C = 0,
intv;
if (N <= 1) $('#left, #right').hide();
$('#slider').width(W * N);
$('#left, #right').click(function() {
C = (this.id == 'right' ? ++C : --C) < 0 ? N - 1 : C % N;
$('#slider').stop().animate({
left: -C * W
}, 300);
});
function setResetInterval(e) {
var intv = $("#slider");
if (e) {
timer = setInterval(function() {
$('#right').click();
}, 1000);
} else {
clearInterval(timer);
}
$('#slider').click(function() {
var x = $('#slider').offset();
alert("Top: " + x.top + " Left: " + x.left);
});
}
$("#btn").click(function(e) {
e.preventDefault();
setResetInterval(true);
});
$("#btn2").click(function(e) {
e.preventDefault();
setResetInterval(false);
});
$('#slider').hover(function(e) {
return e.type == 'mouseenter' ? setResetInterval(false) : setResetInterval(true);
});
This accomplishes both of the things that you wanted using the optional callback parameter in the animate function. It checks first to see if the variable C (the 0-based index of the current slide) is equal to 2 (3 in 1-based indexing), and shows an alert if it is. Then it checks to see if C is equal to 10 (which would mean that the slide currently being shown is the 9th one; The 9th image is just a duplicate of the 1st one) If it is on the 9th one, then jump back to the first one and trigger $("#right").click();.
$('#left, #right').click(function() {
C = (this.id == 'right' ? ++C : --C) < 0 ? N - 1 : C % N;
$('#slider').stop().animate({
left: -C * W
}, 300, function() {
if (C == 2){alert("3rd");}
if (C == 10) {
$('#slider').css("left", "0");
$('#right').click();
}
});
});
JSFiddle (Because CodePen's layout is weird to me)
I'm using meteor-keybindings and the following code:
Meteor.Keybindings.add({
'plus' : function () { zoome.value -= -(zoome.value-90); },
'-' : function () { zoome.value -= 10; },
'*' : function () { zoome.value = 100; }
});
I had to write the above code for a solid solution around this misty bug...
Scenario:
I have a range element with min value of 100 and max value of 500 to zoom a page.
the zoome.value += 10 jumps right up to 500, what's behind the scene?
The minus and reset functions work well...
I'm trying to create a fading effect using vanilla.js instead of jQuery. I'm using the following code to create the hide and show effect:
document.getElementById("pic-num-submit").onclick = function() {
fade();
};
var home = document.getElementById('home').style;
home.opacity = 1;
var agree = document.getElementById('agree').style;
agree.opacity = 0;
agree.display = "none";
function fade() {
if((home.opacity -= .1) < 0) {
home.display = "none";
show();
}
else {
setTimeout(fade, 40);
}
}
function show() {
if((agree.opacity += 0.2) < 1) {
agree.display = "";
}
else {
setTimeout(show, 40);
}
}
Everything is working with the fade function (in Firefox) But when I invoke the show function it only runs once, then it removes the display styling, and shows the div element at 0.2 opacity. I'm not sure what I'm doing wrong.
Here is a jsFiddle example of the problem I am having: http://jsfiddle.net/L54Aw/2/
Also it's broken in Chrome for some reason (The fade function never completes because of something to do with a js decimal subtracting problem)
Your "show" function is not correct. You only set up the timer when the opacity is not less than one. Initially, it is, so the code only runs once.
You're also running into a weirdness in JavaScript that pertains to a significant difference between the + and - operators. Subtraction is always numeric, but not so addition!
Here's a working "show" function:
function show() {
agree.display = ""; // only need this the first time anyway
agree.opacity = +(agree.opacity) + 0.2;
if (agree.opacity <= 1)
setTimeout(show, 40);
}
That unary + operator forces the "opacity" property to be interpreted as a number. Without that, it's a string! Thus adding 0.2 to the string "0.2" gives you "0.20.2", which is nonsense.
The decrementing you did for the other element worked OK because the subtraction operator coerces operands to numbers.
I can't comment on Pointy's solution, but here's what you could do with the fade function to avoid the bug that happens when you subtract low numbers:
function fade() {
home.opacity -= .05;
if(home.opacity - .05 < 0) {
home.display = "none";
show();
}
else {
setTimeout(fade, 20);
}
}
It isn't bulletproof, but it works by subtracting .05 instead of .1 and counter it by doubling the speed of the animation.
you probably want
(agree.opacity += 0.2) > 1
instead of
(agree.opacity += 0.2) < 1
I have a function to change the background color depending on the value of a slider
There are 35 different colors and I now use this code for it (of course it is longer)
if (value < 25) {
color = '#FFFFFF';
} else if (value > 25 && value < 50) {
color = '#F8F8F8';
} else if (value > 50 && value < 75) {
color = '#F0F0F0 ';
}
Is there a way to shorten this up?
If you're incrementing by 25, then make an Array of colors:
var colors = ['#FFFFFF', '#F8F8F8', '#F0F0F0 ', ... ]
And then do a little math to see which index to use.
color = colors[(value - (value % 25)) / 25];
Or if you prefer:
color = colors[Math.floor(value / 25)];
You could make it a two line statement, without arrays, by doing something similar to this:
var rgbvalue = 255-Math.floor(value/25);
var color = 'rgb('+rgbvalue+','+rgbvalue+','+rgbvalue+');';
Of course you would have to limit the value, so that the rgbvalue doesn't get smaller than 0, but I guess you can easily do that, if you know the possible values.
And if you want it to get dark faster, you can multiply the result of the Math.floor operation, like this:
var rgbvalue = 255-(Math.floor(value/25)*5);
And you have the advantage that you don't have to write a huge array of shades of gray.
More bullet-proof version (not fully -proof though)
var colors = ['#FFFFFF','#F8F8F8','#F0F0F0'];
/* this is not that necessary */
var value = input_value || default_input_value;
var color = colors[ Math.floor(value/25) ];
colors = {'#FFFFFF','#F8F8F8','#F0F0F0 '}
color=colors[(int)value/25];
You may need to adjust this depending on the range of value.
Ditch the && and cascade instead
if(values > 75){
//anything above 75 falls here
}
else if(value > 50){
//anything <= 75 but > 50 falls here
}
else if(values > 25){
//anything <= 50 but > 25 falls here
}
else {
//anything <= 25 falls here
}
You could use an array of objects that describe the color and the min and max of the range and then use a function to iterate through the array to find the color between the range.
function getColor(value) {
var colorRanges = [
{ color : '#FFFFFF', min : 0, max : 25 },
{ color : '#F8F8F8', min : 25, max : 50 },
{ color : '#F0F0F0', min : 50, max : 75 }
],
length = colorRanges.length;
while(length--) {
var colorRange = colorRanges[length];
if (value >= colorRange.min && value < colorRange.max) {
return colorRange.color;
}
}
// default color
return colorRanges[0].color;
}
With a little additional effort, you could expose a way to add new colors and ranges, have a default for the range interval, etc. If your colors and range interval are fixed however, this is probably overkill.
I've been given a cut down subset of the jQuery lib one of the key features I'm missing is the .effect functions. I do however have .animate. I was wondering if anyone would have any ideas how I could go about reproducing the animation functions.
I am particularly consious of making this only a few lines as I need to keep the code size down. Which is why the jquery lib is as small as it is and doesnt have the effects functions.
TLDR - I'm trying to replace
$("#"+id_string).effect( "shake", {}, "fast" );
With something using .animate within jQuery.
So far I have something like this ..
jQuery.fn.shake = function(intShakes, intDistance, intDuration) {
this.each(function() {
$(this).css("position","relative");
for (var x=1; x<=intShakes; x++) {
$(this).animate({left:(intDistance*-1)}, (((intDuration/intShakes)/4)))
.animate({left:intDistance}, ((intDuration/intShakes)/2))
.animate({left:0}, (((intDuration/intShakes)/4)));
}
});
return this;
};
I like #phpslightly solution so much, I keep using it. So here it is updated to basic jquery plugin form which will return your element
jQuery.fn.shake = function(interval,distance,times){
interval = typeof interval == "undefined" ? 100 : interval;
distance = typeof distance == "undefined" ? 10 : distance;
times = typeof times == "undefined" ? 3 : times;
var jTarget = $(this);
jTarget.css('position','relative');
for(var iter=0;iter<(times+1);iter++){
jTarget.animate({ left: ((iter%2==0 ? distance : distance*-1))}, interval);
}
return jTarget.animate({ left: 0},interval);
}
You would then use it like a regular plugin:
$("#your-element").shake(100,10,3);
Or use the default values (100, 10, 3):
$("#your-element").shake();
It's actually already implemented this way under the covers, you can see exactly how in jquery.effects.shake.js, if you wanted to copy only that functionality you can.
Another approach to think about: if you're using multiple effects, I'd recommend downloading jQuery UI with only the effects you want. For this effect, without copying the functionality yourself, you would just need jquery.effects.core.js and jquery.effects.shake.js.
This is probably irrelevant now but I've ported jQ UI's shake effect as a standalone jQuery plugin. All you need is jQuery and it will work exactly like the one provided in jQ UI.
For those who want to use the effect without actually bloating their project with unnecessary jQ UI core files.
$('#element').shake({...});
It can be found here with instruction: https://github.com/ninty9notout/jquery-shake
Thought I'd leave this here for future reference.
This is a more clean and smooth way to do the animation.
jQuery.fn.shake = function(shakes, distance, duration) {
if(shakes > 0) {
this.each(function() {
var $el = $(this);
var left = $el.css('left');
$el.animate({left: "-=" + distance}, duration, function(){
$el.animate({left: "+=" + distance * 2}, duration, function() {
$el.animate({left: left}, duration, function() {
$el.shake(shakes-1, distance, duration); });});
});
});
}
return this;
};
I don't understand all the complexity being thrown into reproducing the shake effect with solely animate. Here's my solution in just a couple lines.
function shake(div,interval=100,distance=10,times=4){
$(div).css('position','relative');
for(var iter=0;iter<(times+1);iter++){
$(div).animate({ left: ((iter%2==0 ? distance : distance*-1))}, interval);
}//for
$(div).animate({ left: 0},interval);
}//shake
EDIT: Updated code to return element to original position. Still believe this is the lightest and best solution to the problem.
I wrote some time ago a few simple jquery animations:
https://github.com/yckart/jquery-custom-animations
/**
* #param {number} times - The number of shakes
* #param {number} duration - The speed amount
* #param {string} easing - The easing method
* #param {function} complete - A callback function
*/
jQuery.fn.shake =
jQuery.fn.wiggle = function (times, duration, easing, complete) {
var self = this;
if (times > 0) {
this.animate({
marginLeft: times-- % 2 === 0 ? -15 : 15
}, duration, easing, function () {
self.wiggle(times, duration, easing, complete);
});
} else {
this.animate({
marginLeft: 0
}, duration, easing, function () {
if (jQuery.isFunction(complete)) {
complete();
}
});
}
return this;
};
This is not perfect, but functional
// Example: $('#<% =ButtonTest.ClientID %>').myshake(3, 120, 3, false);
jQuery.fn.myshake = function (steps, duration, amount, vertical) {
var s = steps || 3;
var d = duration || 120;
var a = amount || 3;
var v = vertical || false;
this.css('position', 'relative');
var cur = parseInt(this.css(v ? "top" : "left"), 10);
if (isNaN(cur))
cur = 0;
var ds = d / s;
if (v) {
for (i = 0; i < s; i++)
this.animate({ "top": cur + a + "px" }, ds).animate({ "top": cur - a + "px" }, ds);
this.animate({ "top": cur }, 20);
}
else {
for (i = 0; i < s; i++)
this.animate({ "left": cur + a }, ds).animate({ "left": cur - a + "px" }, ds);
this.animate({ "left": cur }, 20);
}
return this;
}
Based on #el producer solution, I added some multiply logic and make it look like a random shake.
jQuery.fn.shake = function (interval, distance, times) {
interval = typeof interval == "undefined" ? 100 : interval;
distance = typeof distance == "undefined" ? 10 : distance;
times = typeof times == "undefined" ? 3 : times;
var jTarget = $(this);
jTarget.css('position', 'relative');
for (var iter = 0; iter < (times + 1) ; iter++) {
jTarget.animate({ top: ((iter % 2 == 0 ? distance * Math.random() : distance * Math.random() * -1)), left: ((iter % 2 == 0 ? distance * Math.random() : distance * Math.random() * -1)) }, interval);
}
return jTarget.animate({ top: 0 , left: 0 }, interval);
}
Position had to be absolute on my side, so I changed it to:
jQuery.fn.shake = function(interval, distance, times) {
interval = typeof interval == "undefined" ? 100 : interval;
distance = typeof distance == "undefined" ? 10 : distance;
times = typeof times == "undefined" ? 3 : times;
var jTarget = $(this);
for (var iter=0;iter<(times+1);iter++) {
jTarget.animate({ 'padding-left': ((iter%2==0 ? distance : distance*-1))}, interval);
}
return jTarget.animate({ 'padding-left': 0 } ,interval);
}