jQuery - use .hover instead of .click - javascript

I have the following code on my page.
http://jsfiddle.net/SO_AMK/r7ZDm/
As you see it's a list of links, and every time a link is clicked, the popup box opens up right underneath the link in question.
Now, what I need to do is basically the same, except I need to use the .hover event and delay the execution by 2 seconds. So instead of clicking, the user should keep the cursor over a link for 2 seconds.
Sounds simple enough but I can't get the positioning to work properly. here's what I tried:
$('a.showreranks').hover(function()
{
$(this).data('timeout', window.setTimeout(function()
{
position = $(this).position();
$('#rerank_details').css('top', position.top + 17);
$('#rerank_details').slideToggle(300);
}, 2000));
},
function()
{
clearTimeout($(this).data('timeout'));
});
Can someone modify this to make it work?

Try like this:
$('a.showreranks').hover(function()
{
var self = this;
$(this).data('timeout', window.setTimeout(function() {
var position = $(self).offset();
$('#rerank_details').css('top', position.top + 17);
$('#rerank_details').slideToggle(300);
}, 2000));
},
function()
{
clearTimeout($(this).data('timeout'));
});
DEMO

jsFiddle demo
$('ul').on('mousemove','li',function(e){
var m = {x: e.pageX, y: e.pageY};
$('#rerank_details').css({left: m.x+20, top: m.y-10});
}).on('mouseenter','li',function(){
var t = setTimeout(function() {
$('#rerank_details').stop().slideDown(300);
},2000);
$(this).data('timeout', t);
}).on('mouseleave','li',function(){
$('#rerank_details').stop().slideUp(300);
clearTimeout($(this).data('timeout'));
});
The setTimeout will act like a hover intent that actually delays the execution for 2 seconds and counts the time hovered inside a data attribute of the hovered element - that gets 'nulled' on mouseleave.
I added also a few lines of code that will make your tooltip follow the mousemove.

Related

scroll based on dragenter event?

how to scroll up step by step and scroll down step by step using jquery. (jquery ui not appreciated).
i have a 2 divs
<div class="upper" style="height:35px;background-color:red;right:0;left:0;top:0;position:fixed;width:100%;z-index:2000"></div>
<div class="lower" style="height:35px;background-color:red;right:0;left:0;bottom:0;position:fixed;width:100%;z-index:2000"></div>
if i drag an image and hover on first div (upper),it should scroll up step by stell.
if i drag and hover on 2nd div it should scroll down manually.
in both cases scrolling should stop if i came out of the div.
i am trying to implement it using events
var isleftDragPosition=true;;
$('.upper').on('dragleave', function(){
console.log("hidragleave");
var isleftDragPosition=true;
});
$('.lower').on('dragleave', function(){
console.log("hi2dragleave")
var isleftDragPosition=true;
});
$('.upper').on('dragenter', function(){
var isleftDragPosition=false;
while(!isleftDragPosition){
var x=document.documentElement.scrollTop;
console.log("to upper position",x);
window.scrollTo(0, x-2);
}
});
$('.lower').on('dragenter', function(){
console.log("hi2dragenter",document.documentElement.scrollTop)
window.scrollTo(1000, 1000);
});
i am trying it with the top div to scroll up, but the code crashes my tab(hang).
how i can do that?
You are redefining your flag in each handler, so the change is not saved. Also, while loop might be to fast for your particular case. I modified code like this:
$('.upper').on('dragenter', function(){
isleftDragPosition=false;
clearInterval(interval);
var f = function() {
if(!isleftDragPosition){
var x=document.documentElement.scrollTop;
console.log("to upper position",x);
window.scrollTo(0, x-2);
} else {
clearInterval(interval);
}
}
setInterval(f, 1000);
});
Hope this helps.

Detecting the end of a overflow-x:scroll element and add a class before animation

As the title suggests I want to detect the start and end of a scrollable element built using overflow.
The following code works:
var scrollAmount = 150;
var scrollBox = $('.js-compare_scroll');
var arrowLeft = $('.js-compare_scroll_left');
var arrowRight = $('.js-compare_scroll_right');
var inactive = 'm-inactive';
$(arrowLeft).on('click', function () {
$(this).parent().find(scrollBox).stop().animate({
scrollLeft: '-='+scrollAmount
}, function() {
arrowRight.removeClass(inactive);
if(scrollBox.scrollLeft() === 0) {
arrowLeft.addClass(inactive);
}
});
});
$(arrowRight).on('click', function () {
$(this).parent().find(scrollBox).stop().animate({
scrollLeft: '+='+scrollAmount
}, function() {
arrowLeft.removeClass(inactive);
if(scrollBox.scrollLeft() + scrollBox.innerWidth() >= scrollBox[0].scrollWidth) {
arrowRight.addClass(inactive);
}
});
});
However the class to style the inactive colour of the arrows only appears once the animation completes. I need to add the class before the animation completes because it has a delay. I believe by default it is 400.
Is there anyway to detect this and apply the arrow classes where needed?
Thanks.
Came back from a break and realised I should take the checking if its at the end off the click event and onto a scroll event. This works a lot better now.

Place items right after the animation and inserbefore function mess

Here is my fiddle
I have an animation, that have to rearrange items in the list, the one we clicked on slides on the left and becomes active, the active element slides on the right and active class is remove from it.
However, i have some problems with the insertBefore function. Even if animation went right, it messes everything up. I am trying to figure out how to make everything look in place
Here is my script, but you can use fiddle
$(document).ready(function(){
console.log("it started");
swapsies();
});
function swapsies()
{
$('.lang').on('click', function() {
// console.log("here");
//.when(
var $dist = 27;
var $diststr="+="+$dist;
var $diststr2="-="+$dist*2
var $clicked=$(this);
var $mcb= $clicked.css('margin-left');
var $mnb=$clicked.css('margin-left');
var $mab=$('.active').css('margin-left');
$.when(
$(this).animate({ "margin-left": $diststr2 }, 500),
$(this).next().animate({ "margin-left": $diststr }, 500),
$('.active').animate({ "margin-left": $diststr }, 500)
).done(function(){
$clicked.insertBefore('.active');
$(this).css('margin-left', "-54")
$(this).next().css('margin-left', "27");
$('.active').css('margin-left', "27");
$('.active').removeClass('active');
$clicked.addClass('active');
});
});
}
Im not sure how exactly its supposed to re-arrange the items. but one way is this.
http://jsfiddle.net/7o6uuf0f/
minor change to the code in your done function
$clicked.insertBefore('.active');
$("#swapthis li").css("margin-left", "0");
$('.active').removeClass('active');
$clicked.addClass('active');
However you could also consider not reinventing the wheel, and use this.
http://jqueryui.com/sortable/#display-grid

Using a jquery slider for text instead of images?

This may be a little too specific, but I have a jquery slider that I am using <p> classes instead of images to cycle through customer quotes. Basically the problem I am running into right now is when it is static and non moving (JS code is commeneted out) they are aligned how I want them to be. As soon as the JS is un commented, they stretch out of view and you just see a white box?
Any ideas?
How I want each panel to look like:
jsfiddle
So I sort of made this my Friday project. I've changed a whole lot of your code, and added a vertical-align to the quotes and authors.
Here's the fiddle http://jsfiddle.net/qLca2fz4/49/
I added a whole lot of variables to the top of the script so you could less typing throughout.
$(document).ready(function () {
//rotation speed and timer
var speed = 5000;
var run = setInterval(rotate, speed);
var slides = $('.slide');
var container = $('#slides ul');
var elm = container.find(':first-child').prop("tagName");
var item_width = container.width();
var previous = 'prev'; //id of previous button
var next = 'next'; //id of next button
Since you used a % based width I'm setting the pixel widths of the elements in case the screen is reszed
slides.width(item_width); //set the slides to the correct pixel width
container.parent().width(item_width);
container.width(slides.length * item_width); //set the slides container to the correct total width
As you had, I'm rearranging the slides in the event the back button is pressed
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
I combined the prev and next click events into a single function. It checks for the ID of the element targeted in the click event, then runs the proper previous or next functions. If you reset the setInterval after the click event your browser has trouble stopping it on hover.
//if user clicked on prev button
$('#buttons a').click(function (e) {
//slide the item
if (container.is(':animated')) {
return false;
}
if (e.target.id == previous) {
container.stop().animate({
'left': 0
}, 1500, function () {
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
});
}
if (e.target.id == next) {
container.stop().animate({
'left': item_width * -2
}, 1500, function () {
container.find(elm + ':last').after(container.find(elm + ':first'));
resetSlides();
});
}
//cancel the link behavior
return false;
});
I've found mouseenter and mouseleave to be a little more reliable than hover.
//if mouse hover, pause the auto rotation, otherwise rotate it
container.parent().mouseenter(function () {
clearInterval(run);
}).mouseleave(function () {
run = setInterval(rotate, speed);
});
I broke this in to its own function because it gets called in a number of different places.
function resetSlides() {
//and adjust the container so current is in the frame
container.css({
'left': -1 * item_width
});
}
});
//a simple function to click next link
//a timer will call this function, and the rotation will begin :)
And here's your rotation timer.
function rotate() {
$('#next').click();
}
It took me a little bit, but I think I figured out a few things.
http://jsfiddle.net/qLca2fz4/28/
First off, your console was throwing a few errors: first, that rotate wasn't defined and that an arrow gif didn't exist. Arrow gif was probably something you have stored locally, but I changed the 'rotate' error by changing the strings in the code here to your actual variables.
So, from:
run = setInterval('rotate()', speed);
We get:
run = setInterval(rotate, speed);
(No () based on the examples here: http://www.w3schools.com/jsref/met_win_setinterval.asp)
But I think a more important question is why your text wasn't showing up at all. It's because of the logic found here:
$('#slides ul').css({'left' : left_value});
You even say that this is setting the default placement for the code. But it isn't..."left_vaule" is the amount that you've calculated to push left during a slide. So if you inspect the element, you can see how the whole UL is basically shifted one slide's worth too far left, unable to be seen. So we get rid of 'left_value', and replace it with 0.
$('#slides ul').css({'left' : 0});
Now, there's nothing really handling how the pictures slide in, so that part's still rough, but this should be enough to start on.
Let me know if I misunderstood anything, or if you have any questions.
So, a few things:
1) I believe you are trying to get all of the lis to be side-by-side, not arranged up and down. There are a few ways to do this. I'd just make the ul have a width of 300%, and then make the lis each take up a third of that:
#slides ul {
....
width: 300%;
}
#slides li {
width: calc(100% / 3);
height:250px;
float:left;
}
2) You got this right, but JSFiddle automatically wraps all your JS inside a $(document).ready() handler, and your function, rotate needs to be outside, in the normal DOM. Just change that JSFiddle setting from 'onload' to 'no wrap - in head'
3) Grabbing the CSS value of an element doesn't always work, especially when you're dealing with animating elements. You already know the width of the li elements with your item_width variable. I'd just use that and change your code:
var left_indent = parseInt($('#slides ul').css('left')) - item_width;
$('#slides ul').animate({'left' : left_indent}, 1500, function () {
to:
$('#slides ul').stop().animate({'left' : -item_width * 2}, 1500, function () {
4) Throw in the .stop() as seen in the above line. This prevents your animations from overlapping. An alternative, and perhaps cleaner way to do this, would be to simply return false at the beginning of your 'next' and 'prev' functions if #slides ul is being animated, like so:
if ($('#slides ul').is(':animated')) return false;
And I think that's everything. Here's the JSFiddle. Cheers!
EDIT:
Oh, and you may also want to clearInterval at the beginning of the next and prev functions and then reset it in the animation callback functions:
$('#prev').click(function() {
if ($('#slides ul').is(':animated')) return false;
clearInterval(run);
$('#slides ul').stop().animate({'left' : 0}, 1500,function(){
....
run = setInterval('rotate()', speed);
});
});

Fixing the animation properties

I am doing some research at the moment into creating a new maths game for primary school children where divs from 0-9 appear at random inside a container.
A question is given at the beginning. Something like, multiples of 20. The user will then have to click on the correct ones, and they will then be counted at the end and a score will be given.
I have just changed the speed in which the divs appear so that they appear for longer and more than one at a time to make the game easier for younger children.
I used "fadeIn" like so..
$('#' + id).animate({
top: newY,
left: newX
}, 'slow', function() {}).fadeIn(2000);
}
My problem is that now when I shoot the correct or incorrect number the animation is very glitchy and I cannot figure out why.
Fiddle: http://jsfiddle.net/cFKHq/6/ (See version 5 to see what it was like before)
Inside startplay(), control the concurrency when calling scramble() , I do it with a global var named window.cont, so I replaced your following call:
play = setInterval(scramble, 1800);
for this one:
play = setInterval(function() {
if (window.cont){
window.cont = false;
scramble();
}
}, 1000);
The var window.cont needs to be set globally at the start of your code, like so:
var miss = 0;
var hit = 0;
var target = $("#target");
window.cont = true;
So with window.cont you now can control that animations are executed one after another, without overlapping, like so:
$('#'+id).css({
top: newY,
left: newX
}).fadeIn(2000, function() {
setTimeout(function() {
$('#' + id).slideUp('fast');
window.cont = true;
}, 1500);
});
See working demo

Categories

Resources