I'm getting error from using top property in my jquery code. The code is about navigation dots on my slider. This is the link to my page: http://54.169.61.153/teavana
Below is my code. I'm getting error in the console saying that:
Uncaught TypeError: Cannot read property 'top' of undefined
$(document).ready(function () {
var one = $("#slider").offset();
var two = $("#tabsDiv").offset();
var three = $("#teaWare").offset();
var four = $("#videoo").offset();
$(window).scroll(function () {
var screenPosition = $(document).scrollTop();
if (screenPosition < one.top) {
$(".teavanamenu li a").removeClass("active");
$(".teavanamenu li a.menu1").addClass("active");
}
if (screenPosition >= two.top) {
$(".teavanamenu li a").removeClass("active");
$(".teavanamenu li a.menu2").addClass("active");
}
if (screenPosition >= three.top) {
$(".teavanamenu li a").removeClass("active");
$(".teavanamenu li a.menu3").addClass("active");
}
if (screenPosition >= four.top) {
$(".teavanamenu li a").removeClass("active");
$(".teavanamenu li a.menu4").addClass("active");
}
});
$(window).scroll();
$(".one, .two").click(function () { $(window).scroll(); });
});
I'm not sure why it can't read the property top. Any help?
Related
I am working on a pagination script (code below); and I don't know how to select the current pagination number after clicking on the next previous buttons (I have added a comment to the missing bit below: removeClass('current'); and addClass('current') to active pagination number; ). The style should work the same as directly clicking on the page number $("#pagin li a").click(function()...
here is a picture:
pagination style when current page selected
Thank you in advance for your help!
pageSize = 4;
incremSlide = 5;
startPage = 0;
numberPage = 0;
var pageCount = $(".browsethearchive-items").length / pageSize;
var totalSlidepPage = Math.floor(pageCount / incremSlide);
for(var i = 0 ; i<pageCount;i++){
$("#pagin").append('<li>'+(i+1)+'</li> ');
if(i>pageSize){
$("#pagin li").eq(i).hide();
}
}
var prev = $("<li/>").addClass("prev").html("Prev").click(function(){
startPage-=1;
incremSlide-=1;
numberPage--;
slide();
});
prev.hide();
var next = $("<li/>").addClass("next").html("Next").click(function(){
startPage+=1;
incremSlide+=1;
numberPage++;
slide();
});
$("#pagin").prepend(prev).append(next);
$("#pagin li").first().find("a").addClass("current");
slide = function(sens){
$("#pagin li").hide();
for(t=startPage;t<incremSlide;t++){
$("#pagin li").eq(t+1).show();
}
if(startPage == 0){
next.show();
prev.hide();
}else if(numberPage == totalSlidepPage ){
next.hide();
prev.show();
}else{
next.show();
prev.show();
}
}
showPage = function(page) {
$(".browsethearchive-items").hide();
$(".browsethearchive-items").each(function(n) {
if (n >= pageSize * (page - 1) && n < pageSize * page)
$(this).show();
});
}
showPage(1);
$("#pagin li a").eq(0).addClass("current");
var $listItems = $('#pagin li a');
var activeLink;
$("#pagin li a").click(function() {
$listItems.removeClass('current');
$(this).addClass('current');
var activeLink=$(this);
showPage(parseInt($(this).text()));
});
var i = 1;
$(".prev").click(function() {
// removeClass('current');
// addClass('current') to active pagination number;
if (i != 1) {
showPage(--i);
}
});
$(".next").click(function() {
// removeClass('current');
// addClass('current') to active pagination number;
if (i < ($('.browsethearchive-items').length)/4) {
showPage(++i);
}
});
UPDATE here is a fiddle with the working code — > https://jsfiddle.net/JoChicau/em19ku8v/39/ — > thanks to #biberman!
You can select the list element with the class "current" in this way:
$("#pagin li a.current")
For setting the class "current" to the next or previous list element you can use the jQuery methods next() and prev(). Since you set the class to the anchor inside the list element you first have to select the parent of the anchor with the parent() function to get the list element itself and after using next() or prev() select the anchor inside the new list element with find("a").
Working example:
$(".prev").click(function() {
let prevLi = $("#pagin li a.current").parent().prev().find("a");
if (prevLi[0]) {
$("#pagin li a.current").removeClass("current");
prevLi.addClass("current");
}
});
$(".next").click(function() {
let nextLi = $("#pagin li a.current").parent().next().find("a");
if (nextLi[0]) {
$("#pagin li a.current").removeClass("current");
nextLi.addClass("current");
}
});
ul {
list-style: none;
}
li {
display: inline-block;
width: 20px;
height: 20px;
text-align: center;
}
li:not(.next, .prev) {
background-color: grey;
}
li a.current {
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="pagin">
<li class="prev"><</li>
<li><a class="current">1</a></li>
<li><a>2</a></li>
<li><a>3</a></li>
<li><a>4</a></li>
<li><a>5</a></li>
<li class="next">></li>
</ul>
Additionally i would recommend to add and remove the classes directly to/from the li tag because it makes the script a bit easier (for example no need for parent() and find("a")).
Working example:
$(".prev").click(function() {
let prevLi = $("#pagin li.current").prev();
if (prevLi.find('a')[0]) {
$("#pagin li.current").removeClass("current");
prevLi.addClass("current");
}
});
$(".next").click(function() {
let nextLi = $("#pagin li.current").next();
if (nextLi.find('a')[0]) {
$("#pagin li.current").removeClass("current");
nextLi.addClass("current");
}
});
ul {
list-style: none;
}
li {
display: inline-block;
width: 20px;
height: 20px;
text-align: center;
}
li:not(.next, .prev) {
background-color: grey;
}
li.current {
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="pagin">
<li class="prev"><</li>
<li class="current"><a>1</a></li>
<li><a>2</a></li>
<li><a>3</a></li>
<li><a>4</a></li>
<li><a>5</a></li>
<li class="next">></li>
</ul>
Warning: below code is untested.
Set an id containing the page number on every <a> representing a page. For instance
$("#pagin").append(`<li>${i+1}</li> `);
Then use this id to target the right <a>
$(".prev").click(function() {
if (i != 1) {
i--;
$listItems.removeClass('current');
$(`#pagin li a#page-${i}`).addClass('current');
showPage(i);
}
});
I have a little glitch where when you scroll to the very top of my page the class active (which detects the active section of my page and underlines the fitting link in my navbar) gets removed from #home. I tried to fix that using something like this:
var st = $(this).scrollTop();
var id = $(this).attr('id');
if (st.scrollTop == 0) {
$('a[href="#' + id + '"]').parent('li').addClass('active');
}
This didn't quite work.
This is the rest of my javascript:
$(document).ready(function () {
var navTop = $('#navbar').offset().top;
var navHeight = $('#navbar').height();
var windowH = $(window).height();
$('.section').height(windowH);
$(document).scroll(function () {
var st = $(this).scrollTop();
var id = $(this).attr('id');
if (st.scrollTop == 0) {
$('a[href="#' + id + '"]').parent('li').addClass('active');
}
// for the nav bar:
// if (st > navTop) {
// $('#navbar').addClass('fix');
// $('.section:eq(0)').css({
// 'margin-top': navHeight
// }); //fix scrolling issue due to the fix nav bar
// } else {
// $('#navbar').removeClass('fix');
// $('.section:eq(0)').css({
// 'margin-top': '0'
// });
// }
$('.section').each(function (index, element) {
if (st + navHeight > $(this).offset().top && st + navHeight <= $(this).offset().top + $(this).height()) {
$(this).addClass('active');
var id = $(this).attr('id');
$('a[href="#' + id + '"]').parent('li').addClass('active');
// or $('#nav li:eq('+index+')').addClass('active');
} else {
$(this).removeClass('active');
var id = $(this).attr('id');
$('a[href="#' + id + '"]').parent('li').removeClass('active');
//or $('#nav li:eq('+index+')').removeClass('active');
}
});
});
});
I unfortunately lost the source from where I got the code(s).
I checked if my page was at the top with
if(window.scrollY==0)
and when it was I added the class active
{
element.classList.add("active");
}
and this somehow worked :D
I use same concept like your code. But, I make it separately to make easier to understand. Firstly, take offset and height of every section. Secondly, calculate if the scrolling page between the element. Lastly, if the scrolling page between element set active on the target. You can call the element which have id, just by type the id; I got this when I want to make sure if the script success to load, so I set the id same as the object, when I use the id it became the element.
JavaScript
document.addEventListener("DOMContentLoaded", function(){
if (!window.$) location.reload(); //Sometimes jQuery failed to load, so I reload the page
//Take pos (offset) and height elelement
var pH = [];
$("section").each(function(){
pH.push([this.offsetTop, $(this).height()]);
});
$(window).on("scroll", function(){
var pos = this.scrollY + $(sc).height(), //Position when scrolling
index = pH.findIndex(x => pos >= x[0] && pos <= x[0]+x[1]); //index element of position scrolling between the element
if (index >= 0) {
//Make sure only 1 class "active"
//Remove all class "active" then add class "active" on above element
$("span", sc) //sc is an id's element
.removeClass("active")
.eq(index).addClass("active");
}
else {
//Remove class "active" If the scrolling position outside the element
$("span.active", sc).removeClass("active");
}
})
})
CSS
#sc > .active {
color: white;
text-decoration: underline;
}
section {
display: flex;
align-items: center;
justify-content: center;
font-size: 20vw;
height: 100vh;
border: 1px solid black;
}
HTML
<div class="fixed-top bg-primary" id="sc" style="color: lightblue;">
<span>1</span>
<span>2</span>
<span>3</span>
</div>
<section>1</section>
<section>2</section>
<section>3</section>
<p style="padding: 60vh 0;">Hi</p>
This is JS, I try to change "touch" to "click", but nothing happens:
$(document).ready(function(){
var touch = $('#resp-menu');
var menu = $('.menu');
$(touch).on('click', function(e) {
e.preventDefault();
menu.slideToggle();
});
$(window).resize(function(){
var w = $(window).width();
if(w > 767 && menu.is(':hidden')) {
menu.removeAttr('style');
}
});
});
You can see the full dropdown menu here:
http://codepen.io/anon/pen/ygbpmV
.menu li:hover>ul {
visibility: visible;
opacity: 1;
transform: translate(0,0);
}
replace with
.menu li.active>ul {
visibility: visible;
opacity: 1;
transform: translate(0,0);
}
JS
$(document).ready(function(){
var touch = $('#resp-menu');
var menu = $('.menu li');
$(menu).on('click', function(e) {
e.preventDefault();
$(this).addClass('active');
}).on('mouseleave',function(){
$(this).removeClass('active');
});
$(window).resize(function(){
var w = $(window).width();
if(w > 767 && menu.is(':hidden')) {
menu.removeAttr('style');
}
});
});
You are actually setting the onclick function as it's supposed to be.
You can test this by writing this in the developers console.
var touch = $('#resp-menu');
touch.click();
The issue here is that the "touch" element can't be clicked because you can't see it.
Perhaps you should think again where do you want the event to happen.
I have a script that changes the way my menu looks when you scroll past a certain point, to stop it repeating my animation over and over again I have put in a $(window).off("scroll"); so it only executes once. I need the menu to change back again when I scroll back past the same point again, but once I have turned off scroll, is there a way I can turn it back on at certain point?
This is what I have so far:
var Header = $('#header');
var Navbar = $('.navbar');
var links = $(".navbar ul.nav > li > a");
var HeaderH = Header.height();
var NavbarH = Navbar.height();
$(window).on("scroll", function(){
if ($(this).scrollTop() === (HeaderH + 64)) {
$(window).off("scroll");
Navbar.addClass('navbar-fixed-top')
links.css('padding', '10px 20px 10px 20px');
Header.css('margin-bottom', '64px');
$('.navbar-fixed-top').css('top', '-64px')
$('.navbar-fixed-top').animate({'top' : '0'}, 1000);
}
});
Just toggle a custom class :
var Header = $('#header');
var Navbar = $('.navbar');
var links = $(".navbar ul.nav > li > a");
var HeaderH = Header.height();
var NavbarH = Navbar.height();
$(window).on("scroll", function(){
if ($(this).scrollTop() >= (HeaderH + 64)) {
if (!Navbar.hasClass('myclass')) {
Navbar.addClass('navbar-fixed-top myclass')
$('.navbar-fixed-top').stop().animate({'top' : '0'}, 1000);
}
} else {
Navbar.removeClass('navbar-fixed-top myclass');
}
});
And CSS :
.myclass {
padding: 10px 20px;
margin-bottom: 64px;
top: -64px;
}
I have some jQuery that needs to activate depending on the window size.
The current code I have does trigger correctly when the page is loaded, but if I resize the window the jQuery does not enable or disable according to the size of the screen
$(document).ready(function() {
var width = $(window).width();
if ((width < 980)) {
$( '.navigation > ul > li > a' ).click(function() {
if($(this).next('ul').is(':visible')){
$(this).next("ul").slideUp(400);
} else {
$( '.navigation > ul > li > ul' ).slideUp(400);
$(this).next("ul").slideToggle(400);
}
});
$( '.navigation > ul > li > ul > li > a' ).click(function() {
if($(this).next("ul").is(":visible")){
$(this).next("ul").slideUp(400);
} else {
$( '.navigation > ul > li > ul > li > ul' ).slideUp(400);
$(this).next("ul").slideToggle(400);
}
});
$( '.menu-link' ).click(function() {
if($(this).next("div").is(':visible')){
$(this).next("div").slideUp(400);
} else {
$( '.navigation' ).slideUp(400);
$(this).next('div').slideToggle(400);
}
});
}
});
Effectively what I need is for the jQuery to trigger under a screen size of 980px and disable over that figure.
As an extra googly I need to make sure that any expanded elements are able to close or are closed when the page size exceeds 980px as over this size the usual CSS media queries take effect on hover.
An earlier version of my code was able to take into account of a dynamic window size, but left the expanded items open and unable to close since the jQuery no longer functioned.
In case it helps here's a fiddle
You need to use window.onresize method.
EDITED CODE
// flag to check that events doesn't bind twice
var isNavigationEventsEnable = false;
// enable events
var enableNavigationEvents = function () {
$(".navigation > ul > li > a").on('click.screen-lt-980', function () {
if ($(this).next("ul").is(":visible")) {
$(this).next("ul").slideUp(400);
} else {
$(".navigation > ul > li > ul").slideUp(400);
$(this).next("ul").slideToggle(400);
}
});
$(".navigation > ul > li > ul > li > a").on('click.screen-lt-980', function () {
if ($(this).next("ul").is(":visible")) {
$(this).next("ul").slideUp(400);
} else {
$(".navigation > ul > li > ul > li > ul").slideUp(400);
$(this).next("ul").slideToggle(400);
}
});
$(".menu-link").on('click.screen-lt-980', function () {
if ($(this).next("div").is(":visible")) {
$(this).next("div").slideUp(400);
} else {
$(".navigation").slideUp(400);
$(this).next("div").slideToggle(400);
}
});
}
// disable events
var disableNavigatioEvents = function () {
$(".navigation > ul > li > a").off('click.screen-lt-980');
$(".navigation > ul > li > ul > li > a").off('click.screen-lt-980');
$(".menu-link").off('click.screen-lt-980');
}
// call this method on window resize
var redesignScreen = function () {
//function (e) { // comment this line
var width = $(window).width();
if ((width < 980)) {
if (!isNavigationEventsEnable) {
isNavigationEventsEnable = true;
enableNavigationEvents();
}
} else {
isNavigationEventsEnable = false;
disableNavigatioEvents();
}
//} // comment this line
}
$(document).ready(function () {
// attach onresize function
window.onresize = redesignScreen;
// calling redesignScreen initially
redesignScreen();
});
JSFiddle: http://jsfiddle.net/hEtTg/2/
WITH FORCE CLOSE
// flag to check on that events doesn't bind twice
var isNavigationEventsEnable = false;
// enable events
var enableNavigationEvents = function () {
$(".navigation > ul > li > a").on('click.screen-lt-980', function (e, data) {
data = (typeof data == 'undefined') ? {} : data;
if ($(this).next("ul").is(":visible") || data.forceClose) {
$(this).next("ul").slideUp(400);
} else {
$(".navigation > ul > li > ul").slideUp(400);
$(this).next("ul").slideToggle(400);
}
});
$(".navigation > ul > li > ul > li > a").on('click.screen-lt-980', function (e, data) {
data = (typeof data == 'undefined') ? {} : data;
if ($(this).next("ul").is(":visible") || data.forceClose) {
$(this).next("ul").slideUp(400);
} else {
$(".navigation > ul > li > ul > li > ul").slideUp(400);
$(this).next("ul").slideToggle(400);
}
});
$(".menu-link").on('click.screen-lt-980', function (e, data) {
data = (typeof data == 'undefined') ? {} : data;
if ($(this).next("div").is(":visible") || data.forceClose) {
$(this).next("div").slideUp(400);
} else {
$(".navigation").slideUp(400);
$(this).next("div").slideToggle(400);
}
});
}
// disable events
var disableNavigatioEvents = function () {
$(".navigation > ul > li > a").trigger('click', [{
forceClose: true
}]);
$(".navigation > ul > li > ul > li > a").trigger('click', [{
forceClose: true
}]);
$(".menu-link").trigger('click', [{
forceClose: true
}]);
$(".navigation > ul > li > a").off('click.screen-lt-980');
$(".navigation > ul > li > ul > li > a").off('click.screen-lt-980');
$(".menu-link").off('click.screen-lt-980');
}
// call this method on window resize
var redesignScreen = function () {
// function (e) { // comment this line
var width = $(window).width();
if ((width < 980)) {
if (!isNavigationEventsEnable) {
isNavigationEventsEnable = true;
enableNavigationEvents();
}
} else {
isNavigationEventsEnable = false;
disableNavigatioEvents();
}
// } // comment this line
}
$(document).ready(function () {
// attach onresize function
window.onresize = redesignScreen;
// calling redesignScreen initially
redesignScreen();
});
JSFiddle:http://jsfiddle.net/hEtTg/3/
Hopes it helps.