I need help with this since it's showing and I tried with global variable etc an issue remains..
var $ = jQuery;
var $window = $(window),
$moving1 = $(".scroller1"),
$holder1 = $("#scroller-wrap1"),
offset1;
$window.load(function() {
offset1 = $holder1.offset();
});
$window.scroll(function() {
if ($window.scrollTop() > offset1.top) {
$moving1.addClass('fixed');
} else {
$moving1.removeClass('fixed');
}
if ($window.scrollTop() > (offset1.top + $holder1.height() - $moving1.height() - 60)) {
$moving1.removeClass('fixed', 1000);
}
//console.log("scroll: " +$window.scrollTop());
});
Basically I am checking if the windows if fully loaded so I can make the calculations without error but I guess it's not correct.
This is inside wordpress that's why I need the jQuery part.
Ok. The error is coming from this command:
if ($window.scrollTop() > offset1.top) {
and it means that offset1 is undefined. Now, you are initializing offset1 in your .load event, but you are setting it equal to $holder and $holder1 is initialized before the document is ready, so it becomes undefinded.
Your code can be reduced greatly by just adding a document.ready function. You also don't have to do this var $ = JQuery as that is automatic.:
// Passing a function to JQuery creates a "document.ready()" callback
// function that will automatically be executed when the DOM is built.
$(function(){
var $window = $(window);
var $moving1 = $(".scroller1");
var $holder1 = $("#scroller-wrap1");
var offset1 = $holder1.offset();
// JQuery recommends the use of the .on() function to bind
// event callbacks as opposed to event methods.
$window.on("scroll", function() {
if ($window.scrollTop() > offset1.top) {
$moving1.addClass('fixed');
} else {
$moving1.removeClass('fixed');
}
if ($window.scrollTop() > (offset1.top + $holder1.height() - $moving1.height() - 60)) {
$moving1.removeClass('fixed', 1000);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Related
My code seems to be working fine on JSfiddle, but once im placing it to the a webpage that has jquery already loaded in the DOM, i get this console error, as seen on the screenshot.
The iframe selector that I do target, exists.
Any ideas?
$(document).ready(function() {
var stickyTop = $("iframe[id*='google_ads_iframe']").offset().top;
$(window).scroll(function() {
var windowTop = $(window).scrollTop();
if (stickyTop < windowTop && $(".adSlot.headBanner").height() - $(".sticky").height() > windowTop) {
$("iframe[id*='google_ads_iframe']").css('position', 'fixed');
} else {
$("iframe[id*='google_ads_iframe']").css('position', 'relative');
}
});
});
$("iframe[id*='google_ads_iframe']")
will return array. You need to iterate through each of them.
Something like this
$("iframe[id*='google_ads_iframe']").each(function(i, val){
$(val).offset().top;
...
});
What I would like to do is have a JavaScript file which would contain jQuery functions that are used across multiple sites (all hosted on the same CMS - eTouches, so there is no cross domain scripting issue) and then have a site specific JavaScript file for each site which utilised the functions, making it easy to change the central function file as needed.
I am getting errors when trying to do this though, with functions not being defined when the second script it trying to execute things. Is this a possible and have I missed something basic or is it something that is not possible.
I don't think it is possible to include files as you do in PHP etc, but if I call the functions file before the site specific one I thought this should work?
Thanks in advance for any help.
Code from function document
$.noConflict();
jQuery(document).ready(function ($) {
$('☰ Menu').insertBefore($('.ehtm'));
if ($('#right_sidebar_section').length) {
} else {
$('#main_section').css('width','100%')
$('#main_section').css('marginLeft','0')
}
var mobileMenu = function (menuParent, prevSibling, menuIdentifier) {
if ($('#mobileMenu').length == 0) {
var $select = $('<div>', {
'class': 'mobile-menu',
'id': menuIdentifier
}).insertBefore(prevSibling);
$('.ehtm > ul').prependTo($('#mobileMenu'));
}
if ($('.expandContract').length==0) {
$('.mobile-menu > ul > li > a').each(function(){
$(this).css("width", "120px");
$('+<span></span>').insertBefore($(this));
})
}
$('.expandContract').click(function (evt) {
evt.preventDefault();
$(this).text($(this).text() == '+' ? '-' : '+');
$(this).parent().find("ul").slideToggle();
evt.stopImmediatePropagation();
})
};
var menuReset = function () {
$('.mobile-menu > ul').prependTo($('.ehtm'));
$('#mobileMenu').remove();
if (parseInt($('#outer_table').css('margin-left')) > 0) {
$('#outer_table').animate({
marginLeft: parseInt($('#outer_table').css('marginLeft'), 10) == 0 ? 200 : 0
});
}
$('a.expandContract').each(function(){
$(this).remove();
})
$('.ehtm > ul > li > a').each(function(){
$(this).css('width','auto');
})
}
$('.mobile-menu-toggle-link').click(function (evt) {
evt.preventDefault();
$('#outer_table').animate({
marginLeft: parseInt($('#outer_table').css('marginLeft'), 10) == 0 ? 200 : 0
});
$('.header').animate({
marginLeft: parseInt($('#outer_table').css('marginLeft'), 10) == 0 ? 200 : 0
});
$('.mobile-menu').animate({
marginLeft: parseInt($('#outer_table').css('marginLeft'), 10) == 0 ? 0 : -200
});
var wHeight = $(window).innerHeight();
var divHeight = $('#mobileMenu').height();
if (wHeight > divHeight) {
$('.mobile-menu').css("height", wHeight);
} else {
$('.mobile-menu').css("height", divHeight);
}
})
var compareWidth = $('.header').width();
/* Add class to the first table row, to allow header styling */
var headRow = $("table#outer_table").find("tr:first");
$(headRow).addClass("headerBGColor");
});
Code from site specific document
$.noConflict();
jQuery(document).ready(function ($) {
var compareWidth = $('.header').width();
var setUpPage = function () {
if (compareWidth < 768) {
mobileMenu('.ehtm li', '.header', 'mobileMenu');
}
if (compareWidth >= 768) {
menuReset();
}
/* Header image swap */
if (compareWidth>=1024) {
$("#headerImage").attr("src","https://www.eiseverywhere.com/image.php?acc=xxx&id=xxxxxx");
} else if ((compareWidth>=768) && (compareWidth<1024)) {
$("#headerImage").attr("src","https://www.eiseverywhere.com/image.php?acc=xxx&id=xxxxxx");
} else {
$("#headerImage").attr("src","https://www.eiseverywhere.com/image.php?acc=xxx&id=xxxxxx");
}
/* Carousel */
if ($('.owl-carousel').length > 0) {
$('.owl-carousel').owlCarousel({
items:1,
loop:true,
margin:10,
autoplay:true,
autoplayTimeout:3000,
dots:true
});
}
}
var breakPointCheck = function () {
var currentWidth = $('.header').width();
if (currentWidth != compareWidth) {
compareWidth = currentWidth;
setUpPage();
}
}
setUpPage();
// fixElement('.tabmenu')
$(window).resize(function () {
breakPointCheck();
});
});
They are all declared in DOM ready functions which give them a local scope. The functions cannot then be seen outside of that function and each DOM ready function is separate to the others.
You need to declare them as global functions instead (using global vars):
e.g.
// Global scope
var mobileMenu;
$.noConflict();
jQuery(document).ready(function ($) {
// Aside local function to global var
mobileMenu = function(...
The alternative is to declare the functions outside of the DOM ready handlers and make sure they are only called from code inside of DOM ready handlers. Most of the functions shown do not need to be inside DOM ready handlers as they are just declarations and are not run at that point:
e.g.
$.noConflict();
//Declare global functions
var mobileMenu = function (menuParent, prevSibling, menuIdentifier) {
if ($('#mobileMenu').length == 0) {
var $select = $('<div>', {
'class': 'mobile-menu',
...snip...
});
jQuery(document).ready(function ($) {
// Use global functions
mobileMenu(...);
});
Use jQuery.getScript()
In your shared function script, remove the jQuery(document).ready(function () {...}) wrapper.
In your site-specific document, use $.getScript() to load the shared file and place your site-specific functions in a callback that runs after the shared script loads successfully:
jQuery(document).ready(function() {
$.getScript('/url/to/functionScript.js', function () {
// Site specific functions
});
});
I am trying to add class or remove class on getting element top by using This DEMO . Here is the code as well:
$(document).ready(function () {
var sec1_offset = $("#sec1").offset();
var sec2_offset = $("#sec2").offset();
var sec3_offset = $("#sec3").offset();
var sec4_offset = $("#sec4").offset();
var sec5_offset = $("#sec5").offset();
var sec6_offset = $("#sec6").offset();
var sec7_offset = $("#sec7").offset();
$("section").scroll(function () {
if (sec4_offset.top < 100) {
alert("You Are in Sec 4");
}
});
});
I also change the $("section").scroll(function () { to $(body).scroll(function () { and $(document).scroll(function () { but it didn't work!
Can you please let me know what I am doing wrong? Thanks
You can listen to the scroll event of the window object, scroll event like the resize event is fired so many times, for efficiency you can throttle the handler, ie the handler is executed after a specified timeout.
$(document).ready(function () {
var $sec = $("section"),
handle = null;
var $w = $(window).scroll(function () {
// clear the timeout handle
clearTimeout(handle);
// throttling the event handler
handle = setTimeout(function() {
var top = $w.scrollTop();
// filtering the first matched element
var $f = $sec.filter(function() {
return $(this).offset().top + $(this).height() >= top;
}).first().addClass('active');
$sec.not($f).removeClass('active');
}, 50);
}).scroll();
});
http://jsfiddle.net/UTCER/
edit: If you want to add a class to another element, the most efficient way is using the index method:
// Cache the object outside the `scroll` handler
var $items = $('#menu li');
// within the `setTimeout` context:
var $f = $sec.filter(function() {
return $(this).offset().top + $(this).height() >= top;
}).first();
$items.removeClass('active').eq( $sec.index($f) ).addClass('active');
use $(window).scroll for the scroll event listener
also you want to check sec4_offset.top against window.scrollY
JS
$(document).ready(function () {
var sec1_offset = $("#sec1").offset();
var sec2_offset = $("#sec2").offset();
var sec3_offset = $("#sec3").offset();
var sec4_offset = $("#sec4").offset();
var sec5_offset = $("#sec5").offset();
var sec6_offset = $("#sec6").offset();
var sec7_offset = $("#sec7").offset();
$(window).scroll(function () {
if (window.scrollY >= sec4_offset.top) {
alert("You Are in Sec 4");
}
});
});
JSFiddle Demo
Use $(window).scroll()
Here's what jQuery documentation says about scroll event
The scroll event is sent to an element when the user scrolls to a different place in the element. It applies to window objects, but also to scrollable frames and elements with the overflow CSS property set to scroll (or auto when the element's explicit height or width is less than the height or width of its contents).
I know this answer has already been answered, but I'd like to provide an alternative answer on JSFiddle that might accomplish what you're looking for to a more dynamic extent. I would not ask to be voted as the answer, but simply noted as a reference for an alternative approach to this problem
http://jsfiddle.net/mLfAq/5/
$(document).ready(function () {
var offsets = [];
$('[id^="#sec"]').each(function() {
offsets.push([$(this).attr('id'), $(this).offset().top + $(this).height()]);
});
$(window).scroll(function () {
for(var i = 0; i < offsets.length; i++) {
if(offsets[i][1] > $(window).scrollTop()) {
console.log('You are in ' + offsets[i][0]);
return;
}
}
});
});
I am making a simple JS plugin to resize objects vertically. It works fine until the resize event - wherein $flexParent appears to be being set as the last $flexParent in the initial .each() function for all of the binds. So for three 'flexParents' being passed to the plugin, only the last one is getting acted on on the resize event; just 3 times. Obviously I'm misunderstanding binding here but I'd be grateful of some clarity!
(function($){
$.fn.flexHeight = function(options) {
if (!options){options = {};}
var settings = $.extend({
boxes: false
}, options);
function main(flexParent) {
var $flexParent = flexParent;
if (settings.boxes) {
$children = $flexParent.find(settings.boxes);
} else {
$children = $flexParent.children
}
var maxHeight = 0;
$children.each(function() {
$(this).height('auto');
});
$children.each(function() {
maxHeight = maxHeight > $(this).outerHeight(false) ? maxHeight : $(this).outerHeight(false);
});
$children.each(function() {
$(this).height(maxHeight);
});
}
return this.each(function() {
$flexParent = $(this);
main($flexParent);
$(window).resize(function() {
main($flexParent);
});
});
}
}(jQuery));
$flexParent is declared as a global variable, so it's shared between function calls. By the time the window resize callback gets called, the global $flexParent variable will point to the last element.
Change your code to:
return this.each(function() {
var $flexParent = $(this); // <-- added var here
main($flexParent);
$(window).resize(function() {
main($flexParent);
});
});
This makes the $flexParent local to the function passed to each, so there will be one variable for each element.
My following code will not function, unless I place it all
$(window).load(function(){
// within here
}
How can I get my code to run without requiring the above function?
Thanks!
My code:
// Player controls
var timer = null;
$('#left').mousedown(function() {
moveLeft(); // Do it now
timer = setInterval(moveLeft, 5); // Then every 100 ms
}).mouseup(function() {
clearInterval(timer); // And stop it
});
function moveLeft() {
var nextpos = parseInt($('#player').css('left')) - 5;
if (nextpos > 0) {
$('#player').css('left', nextpos + 'px');
}
}
$('#right').mousedown(function() {
moveRight(); // Do it now
timer = setInterval(moveRight, 5); // Then every 100 ms
}).mouseup(function() {
clearInterval(timer); // And stop it
});
function moveRight() {
var nextpos = parseInt($('#player').css('left')) + 5;
if (nextpos < PLAYGROUND_WIDTH - 100) {
$("#player").css("left", ""+nextpos+"px");
}
}
// Timer
$(function(){
var timercount = 30;
countdown = setInterval(function(){
$("#timer").html(timercount);
if (timercount <= 0) {
$("#timer").html("TIMES UP");
}
timercount--;
}, 1000);
});
I'm going to assume you're not trying to get a comparison of why you need $(window).load and not $.ready. Anyway, javascript is run as it's seen. You've got jquery looking up elements (#right, #player, etc) that probably haven't been loaded into the page yet. So, because these elements are not on the page, jQuery can't bind these events to them.
Read this through - it may more thoroughly answer your question. http://api.jquery.com/ready/
If you run the code at the end of the page, rather than in the header, those elements should be loaded by the time the javascript runs.
That said, if your code is comparing the size of images, the images need to be loaded first...
You have to put it below your HTML..
<body>
//your html stuff here that uses the script
<script type="text/javascript">
// the js code here
</script>
</body>