How do I reinitialize HammerJS on resize event?
My problem is when I trigger the resize event the Selectors reset, and using jQuery for matching a container $('.container') will return an index of 0 all the time.. on document ready it worked before.
The $('.container') appears more than once so it should increment on swipe event.
Anyone got any ideas ?
$(document).ready(function() {
mobileCalculus(animation);
swipeActions( $('.home-element-wrapper'), $('.home').width());
$(window).on('resize', function() {
mobileCalculus(animation);
});
});
function swipeActions(parent, offset) {
var curInd = 0;
var theThumb = $('.thumb');
var myElement = document.getElementById('main-swipe');
var max = theThumb.length - 1;
// create a simple instance
// by default, it only adds horizontal recognizers
var mc = new Hammer(myElement);
// listen to events...
mc.on("swipeleft", function(ev) {
curInd = $('.thumb.active').index() + 1;
if (curInd > max) {
curInd = max;
}
var newML = offset * curInd;
theThumb.removeClass('active');
theThumb.eq(curInd).addClass('active');
console.log($('.thumb.active').index() + 1);
parent.css({
'margin-left': '-'+newML+'px'
});
});
mc.on("swiperight", function(ev) {
curInd = $('.thumb.active').index() - 1;
if (curInd < 0) {
curInd = 0;
}
var newML = offset * curInd;
theThumb.removeClass('active');
theThumb.eq(curInd).addClass('active');
parent.css({
'margin-left': '-'+newML+'px'
});
});
}
For example jquery has a function called .off which deactivates the event after which we can put a new event on the selector.
$('element').off('swiperight').on('swiperight')
Apparently I've figured it out. I had to make the var mc = new Hammer(myElement); value "global". Apparently when I reinitialized it the second time in swipeActions(), the off() function would not work, so initializing the value only once and then performing off() and on() with it makes everything work.
Related
var id = document.querySelector("#arrowUp");
var arrowUp = window.pageYOffset >= 5;
console.log(arrowUp);
id.classList.toggle("arrowUp", arrowUp);
id.addEventListener('click', function() {
window.scrollTo(0, 0);
})
I am trying to insert a class in certain HTML based on the scroll, but the issue is this part of the code:
var arrowUp = window.pageYOffset >= 5;
It is not dynamically getting true or false based on the scroll and the condition window.pageYOffset >= 5; is not dynamically true or false right now. Hence anticipated class is not getting inserted/deleted.
How to bind this part of the code to scroll event
Add an EventListener for the scroll event.
var id = document.querySelector("#arrowUp");
id.addEventListener('click', function() {
window.scrollTo(0, 0);
})
window.addEventListener('scroll', function() {
var arrowUp = window.pageYOffset >= 5;
if (arrowUp == true) {
id.classList.add('visible');
} else {
id.classList.remove('visible');
}
})
You can't do this "dynamically", window.pageYOffset is not a magic dynamic variable, it's a getter (function without arguments that retrieves some value)
In order for this to work, you have to check on each scroll event is the condition holds true.
var id = document.querySelector("#arrowUp");
document.addEventListener("scroll", function() {
var arrowUp = window.pageYOffset >= 5;
console.log(arrowUp);
id.classList.toggle("arrowUp", arrowUp);
});
id.addEventListener('click', function() {
window.scrollTo(0, 0);
});
I followed a tutorial and created a simple manual loop slideshow. I'm trying to make it so it changes the slide automatically even if the prev/next buttons aren't clicked. I tried a crude approach by setting a delay between automatic click events on the "next" button but for some reason it clicks it only once and stops. My js knowledge is very limited and can't figure it out, any input is appreciated. This is the script so far:
$(function() {
var ul = $(".slider ul");
var slide_count = ul.children().length;
var slide_width_pc = 100.0 / slide_count;
var slide_index = 0;
var first_slide = ul.find("li:first-child");
var last_slide = ul.find("li:last-child");
last_slide.clone().prependTo(ul);
first_slide.clone().appendTo(ul);
ul.find("li").each(function(indx) {
var left_percent = (slide_width_pc * indx) + "%";
$(this).css({"left":left_percent});
$(this).css({width:(100 / slide_count) + "%"});
});
ul.css("margin-left", "-100%");
$(".slider .prev").click(function() {
console.log("prev button clicked");
slide(slide_index - 1);
});
$(".slider .next").click(function() {
console.log("next button clicked");
slide(slide_index + 1);
});
function slide(new_slide_index) {
var margin_left_pc = (new_slide_index * (-100) - 100) + "%";
ul.animate({"margin-left": margin_left_pc}, 400, function() {
if(new_slide_index < 0) {
ul.css("margin-left", ((slide_count) * (-100)) + "%");
new_slide_index = slide_count - 1;
}
else if(new_slide_index >= slide_count) {
ul.css("margin-left", "-100%");
new_slide_index = 0;
}
slide_index = new_slide_index
});
}
});
Here is an approach to make it sliding automatically...
But if user clicks on prev/next, it holds the automatic feature for a defined "idle" time.
It need two lines added to your click handlers:
var autoEnabled = true; // ADDED
$(".slider .prev").click(function() {
console.log("prev button clicked");
slide(slide_index - 1);
autoEnabled = false; // ADDED
disabledCount = 0; // ADDED
});
$(".slider .next").click(function() {
console.log("next button clicked");
slide(slide_index + 1);
autoEnabled = false; // ADDED
disabledCount = 0; // ADDED
});
And this to cyclically slide or check if it can re-enable itself.
// ----------------- Automatic sliding interval with "idle time" to re-enable on user click
var idleTime = 5000; // Time without manual click to re-enable automatic sliding.
var autoSlideDelay = 1000; // Time between each slide when automatic.
var disabledCount = 0;
var autoSlide = setInterval(function(){
if(autoEnabled || disabledCount >= idleTime/autoSlideDelay ){
disabledCount = 0;
autoEnabled = true;
slide(slide_index + 1);
}else{
disabledCount++;
}
},autoSlideDelay);
var break_auto_slide = false;
function auto_silde()
{
if(break_auto_slide)
{
break_auto_slide = false;
return;
}
slide(slide_index + 1);
setTimeout(auto_silde,1000 /* time in ms*/);
}
setTimeout will call the function in a specified timeout in milliseconds.
Variable break_auto_slide - set it to true to stop the automatic slide. Next time the function is called it will return without setting a new timer and will reset this variable so auto mode can be turned on again.
This question already has an answer here:
jQuery trigger when 2/3s of div are in viewport
(1 answer)
Closed 6 years ago.
I would like to check if a class is added on an Element during the scroll and launch another function, just once, until the class is added to the next element.
here my first function :
function onScreen() {
$('article').each(function() {
var thisTop = $(this).offset().top - $(window).scrollTop();
var middleScreen = $(window).height() / 2;
if (thisTop < middleScreen && (thisTop + $(this).height()) > middleScreen) {
$(this).addClass('visible');
} else {
$(this).removeClass('visible');
}
});
}
// launch
$(window).on('load scroll', onScreen);
My seconde function : I would like to launch just once if the visible class is added to another article.
function textChange() {
var v = $('article.visible');
var el = $('.el', v);
var text = $(el).html();
$('.titre').html(text);
}
$(window).on('load scroll', textChange);
note : It's important to me to keep two separate function.
My issue is the scroll function get call textChange() each pixel I scroll on the page. Strangly, the onScreen() function add the visible class just once until the next article gonna be visible.
Thanks for yours suggestions.
Introduce a global variable that tells you if the function has been executed or not:
var textChanged = false;
In your textChange() function set it to true when the function was called the first time:
function textChange() {
if(!textChanged){
textChanged = true;
var v = $('article.visible');
var el = $('.el', v);
var text = $(el).html();
$('.titre').html(text);
}
}
EDIT: Alternatively you can do the check before the function gets called:
if (thisTop < middleScreen && (thisTop + $(this).height()) > middleScreen) {
$(this).addClass('visible');
if(!textChanged){
textChange();
}
} else {
$(this).removeClass('visible');
}
i have 3 divs with scrollbars.
If i scroll in div 1 i want to scroll div 2 and 3 in the opposite direction.
The distance scrolled should be half the distance of div 1.
This is what i have now (small part, rest is in jsfiddle), which works for 1 div.
$("#textBox1").scroll(function () {
console.log("scroll 1");
var offset = $("#textBox1").scrollTop() - scrollPosTBox1;
var half_offset = offset/2.0;
disable1 = true;
if(disable2 == false) {
$("#textBox2").scrollTop(scrollPosTBox2 - half_offset);
}
if(disable3 == false) {
$("#textBox3").scrollTop(scrollPosTBox3 - half_offset);
}
disable1 = false;
});
However, if i try to get the same for the other 2 divs then i can't scroll anything anymore.
This is because div 1 triggers div 2 and div 2 triggers back to div 1 for example.
I tried to fix this with the disable code but it doesn't help.
Can someone help me?
http://jsfiddle.net/XmYh5/1/
No disrespect to #EmreErkan and #Simon for their effort. Here's a no-click version of this.
var $boxes = $("#textBox1,#textBox2,#textBox3"),
active;
$boxes.scrollTop(150);
// set initial scrollTop values
updateScrollPos();
// bind mouseenter:
// 1) find which panel is active
// 2) update scrollTop values
$boxes.mouseenter(function () {
active = this.id;
updateScrollPos();
});
// bind scroll for all boxes
$boxes.scroll(function (e) {
$this = $(this);
// check to see if we are dealing with the active box
// if true then set scrolltop of other boxes relative to the active box
if(this.id == active){
var $others = $boxes.not($this),
offset = $this.scrollTop()-$this.data("scroll"),
half_offset = offset / 2;
$others.each(function(){
$this = $(this);
$this.scrollTop($this.data("scroll") - half_offset);
});
}
});
// utility function:
// assign scrollTop values element's data attributes (data-scroll)
function updateScrollPos() {
$boxes.each(function(){
$this = $(this);
$this.data("scroll",$this.scrollTop());
});
}
Fiddle
You can use a variable to determine active textbox with .mousedown() and do the trick if it's active;
var activeScroll = '';
$("#textBox1").on('mousedown focus mouseenter', function () {
activeScroll = 'scroll1';
}).scroll(function () {
if (activeScroll == 'scroll1') {
console.log("scroll 1");
var offset = $("#textBox1").scrollTop() - scrollPosTBox1;
var half_offset = offset / 2.0;
$("#textBox2").scrollTop(scrollPosTBox2 - half_offset);
$("#textBox3").scrollTop(scrollPosTBox3 - half_offset);
}
});
You can check your updated jsFiddle here.
Finally got a dynamic solution for this, was more complex than I thought but I think I got it:
http://jsfiddle.net/XmYh5/14/
var initialTop = 150,
factor = 2;
$(".textBox")
.addClass('disabled')
.scrollTop(initialTop)
.on('scroll', function () {
var $this = $(this);
if(!$this.is('.disabled')) {
this.lastOffset = this.lastOffset || initialTop;
var offset = $this.scrollTop(),
step = (offset - this.lastOffset) / factor;
$this.siblings().each( function() {
var $this = $(this),
offset = $this.scrollTop() - step;
$this.scrollTop(offset);
this.lastOffset = offset;
});
this.lastOffset = offset;
}
})
.on('mouseenter', function() {
$(this).removeClass('disabled').siblings().addClass('disabled');
});
I have this code
var timeout = 0;
$('#container td').each(function(){
var td = this;
setTimeout(function() {
var new_text = $(td).find(text).html();
popup_text.html(new_text);
popup.fadeIn('fast').delay(1000).fadeOut('slow');
}, timeout);
timeout += 1000 + 1000;
});
I get text from table cells and is displayed in the layer with a delay.
1 question: How do I make this code to run in an endless loop?
2 question: How to do that when you hover the mouse over popop cycle temporarily stopped and then continue?
Thanks a lot!
One way is to put the code to be repeated in a function, and have the function repeat itself at the end:
var timeout = 1000;
var action = function() {
// Do stuff here
setTimeout(action, timeout);
};
action();
However, as ahren suggested, setInterval might be better:
var timeout = 1000;
var action = function() {
// Do stuff here
};
setInterval(action, timeout);
The difference is slight, but if the machine is running slowly for some reason, the setInterval version will run the code every second on average, whereas the setTimeout version will run the code once each second at most.
Neither of those methods really work well with each(), however, so you'll need to store the sequence of popups somewhere and step through them:
var timeout = 1000;
var tds = $('#container td');
var index = 0;
var action = function() {
var td = tds[index];
var new_text = $(td).html();
popup.html(new_text);
popup.fadeIn('fast').delay(1000).fadeOut('slow');
if(++index >= tds.length)
index = 0;
};
setInterval(action, timeout);
action();
Finally, to avoid moving to the next popup while the popup is hovered, you can add a check for that at the start of the function. It's also necessary to rearrange the animations so that they go "check for hover - fade out - change text - fade in".
var timeout = 1000;
var tds = $('#container td');
var index = 0;
var action = function() {
if(popup.is(':hover'))
return;
var td = tds[index];
var new_text = $(td).html();
popup.fadeOut('slow', function() {
popup.html(new_text);
}).fadeIn('fast');
if(++index >= tds.length)
index = 0;
};
setInterval(action, timeout);
action();
jsFiddle: http://jsfiddle.net/qWkYE/2/
If you like the short clean way, then use the jquery-timing plugin and write:
$.fn.waitNoHover = function(){
return this.is(':hover') ? this.wait('mouseleave') : this;
};
$('#popups div').repeat().each($).fadeIn('fast',$)
.wait(200).waitNoHover().fadeOut('slow',$).all()
See this on http://jsfiddle.net/creativecouple/fPQdU/3/