I have some jquery code that is picking up some issues in firebug chrome.
any help would be great, please update fiddle.
please see the link with fiddle.
http://jsfiddle.net/jwhTd/
image
/* SHOW CATEGORIES
===================================================================*/
$('.normal-btn\.interest').click(function(e){
// Prevent the event from bubbling up the DOM tree
e.stopPropagation();
$('.categories-wrap').fadeIn(); // must be hidden, to fade in
});
$(document, '.normal-btn\.interest').click(function(){
$('.categories-wrap').fadeOut(); // must be visible, to fade out
});
var offset = $(".sticky-header").offset();
var sticky = document.getElementById("sticky-header")
var additionalPixels = 50;
$(window).scroll(function () {
if ($(window).scrollTop() > offset.top - additionalPixels) {
$('#profile-container').addClass('fixed');
} else {
$('#profile-container').removeClass('fixed');
}
});
It's telling you exactly what is wrong. offset is undefined. You probably expect that it has a value, check why it doesn't have one.
You get more errors though. Something about slider and another about an invalid .top access somewhere.
it looks like most of that code is not in the document.ready. the var offset = $(".sticky-header").offset(); needs to be executed once the dom is ready.
Your code:
var offset = $(".sticky-header").offset();
var sticky = document.getElementById("sticky-header")
var additionalPixels = 50;
The first line selects all elements with the class of sticky-header, then gets the offset of the first one. The .offset() function returns undefined in the event that the selector matches zero elements, which appears to be the case here due to the error you're getting later on.
On the next line you're selecting an element with an id of sticky-header, which makes me think that perhaps your first line should be
var offset = $('#sticky-header').offset();
instead, which uses an ID selector rather than a class one.
Related
I'm trying to make a simple scrollspy with jQuery Scroll event but it fails. Here is my JavaScript part:
<script>
$(document).ready(function(){
$("#credit_card").scroll(function(){
console.log('OK');
});
});
</script>
And HTML part:
<section class="method first-of-group" id="credit_card">
...
</section>
As you might have guessed, console.log is just for testing. This section is under a div and this div has "content" id. If I change my JavaScript code for "content" id, it is working. It's really weird.
If you want to see it live, please visit here.
Thanks in advance.
After reading the comments and actually understanding what you mean, this is the solution you are looking for.
$(document).ready(function(){
$("#content").scroll(function(){
// when the user scrolls, we want to detect at what section they currently are.
// This can be calculated, by comparing the current window scrolltop to the position and height of the section elements.
var currentTopOffset = $(document).scrollTop();
$('section').each(function(){
var min = $(this).offset().top;
var max = $(this).offset().top + $(this).height();
if(currentTopOffset > min && currentTopOffset < max){
// current section
// do something here, like getting a value from an input type hidden with the section name
}
});
});
});
I hope this is what you are looking for, or atleast something to get you started with.
I need to make sure that a specific line is visible when the user loads the page, even if that line appears many lines later in the page. In other words, when the page loads, it instantly jumps to that marked line. The line simply needs to be somewhere within the visible screen of the browser window. It is marked like this:
<div class="scrollhere">This line should always be visible when the page loads.</div>
Only one of these appears on the whole page.
I cannot edit the HTML marking the text, but can edit the CSS and JavaScript at the beginning of the document.
I do not mean for just that specific line to be moved, i.e. with position:absolute, but that the page loads to that line.
How can I make the page load mid-way down the page, wherever a specific <div class="scrollhere"> is found?
So if you can't edit the HTML at all, then you'll need to use JavaScript or jQuery. This is a function that I've used to scroll to an element.
Javascript
This will query the DOM for all elements that have your class scrollhere. And we'll select just the first item in the array (to go to the first element). Then we'll use the scrollIntoView().
document.getElementsByClassName('scrollhere')[0].scrollIntoView()
jQuery
/*
* A scrollTo function that gets passed a selector (ID, class, element) & an optional offset
*
* #param {string} location ('#resultsTop')
* #param {integer} offset (-100)
*/
function scrollTo(location, offset) {
$("html, body").animate({scrollTop: ($(location).offset().top + (offset || 0) )}, "slow");
return false;
};
In your case, you'd call this function as follows:
scrollTo('.scrollhere');
You could also optionally pass in an offset. So maybe you don't want to scroll to the top of that element. But would rather scroll to 100 pixels above it.
scrollTo('.scrollhere',-100);
And being that you can't edit the HTML, then you'll definitely want to use a listener.
$(document).ready(function(){
scrollTo('.scrollhere',-100);
});
This is a pure JavaScript example. No jQuery required.
Here is a simple example of this answer in JSFiddle.
window.onload = function() {
var divs = document.getElementsByTagName("div");
for (var i in divs) {
if (divs[i].className.indexOf("class2") > -1) {
//Finds top of of the element
var top = 0;
var obj = divs[i];
if (obj.offsetParent) {
do {
top += obj.offsetTop;
} while (obj = obj.offsetParent);
}
//Scroll to location
window.scroll(0, top);
break;
}
}
};
This snippet may help you
$('html, body').animate({
scrollTop: ($('.class').first().offset().top)
},500);
I have this code and it works exactly as I want. The menu bar sits on top and recognizes the section it is on or in. You can click the links in the yellow menu to move between the sections.
Demos: http://jsfiddle.net/spadez/2atkZ/9/ and http://jsfiddle.net/spadez/2atkZ/9/embedded/result/
$(function () {
var $select = $('#select');
var $window = $(window);
var isFixed = false;
var init = $select.length ? $select.offset().top : 0;
$window.scroll(function () {
var currentScrollTop = $window.scrollTop();
if (currentScrollTop > init && isFixed === false) {
isFixed = true;
$select.css({
top: 0,
position: 'fixed'
});
$('body').css('padding-top', $select.height());
} else if (currentScrollTop <= init) {
isFixed = false;
$select.css('position', 'relative');
$('#select span').removeClass('active');
$('body').css('padding-top', 0);
}
//active state in menu
$('.section').each(function(){
var eleDistance = $(this).offset().top;
if (currentScrollTop >= eleDistance-$select.outerHeight()) {
var makeActive = $(this).attr('id');
$('#select span').removeClass('active');
$('#select span.' + makeActive).addClass('active');
}
});
});
$(".nav").click(function (e) {
var divId = $(this).data('sec');
$('body').animate({
scrollTop: $(divId).offset().top - $select.height()
}, 500);
});
});
However, the code itself gets quite laggy as soon as you start putting any content in the boxes. According to help I've received, it's that I am repeatedly changing page layout properties via the animation and querying page layout properties in the scroll handler, thus triggering a large number of forced layouts.
User Tibos said that:
You could get a big improvement by disabling the scroll handler during
the click animation and instead triggering the effects with no checks
made (set the active class on the clicked element).
Could anyone show me how I can achieve this optimization?
Demo page and another concept demo: http://codepen.io/vsync/pen/Kgcoa
The KEY here is to position your select inside another element, so when it get's FIXED to the screen, it won't affect the other elements by the sudden lack of height it once physically occupied. I've added a little CSS also. It's important to use the jQuery version 1.11 or above, because they fixed a but that caused the same class to be added again and again, regardless if an element already has it. bad for performance. Also, I've used a for loop and not jquery each loop on the sections elements, because a for loop is much faster due to the lack of function callback an each function has. Also, a very important thing is to make sure that every element that can be cached is actually cached, so we don't look for it endlessly in the DOM...
For showing which section we're on, I'm looping on all the sections, starting for the last one, which is important to, and checking if each top has passed the window's top using getBoundingClientRect method for knowing such thing. This helps knowing where we are.
var pos,
$el = $('#select'),
navItems = $el.find('.nav'),
menuHeight = $el[0].clientHeight,
scrollY,
sections = $('.section').toArray(), // cache sections elements
pointOfAttachment = $('.jumbo')[0].clientHeight - menuHeight;
// Bind events
$(window).on('scroll.nav', updateNav)
.on('resize.nav', updateNav);
function updateNav(){
scrollY = window.pageYOffset || document.documentElement.scrollTop;
for( var i = sections.length; i--; ){
if( sections[i].getBoundingClientRect().top < 0 ){
navItems.filter('.' + sections[i].id).addClass('active').siblings().removeClass('active');
break;
}
navItems.removeClass('active');
}
if( scrollY > pointOfAttachment )
$el.addClass('fixed');
else
$el.removeClass('fixed');
}
Why is this optimal?
The key for good performance is to do as minimal as possible to achieve your goal, and minimal here means accessing the DOM as little as possible and changing it even less times than accessing it. This is HIGHLY optimal code which ONLY changes the DOM when a change is required and never in any other situation.
You shouldn't need to do this on each scroll event. You could throttle the event and only run the callback something like every 20ms. The user shouldn't notice. You can do this with underscore, or write your own solution.
Another thing that would ease the lagg is to move as much out of the scroll event callback as possible. You don't need to query $('body') all the time for example, save that to a variable.
Ok, so I have a parent div that contains two divs. The parent div will naturally be as tall as the tallest child div, dictated by content. However, I want the two child divs to be the same dynamic height, regardless of content. Thus, I resolved to JavaScript it. Here's what I have:
<!--- Make main div's same height -->
<script type="text/javascript">
$(window).bind("load", function() {
setDivHeight() {
var left = $('#primary');
var right = $('#secondary');
var maxHeight = Math.max(left.height(), right.height());
left.height(maxHeight);
right.height(maxHeight);
}
});
</script>
However, when I try to run it, I get this message in my console:
Uncaught TypeError: Property '$' of object [object Object] is not a function
I've been digging into this for about 4 hours now, and I've given up hope...
Can anyone tell me what I'm doing wrong???
It sounds like you don't have jQuery included in the page above that code, or you do but something has taken over the $ symbol.
Ensure jQuery is loaded prior to the code, like so (this is just one link you might use):
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
And/or if you have that but something else is using the $ symbol, you can do this with your code:
(function($) {
$(window).bind("load", function() {
// v----- Side note: This looks like a syntax error
setDivHeight() {
var left = $('#primary');
var right = $('#secondary');
var maxHeight = Math.max(left.height(), right.height());
left.height(maxHeight);
right.height(maxHeight);
}
});
})(jQuery);
That uses the jQuery symbol, passing it into a function as the $ argument. Even if $ is something else outside that function, within it, it will be jQuery.
Side note 1: Your code contains a syntax error. Perhaps you meant:
(function($) {
$(window).bind("load", function() {
var left = $('#primary');
var right = $('#secondary');
var maxHeight = Math.max(left.height(), right.height());
left.height(maxHeight);
right.height(maxHeight);
});
})(jQuery);
Side note 2: The window load event happens very late in the load process, after all images are loaded. That may be what you want (for instance, if the height of the divs is partially dictated by images), but if not you might want to use ready instead (in this case, using one of its shortcuts), as it happens sooner:
jQuery(function($) {
var left = $('#primary');
var right = $('#secondary');
var maxHeight = Math.max(left.height(), right.height());
left.height(maxHeight);
right.height(maxHeight);
});
Again, though, maybe you're waiting for the images for a reason.
I'm trying to make some code which finds if a div exists, and if it does then have it fade away slowly. I have this to determine whether or not the div exists
if($('#error').length != 0)
{
$('#error').hide(500);
}
And that does work but only on a refresh, I've been attempting to put it in a timer like this:
var refreshId = setInterval(function()
{
if($('#error').length != 0)
{
$('#error').hide(500);
}
}, 500);
But its not getting rid of the innerHTML! I have some code which on hover alters the innerHTML of the error div so I can fill it up, but for some reason this isn't working, any advice would help!
Thank you!
$("#error").fadeOut(500);
Update:
If you are looking to check for existence:
var msg = $("#error");
if(msg.length) {
msg.fadeOut(500);
}
If you want to empty it:
$("#error").empty();
If you just want to delay 500ms then fade out, do this:
$("#error").delay(500).fadeOut();
To also empty the element, provide a callback to .fadeOut() like this:
$("#error").delay(500).fadeOut(function() {
$(this).html('');
});
There's no need to check .length, if an element that matches the selector isn't present, nothing happens :)
The div you're trying to hide likely hasn't loaded by the time your script runs. Try this; it will defer execution until the DOM is loaded:
$(document).ready(function() {
// put your code here
});
This is a good practice when using jQuery anyway.
Reference: http://docs.jquery.com/Tutorials:Introducing_$(document).ready()