jQuery plugin: Do stuff to matched elements - javascript

Here's the plugin in case anyone finds it useful. http://silvestreh.github.io/onScreen/
Thanks again!
So, I'm trying to write my very first jQuery plugin and I already found my first road block. The plugin is supposed to do something to an element when it's visible (as in the view port area, not CSS visibility)
This is what the plugin looks like:
(function($) {
$.fn.onScreen = function(options) {
var self = $(this);
params = $.extend({
doIn: function(){
console.log('on screen');
},
doOut: function(){
console.log('off screen');
},
offset: 0
}, options);
return this.each(function() {
var $el = $(this);
var elTop = $el.offset().top;
$(window).scroll(function() {
var pos = $(window).scrollTop();
if (pos + params.offset >= (elTop - $el.height()) && pos + params.offset < (elTop + $el.height())) {
params.doIn.call($el[0]);
} else if (pos + params.offset > (elTop + $el.height()) || pos + params.offset < elTop) {
if (typeof(params.doOut) == 'function') {
params.doOut.call($el[0]);
}
}
});
});
};
})(jQuery);
And this is how I'm trying to use it:
$(function(){
$('div').onScreen({
doIn: function() {
$(this).stop().animate({
left: 20
},500)
},
doOut: function() {
$(this).stop().animate({
left: 0
},500)
}
});
});
The problem is that $(this) refers to the window object (because of the $(window).scroll() in the plugin) and not the matched elements. What am I doing wrong? How do I tell my plugin that I want to do stuff to the matched elements instead?
Thanks in advance :-)
EDIT: I just created a JSFiddle so you can check it out. http://jsfiddle.net/FBEFJ/3/
EDIT 2: bfavaretto fixed the code. I updated the question with the working code. Thank you!

The problem is how you're calling doIn and doOut in the plugin. Perhaps the simplest solution is to enforce a this value with Function.prototype.call:
if (pos + params.offset >= (elTop - $el.height()) && pos + params.offset < (elTop + $el.height())) {
params.doIn.call($el[0]);
} else if (pos + params.offset > (elTop + $el.height()) || pos + params.offset < elTop) {
if (typeof(params.doOut) == 'function') {
params.doOut.call($el[0]);
}
}

Related

If statement with scrolltop does not work

I am trying to make an animation happen once the webpage is at a certain part of the page. I have looked at other people queries and my problem is similar but it does not work.
here is the code:
if($('html,body').scrollTop() > 400) {
$('.fish_one').animate({"margin-left":"+=65%"},1000);
$('.fish_two').animate({"margin-left":"-=10%"},1000);
$('.left').animate({"opacity":"+=1"},1000);
$('header').css({"background-color":"#fff"});
$('header a').css({"color":"#94d9f8"});
}
You need to check the if statement every time the page scrolls, not just on load. Use $(window).scroll(function(){
$(window).scroll(function(){
if($(window).scrollTop() > 400) {
alert("lower");
}
});
Fiddle
EDIT: to prevent the function from repeating itself:
var pos = false;
$(window).scroll(function(){
if(($(window).scrollTop() > 400) !== pos ){
alert("changed");
}
pos = $(window).scrollTop() > 400;
});
OR
var pos = false;
$(window).scroll(function(){
if(($(window).scrollTop() > 400) && !pos ){
alert("just passed breakpoint");
}
pos = $(window).scrollTop() > 400;
});
New Fiddle
Try adding it to an event listener like this:
var eventTriggered=false;
$(document).on( 'scroll', function(){
if($(document).scrollTop() > 400 && !eventTriggered) {
alert("success");
eventTriggered=true;
}else if($(document).scrollTop() < 400){
eventTriggered=false;
}
});
This one works

Javascript scroll issue in Opencart theme

I'm working on a project based on Opencart with the theme Tranda Social (I think it's deprecated). The problem I'm facing is that at Home page ONLY I can't get the scroll-effects (eg. When scrolling-down keep the navbar in fixed position, or getting to the TOP by just clicking the button with the UP-arrow). After some research I've concluded that for some reason a Javascript function isn't get called correctly.
setTimeout(function () {
/* Menu */
$('#menu ul > li > a + div').each(function (index, element) {
var menu = $('#menu').offset();
var dropdown = $(this).parent().offset();
i = (dropdown.left + $(this).outerWidth()) - (menu.left + $('#menu').outerWidth());
if (i > 0) {
$(this).css('margin-left', '-' + (i + 5) + 'px');
}
});
/* Fixed Menu */
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('#bottomh').offset().top;
$(window).scroll(function (event) {
var y = $(this).scrollTop();
if (y >= top) {
$('#bottomh').addClass('bottomfixed');
} else {
$('#bottomh').removeClass('bottomfixed');
}
});
}
});
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('#bottomh').offset().top;
$(window).scroll(function (event) {
var y = $(this).scrollTop();
if (y >= top) {
$('#bottomh').addClass('bottomfixed');
} else {
$('#bottomh').removeClass('bottomfixed');
}
});
}
});
/* Margin Menu */
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('#bottomh').offset().top;
$(window).scroll(function (event) {
var y = $(this).scrollTop();
if (y >= top) {
$('#container').addClass(' topmargin');
} else {
$('#container').removeClass(' topmargin');
}
});
}
});
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('#bottomh').offset().top;
$(window).scroll(function (event) {
var y = $(this).scrollTop();
if (y >= top) {
$('#container').addClass(' topmargin');
} else {
$('#container').removeClass(' topmargin');
}
});
}
});
}, 500);
The functions after fixed-menu and margin-menu comments are NOT working when I'm navigating in Home page. Also if you notice, there is a duplicate of each function (don't know for what reason). Have you any ideas? Any help will be greatly appreciated.
It was a problem caused by Slidesshow module (Nivo Slider) because of a JS error related to it. Uninstall-reinstall the module fixes the problem.

Jquery - Detect Window Width

i have this little script where i try to detect the window size to apply the limit of caracters of an element.
the problem the detection is not working. Always apply the limit of 150.
i have set an alert to look if detect or not, and now i´m sure that he is always apply the same.
can someone help me to find out what is wrong with this script?
here is my code:
$(function () {
$(".block6 p").each(function (i) {
len = $(this).text().length;
if (len > 10) {
if ($(window).width() <= 1280) {
$(this).text($(this).text().substr(0, 150) + '...');
}
else if ($(window).width() > 1280) {
$(this).text($(this).text().substr(0, 10) + '...');
}
}
});
});
Your code only runs once, on document.ready. You need to run the test every time the window is resized:
$(window).on('resize',function() {
if ($(window).width() <= 1280) {
$(".block6 p").each(function (i) {
var len = $(this).text().length;
if (len > 10) {
$(this).text($(this).text().substr(0, 150) + '...');
}
});
} else { //if ($(window).width() > 1280) {
$(".block6 p").each(function (i) {
var len = $(this).text().length;
if (len > 10) {
$(this).text($(this).text().substr(0, 10) + '...');
}
});
}
});
$(document).ready(function() {
$(window).trigger('resize');
}
http://jsfiddle.net/mblase75/6PQ4Q/
That said, you have a problem in that you're altering the text of each element directly, so switching back and forth by resizing the browser will be destructive. I suggest using text-overflow: ellipsis instead if possible.

Limit 'mousewheel' delta to fire once per scroll

I'm using the following code below, to scroll two divs in different directions () but I'm curious to know if you can limit the scroll so it only fires once per scroll (rather than it continually scrolling and sending my functions into an endless loop.
$('.page-left, .page-right').bind('mousewheel', function(event, delta) {
var windowHeight = $(window).height();
if (delta < 0) {
prevProject();
}
if (delta > 0) {
nextProject();
}
});
You can see where I'm up up to here: http://dev.rdck.co/lyonandlyon/
Thanks in advance,
R
Animation functions for reference:
var prevProject = function() { // up arrow/scroll up
var windowHeight = $(window).height();
$('.page-left .page-left-wrapper').css({bottom:'auto'});
$('.page-left .page-left-wrapper').animate({top:0},800, function() {
$('.page-left .page-left-wrapper').prepend($('.page-left .project-left:last-of-type'));
$('.page-left .page-left-wrapper').css({top:-windowHeight});
});
$('.page-right .page-right-wrapper').css({top:'auto'});
$('.page-right .page-right-wrapper').animate({bottom:+windowHeight*2},800, function() {
$('.page-right .page-right-wrapper').append($('.page-right .project-right:first-of-type'));
$('.page-right .page-right-wrapper').css({bottom:+windowHeight});
});
};
var nextProject = function() { // down arrow/scroll down
var windowHeight = $(window).height();
$('.page-left .page-left-wrapper').animate({top:0},800, function() {
$('.page-left .page-left-wrapper').prepend($('.page-left .project-left:last-of-type'));
$('.page-left .page-left-wrapper').css({top:-windowHeight});
});
$('.page-right .page-right-wrapper').animate({bottom:+windowHeight*2},800, function() {
$('.page-right .page-right-wrapper').append($('.page-right .project-right:first-of-type'));
$('.page-right .page-right-wrapper').css({bottom:+windowHeight});
});
};
You can just check for animation within the mousewheel function (demo)
$('.page-left, .page-right').on('mousewheel', function(event, delta) {
if ($('.page-left-wrapper, .page-right-wrapper').is(':animated') ) {
return false;
}
var windowHeight = $(window).height();
if (delta < 0) {
prevProject();
}
if (delta > 0) {
nextProject();
}
});
Update: we resolved to use debounce as the long scroll (sliding a finger down a touchpad) needed to be stopped (updated demo).
$(document).keydown( $.debounce( 250, function(e) {
switch (e.which) {
case 38: // up arrow
prevProject();
break;
case 40: // down arrow
nextProject();
break;
}
}) );
$('.page-left, .page-right').on('mousewheel', $.debounce( 250, function(event, delta) {
var windowHeight = $(window).height();
if (delta < 0) {
prevProject();
}
if (delta > 0) {
nextProject();
}
}) );
You can get around this problem with a flag. You can use a global flag isAnimating and set it to true, if you are currently animating the position of the divs of your website.
So the code can look something like this:
var isAnimating = false;
$('.page-left, .page-right').bind('mousewheel', function(event, delta) {
// if the div will be animated at this moment return
if(isAnimating) {
return;
}
var windowHeight = $(window).height();
if (delta < 0) {
prevProject();
}
if (delta > 0) {
nextProject();
}
});
var prevProject = function() {
isAnimating = true;
var oneIsDone = false,
finish = function() {
// if both animations are done, set the flag to false
if(oneIsDone) {
isAnimating = false;
}
// at least one is done...
oneIsDone = true;
};
// animate the previous project and set the flag to false (in the callback)
$('.page-left .page-left-wrapper').css({bottom:'auto'});
$('.page-left .page-left-wrapper').animate({top:0},800, function() {
$('.page-left .page-left-wrapper').prepend($('.page-left .project-left:last-of-type'));
$('.page-left .page-left-wrapper').css({top:-windowHeight});
finish();
});
$('.page-right .page-right-wrapper').css({top:'auto'});
$('.page-right .page-right-wrapper').animate({bottom:+windowHeight*2},800, function() {
$('.page-right .page-right-wrapper').append($('.page-right .project-right:first-of-type'));
$('.page-right .page-right-wrapper').css({bottom:+windowHeight});
finish();
});
};
var nextProject = function() {
// the same as in the prevProject function, but only in the other direction
};
I suggest to detect extremums to fire the function:
var mw1 = 0;
var mw2 = 0;
var lock;
$(document).bind('mousewheel', function(evt) {
var delta = evt.originalEvent.deltaY
if(((delta > 0 && delta < mw2 && mw2 > mw1) || (delta < 0 && delta > mw2 && mw2 < mw1)) && !lock){
console.log(mw1 + " " + mw2 + " " + delta)
// call some function here
lock = true;
window.setTimeout(function(){
lock = false;
},200)
}
mw1 = mw2;
mw2 = delta;
})
lock is actually should not be necessary but extremums sometimes are found more than once per scroll for some reason.

Perform an action when near the bottom of the page

Javascript code:
var next_page = 2;
var next_previews = 36;
function ajax_autopaginate(a, b) {
function incrementPage () {
next_page += 1;
next_previews += 36;
}
jQuery('#' + b).load(a , function() {
incrementPage();
setTimeout(pollScrollPosition, 500);
});
}
function pollScrollPosition() {
var y = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
var max = window.scrollMaxY || (document.body.scrollHeight - document.body.clientHeight);
if ((max - y) <= 1500) {
ajax_autopaginate('http://www.wallpaperup.com/welcome/get_wallpapers/date_added/DESC/' + next_previews + '/','content' + next_page);
} else {
setTimeout(pollScrollPosition, 500);
}
}
setTimeout(pollScrollPosition, 500);
I'm using this code to execute a function if we are 1500px or less from the end of the page, all works good in Firefox, but in IE and Chrome the function is always executed, how should I fix it?
this is the page that gives me problems: http://www.wallpaperup.com/

Categories