Find error: highlight side menu based on page scrolling position - javascript

Trying to highlight side menu based on page scrolling position. The nice example is shown here.
However, when practising in a different way, not able to get similar effect for scrolling. Codes are here.
$('#sn').on('click', function(event) {
$(this).parent().find('a').removeClass('active');
$(this).addClass('active');
});
$(window).on('scroll', function() {
$('.target').each(function() {
if($(window).scrollTop() >= $(this).position().top) {
var id = $(this).attr('id');
$('#sn a').removeClass('active');
$('#sn a[href=#'+ id +']').addClass('active');
}
});
});
#sn {
width: 20%;
position: fixed;
}
#sn a {
display: block;
color: #000;
padding: 8px 16px;
text-decoration: none;
}
/* Change the link color on hover */
#sn a:hover {
background-color: #555;
color: white;
}
#sn .active {
background-color: #666;
color: rgb(58, 133, 204);
}
#sn .active:hover {
background-color: #4f5f;
color: rgb(235, 157, 13);
}
section {
height: 100vh;
overflow: auto;
background-color: #F7F7F7;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="sn" class="toggle_sn">
About
Education
Social
</ul>
<section class="target" id="abt_sec">
ABOUT
</section>
<section class="target" id="edu_sec">
EDUCATION
</section>
<section class="target" id="soc_sec">
SOCIAL
</section>
What I'm doing wrong? How to debug errors in web designing? Is this jquery version problem (e.g. is in 1.10.1, mine is 3.3.1)?

1) Add class="target" to your sections. Like so:
<section id="abt_sec" class="target">ABOUT</section>
<section id="edu_sec" class="target">EDUCATION</section>
<section id="soc_sec" class="target">SOCIAL</section>
Because jQuery code selects elements with target class $('.target').each(function()
2) Correct last line syntax:
From this:
$('#sn a[href=#'+ id +']').addClass('active');
to this:
$('#sn a[href="#'+ id +'"]').addClass('active');
Because css selector should be in this syntax: #sn a[href="#abt_sec"] instead of: #sn a[href=#abt_sec].
This doesn't work in your case because jQuery v3.3.1, if you change the jQuery version in the working example from jsFiddle from 1.1 to 3.3.1 that one doesn't work either with same error like your example:
Uncaught Error: Syntax error, unrecognized expression: #sn a[href=#abt_sec]
So your code should look like this:
$('#sn').on('click', function(event) {
$(this).parent().find('a').removeClass('active');
$(this).addClass('active');
});
$(window).on('scroll', function() {
$('.target').each(function() {
if($(window).scrollTop() >= $(this).position().top) {
var id = $(this).attr('id');
$('#sn a').removeClass('active');
$('#sn a[href="#'+ id +'"]').addClass('active');
}
});
});
A codepen to see it working: Codepen

Related

hover on dynamically created list

I have a menu with a list of items created dynamically using javascript.
They have different colour and country attributes created using setAttribute.
$("#menuList a").hover(
function() {
var countryName = $(this).attr('country');
var fruitColour = $(this).attr('colour');
$('#toshow').append($("countryName \n fruitColour"));
},
function() {}
);
.toshow {
display: none;
}
#menuList a:hover div.toshow {
top: 0;
right: 0;
display: block;
position: absolute;
z-index: 99999;
background: red;
width: 200px;
height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menubar" id="menuList">
<li>Watermelon</li>
<li>Grapes</li>
<li>Strawberry</li>
<li>Blueberry</li>
</ul>
<div class="toshow" id="toshow"></div>
Here, I want to have a separated hidden div (display at top right of the page or next to the menuList) that does not have any content until any of the <a> tag being hovered, and show its responding two attributes until no more mouse hovered.
The code does not have errors. But I don't see anything in red when the mouse hovered through the list. Is it possible to achieve what I am looking for?
You can use the mouseout event to hide the toshow div with hide as you leave a list element. And at each hover event, you can change the html of toshow to the values of the li element which the user is hovering over and use show to display it.
Also make sure you attach the event handlers after you've inserted the html of the dynamically generated list.:
function displayGeneratedList() {
$('#menuList').html(`
<li>Watermelon</li>
<li>Grapes</li>
<li>Strawberry</li>
<li>Blueberry</li>
`);
$("#menuList a").hover(function() {
var countryName = $(this).attr('country');
var fruitColour = $(this).attr('colour');
$('#toshow').html(`${countryName}<br>${fruitColour}`).show();
});
$('#menuList a').mouseout(function() {
$('#toshow').hide();
});
}
$(document).ready(function() {
displayGeneratedList();
});
#menuList {
display: inline-block;
}
.toshow {
display: none;
float: right;
background: maroon;
width: 200px;
height: 100px;
padding: 5px;
color: white
}
<ul class="menubar" id="menuList">
</ul>
<div class="toshow" id="toshow"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Function only works on second click, then works fine?

I am having trouble with a navigation menu I have created. Basically, the navigation consists of several tabs that is collapsible upon click a button and then expandable when you click that button again. When collapsed, the ends of the tabs are still visible, and when you hover over the tabs will go back out, and go back in when hovering out.
So I have the following navigation laid out:
<ul id="navigation">
<li>Name1</li>
<li>Name2</li>
<li>Name3</li>
<li id = "collapser">Collapse All</li>
</ul>
And I have the following jQuery/javascript laid out to do this:
$("#collapser").click(function(){
if($("#collapser").hasClass("clicked")){
$(function() {
$('#navigation a').stop().animate({'marginLeft':'-118px'},1000);
$('#navigation > li').hover(
function () {
$('a',$(this)).stop().animate({'marginLeft':'0px'},400);
},
function () {
$('a',$(this)).stop().animate({'marginLeft':'-118px'},400);
}
);
});
$("#collapser").removeClass("clicked");
$("#collapser").addClass("unclicked");
$("#collapser").html('Expand All')
}
else{
$(function() {
$('#navigation a').stop().animate({'marginLeft':'0px'},1000);
$('#navigation > li').hover(
function () {
$('a',$(this)).stop().animate({'marginLeft':'0px'},400);
},
function () {
$('a',$(this)).stop().animate({'marginLeft':'0px'},400);
}
);
});
$("#collapser").removeClass("unclicked");
$("#collapser").addClass("clicked");
$("#collapser").html('Collapse All')
}
})
The code works, but only when you click the link a second time. I can't seem to figure out what I did to make it work only after clicking it once already.
Any help would be appreciated, thank you very much!!
-Quintin
EDIT:
Here is the CSS for the navigation:
ul#navigation {
position: fixed;
margin: 0px;
padding: 0px;
font-size:14px;
top: 14px;
left: 0px;
list-style: none;
z-index:9999;}
ul#navigation li {
width: 100px;
}
ul#navigation li a {
display:block;
margin-bottom:3px;
width:126px;
padding:3px;
padding-left:15px;
background-color:#ffffff;
background-repeat:no-repeat;
background-position:center center;
opacity:0.7;
filter:progid:DXImageTransform.Microsoft.Alpha(opacity=60);
-moz-box-shadow: 0px 1px 3px #000;
-webkit-box-shadow: 0px 1px 3px #000;
}
ul#navigation .checked a{
color:#ffffff;
background-color:#000000;
}
You are verifying if your collapser div has or not the class clicked or unclicked, but you not initialize the div with some class. Adding the class clicked should adjust your effect:
<li id = "collapser" class='clicked'>Collapse All</li>
You can see it with this jsfiddle

changing css background image in collapsible div using javascript/jQuery

I’m after a hand with a bit of JavaScript if possible, I’m working on a collapsible list using jQuery and want to change a background image in a css file dependent on the state of the list
This is the html for the div
<div class="collapse_div">
<div class="header_div">header text</div>
<div class="content_div">
Some text
</div>
<div class="header_div">another header</div>
<div class="content_div">
some more text
</div>
</div>
This is the .css that puts the image (expanded.gif) into the header div
.collapse_div{
margin: 0;
padding: 0;
width: 500px;
}
.header_div {
margin: 1px;
color: #000;
padding: 3px 10px;
cursor: pointer;
position: relative;
background: url(expanded.gif) no-repeat 95%;
background-color:#ccc;
}
.content_div {
padding: 5px 10px;
background-color:#fafafa;
}
And this is the javascript function that controls the expand/collapse when header_div is clicked
jQuery(document).ready(function() {
jQuery(".content_div").hide();
//toggle the componenet with class msg_body
jQuery(".header_div").click(function()
{
jQuery(this).next(".content_div").slideToggle(500);
});
});
I’ve played around with adding code to the .click(function) to try and change the background css tag in .header_div to another file (collapse.gif) but I can’t get it to work, so I thought I’d ask the experts as my javascript is really rusty
At the moment the collapse/expand of the div works fine having the background image change on click would really make it look good
You can have a class with the requried background set and apply that class conditionally. Try this
CSS
.header_div_collapsed {
background: url(collapse.gif) no-repeat 95% !important;
}
JS
jQuery(document).ready(function() {
jQuery(".content_div").hide();
//toggle the componenet with class msg_body
jQuery(".expand_div").click(function()
{
jQuery(this).next(".content_div").slideToggle(500, function(){
var $this = $(this);
if($this.is(':visible')){
$this.removeClass('header_div_collapsed');
}
else{
$this.addClass('header_div_collapsed');
}
});
});
});
Your script should be something like this,
jQuery(document).ready(function() {
jQuery(".content_div").hide();
//toggle the componenet with class msg_body
jQuery(".expand_div").click(function()
{
var elm = jQuery( this );
jQuery(this).next(".content_div").slideToggle(500, function(){
if(jQuery(this).is(":visible"))
jQuery(elm).css({"background-image" : "collapse.gif"});
else
jQuery(elm).css({"background-image" : "expand.gif"});
});
});
});
thanks to both the suggestions post below I managed to get this to work
firstly I added a whole new css function as just defining the background didn't work
.expand_div_collapsed {
margin: 1px;
color: #000;
padding: 3px 10px;
cursor: pointer;
position: relative;
background: url(collapsed.gif) no-repeat 95%;
background-color:#ccc;
}
then the JS was changed to this
jQuery(document).ready(function() {
jQuery(".content_div").hide();
//toggle the componenet with class msg_body
jQuery(".header_div").click(function()
{
var co = jQuery(this);
jQuery(this).next(".content_div").slideToggle(500, function(){
if(jQuery(this).is(':visible')){
jQuery(co).addClass('expand_div_collapsed');
}
else{
jQuery(co).removeClass('expand_div_collapsed');
}
});
});
});
the add and remove class calls had to be swapped around and I had to define the var co before the slideToggle call
but thanks to everyone who offered suggestions as I would have never got this to work otherwise

JavaScript hide and show content

I was searching for a pure CSS answer to hiding and showing content but after no luck I have been playing around with a piece of JavaScript code. My question is below the code, as it may help you to see the code first.
<script type="text/javascript">
$(document).ready(function(){
$('.text_container').addClass("visible");
$('.text_container').click(function() {
var $this = $(this);
if ($this.hasClass("visible")) {
$(this).removeClass("visible").addClass("hidden");
} else {
$(this).removeClass("hidden").addClass("visible");
}
});
});
</script>
<div id="services" class="text_container">
<h4>SERVICES</h4>
<div>
<p>Loads of text blah blah blah</p>
</div>
</div>
/* HIDE and SHOW content JavaScript function */
.hidden div {display:none;}
.visible div {display:block;}
.text_container {
background-color: #39b54a;
background-image: url("pattern2.png");
border: 1px solid #777777;
box-shadow: 0 1px 1px inset, 0 0 40px rgba(0, 0, 0, 0.5) inset, 0 16px 0 rgba(255, 255, 255, 0.4) inset, 0 4px 5px rgba(0, 0, 0, 0.6);
color: #000000;
padding: 5px;
text-align: left;
width: auto;
}
.text_container h4 {
cursor: pointer;
}
.text_container div p {
margin-bottom: 10px;
}
.visible > div {
display: block;
font-size: 17px;
height: 100%;
}
#rating > div {
clear: left;
height: 260px;
}
/* end of HIDE and SHOW content javascript function */
Currently as expected the div with class = text_container area is clickable, so if a place a form in the child DIV when you select the form the content hides. I Would like to make only the H4 element
clickable so clicking on the shown content will not hide the content.
I am useless at JavaScript and I imagine this requires rejigging the js.
You can use:
$('.text_container h4').click(function() {
if($(this).hasClass("visible")) {
$(this).removeClass("visible").addClass("hidden");
} else {
$(this).removeClass("hidden").addClass("visible");
}
});
The content in the $(' ... ') is just like a CSS selector, so if you know CSS then it won't be a problem for you.
With CSS you could style that h4 element with:
.text_container h4 { color: #000000; }
and just the same, you can create a wrapped set with jQuery that selects it with:
$('.text_container h4')
This will accomplish your goal, example:
$(document).ready(function() {
$('.text_container h4').addClass("visible");
$('.text_container h4').click(function() {
var $this = $(this).parent();
if ($this.hasClass("visible")) {
$this.removeClass("visible").addClass("hidden");
} else {
$this.removeClass("hidden").addClass("visible");
}
});
});
We are selecting the H4 and adding the click event to it, but then using .parent() to access to parent DIV.
replace $('.text_container')... with $('.text_container h4')... or, better yet, $('h4').... if it's the only H4 element on the page.
change this:
$('.text_container').click(function() {
to this:
$('.text_container h4').click(function() {
Simply replace with
$('.text_container h4').click( ...
I am not sure how someone will be able to click on an element with display: none. Also, replace this:
if ($this.hasClass("visible")) {
$(this).removeClass("visible").addClass("hidden");
} else {
$(this).removeClass("hidden").addClass("visible");
}
With this:
$(this).toggle();
Full code:
$(function() {
$('.text_container h4').click(function() {
$(this).parent().toggle(); // toggles between visible and hidden
});
});

Fading one div out and another one in, in it's place

There are 3 divs and 3 links.
Only one div should be displayed at a time. When user clicks on a link for one of the other divs, the current one should fade out and the selected one should fade in, in place of the previous div.
Here is the code at the moment:
Javascript
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
switches = $('#switches > li');
slides = $('#slides > div');
switches.each(function(idx) {
$(this).data('slide', slides.eq(idx));
}).click(
function() {
switches.removeClass('active');
slides.removeClass('active').fadeOut('slow');
$(this).addClass('active');
$(this).data('slide').addClass('active').fadeIn('slow');
});
});
</script>
CSS
<style style="text/css">
ul {
list-style: none;
}
li:hover {
text-decoration: underline;
}
#switches .active {
font-weight: bold;
}
#slides div {
display: none;
}
#slides div.active {
display: block;
}
.outer {
position: absolute;
}
.outer div {
width: 600px;
height: 300px;
}
#uno {
background-color: red;
}
#dos {
background-color: blue;
}
#tres {
background-color: green;
}
</style>
HTML
<ul id="switches">
<li class="active">First slide</li>
<li>Second slide</li>
<li>Third slide</li>
</ul>
<div class="outer" id="slides">
<div class="active" id="uno">
First div.
</div>
<div id="dos">
Second div.
</div>
<div id="tres">
Third div.
</div>
</div>
You can view the page here:
http://dl.dropbox.com/u/6920023/proofOfConcept.html
I'm attempting to use standard Jquery to do this, but clearly there is something wrong with my javascript code.
Can you spot what's wrong and how to fix it?
Your CSS defines a div that's not active as hidden. So as soon as you remove the active class, it will be hidden immediately.
So, remove this entry:
#slides div {
display: none;
}
And add something like this on page load:
$(function() {
$('#slides div:not([class="active"])').hide();
}); // will hide inactive slides initially but not always
The issue is that you use slides.removeClass('active').fadeOut('slow');. So first it will remove the active class, which means (according to your CSS) that it will be a regular div, thus with the property display: none;.
So your div is automatically hidden. It's only afterwards that you do your fadeOut('slow'), on a hidden div thus.
Better would be to do something like:
$('div.active').fadeOut(1000).delay(1000).removeClass('active');
$(this).delay(2000).fadeIn(1000).delay(1000).addClass('active');
This works, if I understand the question correctly.
The issue is that you can't fade in an element that is hot hidden or unchcanged.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
switches = $('#switches > li');
slides = $('#slides > div');
switches.each(function(idx) {
$(this).data('slide', slides.eq(idx));
}).click(
function() {
switches.removeClass('active');
slides.removeClass('active').fadeOut('slow').hide();
$(this).addClass('active');
$(this).data('slide').addClass('active').fadeIn('slow');
});
});
</script>

Categories