All the documentation talks about when the waypoint reaches the top of the viewport, but I would like the trigger to happen when any part of the waypoint is in the center of the viewport.
This code works fairly well if I'm scrolling down, but when I scroll up it doesn't work, obvoiusly.
$('.section').waypoint(function(direction) {
highlight('#' + this.id);
}, {
context: '#scroll',
offset: function (direction) {
return $(this).height();
}
});
I tried the code below and a couple variants and it never even hits either of the return statements.
$('.section').waypoint(function(direction) {
highlight('#' + this.id);
}, {
context: '#scroll',
offset: function (direction) {
if (direction == 'down') {
return -$(this).height();
} else {
return 0;
}
}
});
So now I'm trying this, based on waypoint examples, but $active.id doesn't work like this.id so my function "highlight" fails.
$('.section').waypoint(function (direction) {
var $active = $(this);
if (direction == 'down') {
$active = $active.prev();
}
if (!$active.length) {
$active = $(this);
}
highlight($active.id);
}, {
context: '#scroll',
offset: function (direction) {
return $(this).height();
}
});
The offset option does not take a direction parameter. I'd love to know if you got that from somewhere in the documentation because if there's a section using direction in an offset function, it's a mistake.
You can tell a waypoint to trigger when the top of the element hits the middle of the viewport by using a % offset:
offset: '50%'
If you need to have a different offset when scrolling up versus scrolling down, this is best accomplished by creating two different waypoints:
var $things = $('.thing');
$things.waypoint(function(direction) {
if (direction === 'down') {
// do stuff
}
}, { offset: '50%' });
$things.waypoint(function(direction) {
if (direction === 'up') {
// do stuff
}
}, {
offset: function() {
// This is the calculation that would give you
// "bottom of element hits middle of window"
return $.waypoints('viewportHeight') / 2 - $(this).outerHeight();
}
});
Related
I am trying to have a highchart spline chart with tooltip positioned to the right corner and have another tooltip on mouseover specific points. So basically I would like to show Two tooltips for some points. So far i was able to do that only on click event where we the event information with mouse coordinates with respect to page. Is there a way we can show two tooltips for same point? I want one tooltip to be positioned at the right corner and the other one next to the point as shown in the below JSfiifle.
"point": {
"events": {
"mouseOver": function(e) {
var selectedPoints = $('#' + this.series.chart.renderTo.id).highcharts().getSelectedPoints();
if (selectedPoints.length) {
selectedPoints[0].select();
}
if (e.target.marker && !e.target.marker.radius) {
return;
}
},
"mouseOut": function(e) {
util.hideBandInsightsPopup();
},
"click": function(e) {
if (e.point && e.point.marker && !e.point.marker.radius) {
return;
}
$("#factor-popup-content").html("my popup content");
var yPixel = e.pageY + 5;
var currentPointHeight = yPixel + $("#factor-popup").height();
if ($("#factor-popup").height() < 300 && currentPointHeight > $(window).height()) {
var adjustHeight = currentPointHeight - $(window).height() + 30;
yPixel = yPixel - adjustHeight;
}
$("#factor-popup").css({
'position': 'fixed',
'top': (yPixel) + 'px',
'left': (e.pageX) + 5 + 'px'
}).show();
}
}
}
Here is the Jsfiddle http://jsfiddle.net/zLpakfj2/4/
The original event is not passed to the mouseOver event, but you can add it for example to a point in this way:
(function(H) {
H.wrap(
H.Pointer.prototype,
'getHoverData',
function(
proceed,
existingHoverPoint,
existingHoverSeries,
series, isDirectTouch,
shared,
e
) {
var result = proceed.apply(this, Array.prototype.slice.call(arguments, 1));
if (result.hoverPoint) {
result.hoverPoint.originalEvent = e;
}
return result;
});
}(Highcharts));
Live demo: http://jsfiddle.net/BlackLabel/y18h30t4/
Docs: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts
I've created a React component here where I'm trying to get the header to become fixed after it has scrolled past itself. Everything works as expected in that instance, but after I've scrolled past the elements height, it switches the class on and off constantly.
Here's the scroll function:
handleScroll: function(event) {
// Save the element we're wanting to scroll
var el = document.querySelector("#target");
// If we've scrolled past the height of the element, add a class
if (el.getBoundingClientRect().bottom <= 0) {
console.log(el.getBoundingClientRect().bottom + " bottom");
this.setState({
headerIsActive: true
});
// If we've scrolled back up to the top of the container, remove the class
} else if (el.getBoundingClientRect().top <= 0) {
console.log(el.getBoundingClientRect().top <= 0 + " top");
this.setState({
headerIsActive: false
});
}
},
Can somebody please tell me what I'm doing wrong? Or point me in the right direction?
Thanks
Fixed by detecting when the window.scrollY position is at 0, like so:
handleScroll: function(event) {
// Save the element we're wanting to scroll
var el = document.querySelector("#target");
var pageY = window.scrollY
// If we've scrolled past the height of the element, add a class
if (el.getBoundingClientRect().bottom <= 0) {
console.log(el.getBoundingClientRect().bottom + " bottom");
this.setState({
headerIsActive: true
});
// If we've scrolled back up to the top of the container, remove the class
} else if (pageY == 0) {
console.log("at top");
this.setState({
headerIsActive: false
});
}
},
animate = animate;
desanimate = undo animate;
Friends, I created a function that does an element animate or 'desanimate' depending on where the scroll of the body or a div is, it's working ok, how it works?
<li data-animation-time="[100, 800]" data-animation-position="right" class="list-item one"></li>
the first value of the data-animation-time array is the initial value, ie the animator function should be called when the scrollTop pass that value, the second value is the end, the 'desanimate' function should be called when the scrollTop pass that value.
Everything working as you can see here -> Codepen: http://codepen.io/celicoo/pen/ogKGEP (you need scroll to see the animation happens).
Now I want to determine which way the animation to happen and which way it should end, for that I changed this attr:
data-animation-position="right-to-left" instead of just right or left, and i add some ifs statements to the animation and 'desanimation' function:
Animate:
var animate = function(target, position) {
target.css('display', 'inline-block');
if (position === 'right-to-right') {
target.animate({
opacity: 1,
right: '0px'
}, 500);
}
else if (position === 'right-to-left') {
target.animate({
opacity: 1,
right: '0px'
}, 500);
}
else if (position === 'left-to-left') {
target.animate({
opacity: 1,
left: '0px'
}, 500);
}
else if (position === 'left-to-right') {
target.animate({
opacity: 1,
left: '0px'
}, 500);
}
};
'Desanimate':
var desanimate = function(target, position) {
if (position === 'right-to-right') {
target.animate({
opacity: 0,
right: '245px'
}, 500);
}
else if (position === 'right-to-left') {
target.animate({
opacity: 0,
left: '245px'
}, 500);
}
else if (position === 'left-to-left') {
target.animate({
opacity: 0,
left: '245px'
}, 500);
}
else if (position === 'left-to-right') {
target.animate({
opacity: 0,
right: '245px'
}, 500);
}
};
And is not working in the 'desanimate' way, something is not working good, and i really cant see what it is.
Could someone give me a hand here? What could be doing 'desanimate' not work when I inverted step values?
Example:
left-to-right
right-to-left
Codepen with old code working just with one side (ex: left or right);
Code pen with new code not working 100% with multiple sides (ex: left to left, left to right, right to right or right to left);
Updated the codepen link . Just have a look and let me know whether it matches the requirement.
+ function($) {
var animate = function(target, position) {
target.css('display', 'inline-block');
if (position === 'right-to-left' || position === 'right-to-right' ) {
target.css('right', '500px');
target.css('left','' );
target.animate({
opacity: 1,
right: '0px'
}, 500);
}
else if (position === 'left-to-right' || position=="left-to-left") {
target.css('left', '500px');
target.css('right', '');
target.animate({
opacity: 1,
left: '0px'
}, 500);
}
};
var disanimate = function(target, position) {
if (position === 'right-to-left' || position ==="left-to-left") {
target.css('left','' );
target.animate({
opacity: 0,
right: '245px'
}, 500);
}
else if (position === 'left-to-right' || position === "right-to-right") {
target.css('left','' );
target.animate({
opacity: 0,
left: '245px'
}, 500);
}
};
$(window).on('load', function() {
var target = $('[data-animation-time]');
var animationInitial = target.data('animation-time')[0];
var animationFinal = target.data('animation-time')[1];
var position = target.data('animation-position');
var shown = false;
$('.container').scroll(function() {
var scroll = $(this).scrollTop();
if (!shown && (animationInitial < scroll && animationFinal > scroll)) {
console.log("animate")
animate(target, position);
shown = true;
}
else if (shown && (animationFinal < scroll || animationInitial > scroll)) {
console.log("disanimate")
disanimate(target, position);
shown = false;
if (position.split("-")[0] == position.split("-")[2])
position = anti(position);
}
});
});
}(jQuery);
var anti = function (position){
if (position == "left-to-left")
return "right-to-right"
else
return "left-to-left"
}
Css :- it was right 500px. so intital position of card is fixed. i changed it to dynamic based on input and whenever you are adding right(css) you have to make sure left(css) is null because if you give both right and left it will get confused during animation
left-to-right & right-to-left both have their initial and final position same.. so no need of extra fittings.. so it will work even if you come from down
left-to-left & right-to-right don't have have their initial and final position same .. so left-to-left will become right-to-right in reverse loop. i did that using anti function
I have an issue which is related to greensock animation but also may be a more general js issue in that I need to transfer a mousedown event to a second draggable instance after killing the first draggable instance.
the codepen hopefully will illustrate what i am trying to do.. code is underneath.
Codepen URL: http://codepen.io/anon/pen/ypdGn
var detachdraggable;
var rotatedraggable;
function makeRotateDraggable() {
// create rotate draggable for the cards..
rotatedraggable = Draggable.create(".dragclone", {
type:"rotation",
throwProps:true,
dragResistance : 0,
edgeResistance : 1,
bounds:{minRotation:-60, maxRotation:60},
onDragStart : function() {
var $el = $(this.target);
var cardStartAngle = $el.data('startangle');
},
onDrag: function() {
currentCardAngle = this.rotation;
var $el = $(this.target);
var cardStartAngle = $el.data('startangle');
cardDirection = ( currentCardAngle > cardStartAngle ) ? "up":"down";
cardTravelDegrees = Math.abs(currentCardAngle - cardStartAngle);
this.vars.type = "x";
},
onDragEnd: function() {
},
onClick: function() {
return false;
}
});
$('.dragclone').mousedown(function() {
$('.dragclone').css('z-index','10');
rotatedraggable[0].enable();
});
$('.dragclone').mouseout(function() {
detachdraggable[0].disable();
$('.dragclone').trigger('mousedown');
});
$('.dragclone').trigger('mouseout');
}
// first setup the x,y draggable..
detachdraggable = Draggable.create('.dragclone', {
type: "x,y",
edgeResistance:1,
throwProps:true,
onPress:function() {
startX = this.x;
startY = this.y;
},
onDrag:function() {
var xChange = this.x - startX,
yChange = this.y - startY,
ratio = Math.abs(xChange / yChange),
direction = [];
// NB:: you can adjust these ratio thresholds to make things
// more or less sensitive to diagonal movement.
if (ratio > 0.25) {
direction.push((xChange < 0) ? "left" : "right");
}
if (ratio < 4) {
direction.push((yChange < 0) ? "up" : "down");
}
if(direction[0] == "left") {
// TweenMax.to( $('.cloned'), .0001, {right:-xChange + 135});
}
// moving up so lets switch cards !!
if(direction[0] == "up") {
if(Math.abs(yChange) > 20) {
makeRotateDraggable();
}
}
},
onDragEnd:function() {
// driftDragCardBack();
// if(!cardPopping) { driftClonedCardBack(); }
},
onThrowComplete: function() {
}
});
I am battling to switch between 2 draggables setup on same element, am wondering if this is possible at all. basically the codepen has an example of what I want to do, but it isnt seamless. draggable is setup for element of type x,y, what i want to do is when the drag direction is up kill the type x,y draggable and switch to a type: rotation draggable so that the card moves around on an axis. you can see mine does that, but only if you release and then click again - is there any way to make this seamless, so it just switches mid-drag ?
thanks,
Justin
See http://codepen.io/anon/pen/klanu
I've never used greensock but just had a look at their document:
https://greensock.com/docs/#/HTML5/Drag/Draggable/startDrag/
First of all you had a couple of issues within your code. You don't need to create rotatedraggable inside a function, just create it, it's not enabled anyways. I also moved
$('.dragclone').mousedown(function() {
$('.dragclone').css('z-index','10');
detachdraggable[0].enable();
});
outside the function.
In your 2nd draggable, you were calling createRotation to create the rotation but like I said you can create it at the start. When the div is moved to the top, I just disabled the current drag and enabled the 1st one and called dragStart on it. e is what's passed to drag of the 2nd.
if(Math.abs(yChange) > 20) {
detachdraggable[0].disable();
rotatedraggable[0].enable();
rotatedraggable[0].startDrag(e);
}
i've added this script that scroll down 100% with mouseweel at once
$(document).ready(function () {
var divs = $('.mydiv');
var dir = 'up'; // wheel scroll direction
var div = 0; // current div
$(document.body).on('DOMMouseScroll mousewheel', function (e) {
if (e.originalEvent.detail > 0 || e.originalEvent.wheelDelta < 0) {
dir = 'down';
} else {
dir = 'up';
}
// find currently visible div :
div = -1;
divs.each(function(i){
if (div<0 && ($(this).offset().top >= $(window).scrollTop())) {
div = i;
}
});
if (dir == 'up' && div > 0) {
div--;
}
if (dir == 'down' && div < divs.length) {
div++;
}
//console.log(div, dir, divs.length);
$('html,body').stop().animate({
scrollTop: divs.eq(div).offset().top
}, 200);
return false;
});
$(window).resize(function () {
$('html,body').scrollTop(divs.eq(div).offset().top);
});
});
But i need to add something on it so the scrolling look smooth , how can i do that ?
Fiddle
You can either specify a duration for your animate function or an easing function to have a different animation behavior.
You can find easing functions and instruction to use theme here :
jQuery Easing Plugin
SOLUTION:
#user3127499 already provided you a working FIDDLE.
He changed the time to 1000 from 100
$('html,body').stop().animate({
scrollTop: divs.eq(div).offset().top
}, 1000);
And added a 1000 delay here:
$('html,body').scrollTop(divs.eq(div).offset().top.delay(1000));
There is a plugin for that:
You will counter many other challenges while recreating the wheel, why don you you simply use this plugin named Scroll Section.
DEMO