JQuery .mouseover and .mouseout change font color - javascript

I am newbie to JQuery and I try to make some basic tricks with it. So basicly, I have simple navigation made of unordered list, and I want to change font color on currently mouseover-ed list item with JQuery, but I have problem because my JQuery script is changing font color of all list items, and I want to change font color of ONLY currently mouseover-ed list item, not all. I tried to get currently mouseover-ed list item, but I don't know how to implement it so that my JQuery change only that list item. Here are pictures:
What I currently have: http://i.imgur.com/8vWcOci.jpg
What I want: http://i.imgur.com/4yD0bIc.jpg
Here is my JQuery code:
$(document).ready(
function(){
$('.nav1 ul li').mouseover(
function () {
var index = $( ".nav1 ul li" ).index(this);
$('.nav1 ul li a').css({"color":"white"});
}
);
$('.nav1 ul li').mouseout(
function () {
var index = $( ".nav1 ul li" ).index(this);
$('.nav1 ul li a').css({"color":"#6291d8"});
}
);
}
);
Here is my HTML:
<nav class="nav1">
<ul>
<li>HOME</li>
<li>SERVICES</li>
<li>THERAPIES</li>
<li>GALLERY</li>
<li>BOOKING</li>
<li>CONTACT</li>
<li>ABOUT ME</li>
</ul>
</nav>

Instead of:
$('.nav1 ul li a').css({"color":"white"});
and:
$('.nav1 ul li a').css({"color":"#6291d8"});
use:
$(this).css({"color":"white"});
$(this).css({"color":"#6291d8"});
if you wan to apply css on achor tag:
$(this).find("a").css({"color":"white"});
$(this).find("a").css({"color":"#6291d8"});
By using $('.nav1 ul li a') you are changing all anchor tags css but but by using $(this) will change the current clicked element css.

Why JQuery?
use a:hover in css it is pretty cleaner.
Like:
.nav1 ul li a {
color: #6291d8;
}
.nav1 ul li a:hover{
color:white;
}
For all other links you can again use a and a:hover also a:active will give you additional functionality.

this is a special word in JavaScript that refers to the element that triggers an event. In jQuery you can use $(this). So you can replaceyour code with:
$(document).ready(function () {
$('.nav1 ul li a').hover(function () {
$(this).css("color", "white");
}, function () {
$(this).css("color", "#6291d8");
});
});
jsFiddle example
Notice that I also changed the selector to '.nav1 ul li a'. The anchors have their own default styling, so to override that you should target them, and not the parent list item. I also replaced your mouseover and mouseout with the hover method as it saves a few characters. Finally, I used the more basic single property version of .css() which also saves a few characters.

There is no need for JS here. You can use the CSS :hover psuedo class:
.nav1 ul li a {
color: #6291d8;
}
.nav1 ul li a:hover {
color: #FFF;
}
Example fiddle

Related

jQuery on click, add class but also remove if the class is already present

I have a nav menu that needs to trigger with clicks rather than hovers. When the links are clicked, an .open class would be added to the parent li. If that parent already has the .open class, then it would get removed. It would also be removed if another link is clicked on. So far I can get the class added when clicked and removed when a sibling is clicked, but not removed when it's already .open.
I tried adding a hasClass conditional, but that didn't work either. Seemed like it reruns the function every time it's clicked and therefore ignores the hasClass conditional.
Can anyone provide help? I tried toggleClass, but that didn't work.
$('li a').on('click', function() {
$('li a').parent().removeClass('open');
$(this).parent().addClass('open');
});
ul {
list-style: none;
}
li {
display: inline-block;
padding: 10px;
}
.open {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>
Item 1
</li>
<li>
Item 1
</li>
</ul>
</nav>
To do what you require you can use toggleClass() on the parent li when the element is clicked. To remove the class from all other li elements you can use removeClass() along with not() to exclude the current li. Try this:
$('li a').on('click', function() {
let $li = $(this).parent().toggleClass('open');
$('li').not($li).removeClass('open');
});
ul {
list-style: none;
}
li {
display: inline-block;
padding: 10px;
}
.open {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>
Item 1
</li>
<li>
Item 1
</li>
</ul>
</nav>
You can use
jquery toggleClass() to toggle yellow highlight (.open css class) on click/unclicking the same link.
jquery siblings() to remove .open class on all the other li items.
Below is the link for the demo
https://jsfiddle.net/so1u8hq6/
$('li a').on('click', function() {
$(this).parent().siblings().removeClass('open');
$(this).parent().toggleClass('open');
});
ul {
list-style: none;
}
li {
display: inline-block;
padding: 10px;
}
.open {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>
Item 1
</li>
<li>
Item 2
</li>
<li>
Item 3
</li>
</ul>
</nav>
Late to the party, but, after seeing the provided answers and some of the CSS you use I had to urge with my suggestions:
UX. Avoid styling LI tags in general, or at least set the desired display and move on. Style directly the a tag (with the necessary paddings etc.). You'll not only get less CSS to take care of, but also a larger touch interaction area. Makes no sense to style something yellow if it's not a UI part of something interactable. Also in JS, you don't need to take care about the LI wrappers any more - but only about the actual A Elements.
Don't use common selectors like $('li a') - those might target any LI→A elements in your app. Instead be more specific and use a Class like i.e: .tabs for the parent UL. Both in CSS and JS.
Try to use Event Delegation (in jQuey using the .on() method). Not only it will help you to catch the Event.delegateTarget parent UL where needed, but also the this (the clicked element), but mainly reference all the "group" of a elements enclosed in the common parent. That way you can have as many .tabs in a single page as you like. And yes, thanks to Event delegation you can even add dynamically LI Elements - and your JS will still work as expected.
Since you're using <a href="#"> Anchor elements, instead of (more properly) <button type="button>" Elements, you need to also use Event.preventDefault() in order to prevent the browser its default behavior and that's to follow anchors (scroll the page, navigate, etc...)
Use the selector "a.open" when you want to target and remove the "open" class. By just using "a" (or in other answers on this page - "li") you're uselessly touching elements trying to remove a class that's not there in the first place.
Finally, here's the CSS retouch and the proper jQuery needed for your task:
$(".tabs").on("click", "a", function(ev) {
ev.preventDefault();
$("a.open", ev.delegateTarget).not(this).removeClass("open");
$(this).toggleClass("open");
});
.tabs {
display: flex;
list-style: none;
padding: 0;
}
/* Style your Anchors, not the dummy LI wrappers */
.tabs a { padding: 10px; }
.tabs a.open { background-color: yellow; }
<ul class="tabs">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
To explain the only complicated line:
$(
"a.open", // Target just the ones (if any) of class "open"
ev.delegateTarget // inside the common ".tabs" ancestor
)
.not(this) // ... not the clicked element (since later we'll use .toggleClass on it)
.removeClass("open"); // ... remove that class "open"
the rest is pretty self explanatory.
Further read:
jQuery Event Delegation
jQuery event.delegateTarget
Event.preventDefault
So you only want the yellow background to appear as a signifier of user interaction rather than for the background color to be displayed? Have you tried using the mousedown/mouseup functions instead of .on('click', function(){...}?
I was able to simulate the click event where the color showcases via this method:
$('li a').mousedown(function() {
$('li a').parent().removeClass('open');
$(this).parent().addClass('open');
});
$('li a').mouseup(function() {
$('li a').parent().removeClass('open');
});
ul {
list-style: none;
}
li {
display: inline-block;
padding: 10px;
}
.open {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>
Item 1
</li>
<li>
Item 1
</li>
</ul>
</nav>

HTML Node tree with add buttons and hierarchical numbering

How to create a JavaScript based tree where you have add buttons, to add extra child elements.
For example, it has to look like this:
I need do be able to add child elements, and I need to make number counting work like that also.
I tried jQuery click() and then added append(), but it didn't come out as I expected. It started randomly adding rows.
Is there a simple way to do this or am I just overthinking this too much? I'm new in coding and any help would be appreciated.
I started like below, but obviously it's not working like that:
$('document').ready(function() {
$('#parent').on('click', function() {
$('#tree').append('<li><input type="text"></li>')
$('#tree li:last').append('<button type="button" id="child">ADD</button>')
$('#tree li:last').append('<ul></ul>')
$('#child').on('click', function() {
$('#tree li ul').append('<li><input type="text"></li>')
$('#tree li ul li:last ').append('<button id="child2" type="button">ADD</button>')
$('#tree li ul li:last').append('<ul></ul>')
$('#child2').on('click', function() {
$('#tree li ul li ul').append('<li><input type="text"></li>')
$('#tree li ul li ul li:last').append('<button id="child3" type="button">ADD</button>')
$('#tree li ul li ul li:last').append('<ul></ul>')
$('#child3').on('click', function() {
$('#tree li ul li ul li ul').append('<li><input type="text"></li>')
});
});
});
});
});
ul {
list-style-type: decimal;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<ul id="tree"><button type="button" id="parent">ADD</button></ul>
</div>
The code repetition that you have is indeed a problem. You cannot do this indefinitely.
The solution is to create a generic click handler which will capture a click on any button that exists now or in some future.
For the nested numbering, you can use the counters() CSS-function.
As you are using jQuery, I would also suggest to rely more on the methods it provides:
$('document').ready(function(){
$('#tree').on('click', 'button', function() {
$(this).before(
$("<li>").append(
$("<ul>").append(
$("<button>").text("Add")
)
)
);
});
});
ul { counter-reset: item }
li { display: block }
li:before {
content: "node " counters(item, ".") " ";
counter-increment: item
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div><ul id="tree"><button id="parent">Add</button></ul></div>
This shows more "Add" buttons than in your image, as there are more places where content can be inserted. Every click on such a button will result in one more button.

text on anchor changes when hover

Is it possible to change the content of an anchor when hovered? i have this sample fiddle
i want to change the about anchor to some like My bio when hovered. and something else also for the home. the content attribute doesn't seem to work well with this.
HTML:
<ul>
<li>About</li>
<li>Home</li>
</ul>
CSS:
ul { list-style: none; }
ul li a:hover { color: red; content: 'Content'; }
"content property is used with the :before and :after pseudo-elements, to insert generated content." not with normal elements.
Reference: http://www.w3schools.com/cssref/pr_gen_content.asp
You can change it using jQuery:
$('li a').mouseenter(function(){
$(this).data('text', $(this).text());
$(this).text('Content');
}).mouseleave(function(){
$(this).text($(this).data('text'));
});
http://jsfiddle.net/TrueBlueAussie/s6ao29eg/2/
This version simply saves the text to data on the element on mouseenter, and restores it on mouseleave. You can also use hover passing the same two functions.
e.g.
$('li a').hover(function(){
$(this).data('text', $(this).text()).text('Content');
}, function(){
$(this).text($(this).data('text'));
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/s6ao29eg/5/
I notice several other clever CSS-only solutions have been provided, so the choice depends on how much you can change your content, vs adding code.
If you want different text, use a data attribute:
<li>About</li>
e.g.
$('li a').hover(function(){
$(this).data('text', $(this).text()).text($(this).data('content'));
}, function(){
$(this).text($(this).data('text'));
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/s6ao29eg/8/
Update to use a transition (fade) as requested:
$('li a').hover(function(){
$(this).stop(true,true).fadeOut(function(){
$(this).data('text', $(this).text()).text($(this).data('content')).fadeIn();
});
}, function(){
$(this).stop(true,true).fadeOut(function(){
$(this).text($(this).data('text')).fadeIn();
});
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/s6ao29eg/10/
Further update now the rules have changed :)
As the HTML content apparently cannot be modified, use the index position of the LI combined with an array of text items:
var content = ["About me!", "My home!"];
$('li').hover(function(){
var $a = $('a', this);
$a.stop(true,true).fadeOut(function(){
$a.data('text', $a.text()).text(content[$(this).index()]).fadeIn();
});
}, function(){
var $a = $('a', this);
$a.stop(true,true).fadeOut(function(){
$a.text($a.data('text')).fadeIn();
});
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/s6ao29eg/11/
Credit to #MariaMadalina who used an array before even knowing the HTML could not be modified :)
Really sounds like a job for JS. CSS only solution via pseudo elements:
http://jsfiddle.net/qpdoby91/
.about:before { content: 'About'; }
.home:before { content: 'Home'; }
ul li a:hover:before { content: 'Content'; }
JavaScript Solution: http://jsfiddle.net/bctaxauo/1/
$('ul li a').hover(function() {
$(this).data('prevText', $(this).text()).text('New Content!');
}, function() {
$(this).text($(this).data('prevText');
});
Just hide "hover text" when in normal state and switch display when on hover:
.menu li:hover .unhover {
display: none;
}
.menu li:hover .hover {
display: inline;
}
.menu li .unhover {
display: inline;
}
.menu li .hover {
display: none;
}
<ul class="menu">
<li>
<a href="#">
<span class="unhover">Home</span>
<span class="hover">Visit home</span>
</a>
</li>
</ul>
Made a jquery snippet
$('li#about').hover(function() {
$("a", this ).text( "something" );
}, function() {
$("a", this ).text( "About" );
});
Take a look here http://jsfiddle.net/s6ao29eg/3/
EDIT:
I made some modifications towards a more scalable solution.
var replacementText=["Something 1","Something 2"];
$('li').hover(function() {
var myindex = $(this).index();
var myText=replacementText[myindex];
$("a", this).data('original', $("a",this).text()).text(myText);
}, function() {
var myindex = $(this).index();
$("a",this).text($("a",this).data('original'));
});
http://jsfiddle.net/s6ao29eg/9/
You can, but you have to use the :before and :after pseudo-elements, and a little color trick to hide the original text.
ul li a:hover {
color: transparent;
}
ul li a:hover:before {
content: "Content";
position: absolute;
color: red;
}
Just by the way, why would you want to use a <ul> to nest your <a> elements? You are removing all styles from the list anyway. Most of the time, what you need is just well-styled <a> tags; only nest them in a list if you're structuring the data as a list, which means you likely want to have something like bullet points preceding each li.
Simple Css only solution
HTML
<ul>
<li> <span class="visible">About</span> <span class="hover"> My Bio</span> </li>
</ul>
Css
ul { list-style: none; }
ul li a span.hover{
display:none;}
ul li a:hover span.hover{
display:block;
}
ul li a:hover span.visible{
display:none;
}
You can also do it using jQuery.
Add an id to your li as:
<li>About
and add this jQuery code
$(document).ready(function(){
$('#about').hover(function(){
$(this).text('');
$(this).text('My Bio');
});
$('#about').mouseout(function(){
$(this).text('');
$(this).text('about');
});
});
Fiddle link is:http://jsfiddle.net/sonam185/w5fh140q/
or also do like this if you have multiple li's
http://jsfiddle.net/sonam185/gayph16x/

Override :hover on elements under pseudo element

In our menu, I have a parent menu item and its children turn orange on :hover. I am also using JS to add a toggle to a collapse/expand menu, but since the span element is positioned on top of the parent list item, hovering on the toggle triggers the color change. I am trying to figure out a way (either with Compass or jQuery) to override the hover style on the list if the toggle is hovered on.
We're using Drupal, so the HTML is quite convoluted, but here's a pared down version:
<li class="menu__item is-expanded last-expanded">
<span class="menu__link nolink">About</span>
<span class="menu__link nolink expand"> </span> <!--put here by jQuery for the collapse and expand icon -->
<ul class="menu">
<li>Mission</li>
<li>Team</li>
</ul>
</li>
Here's the jQuery:
jQuery(document).ready(function(){
$(".not-front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand'> </span>");
$(".front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand collapse'> </span>");
$("#block-menu-block-1 ul li li").css({ display: "block" });
$(".not-front #block-menu-block-1 ul li li").css({ display: "none" });
$('#block-menu-block-1 .menu__link.nolink').click(function(){
$('#block-menu-block-1 ul li li').toggle('fast');
$( ".menu__item.is-expanded.last.expanded span.menu__link.nolink.expand" ).toggleClass( "collapse" );
});
});
And here's the Sass:
.menu__item:hover a,
.menu__item:hover span {
color: $orange;
}
Edit: Sorry! I wanted to post a Sassmeister earlier, but their site was down. Had a link to the dev site, but removed once answered.
Edit: I thought something like this would work, but it's not:
jQuery(".menu__item span.expand").mouseover(function(e) {
jQuery("menu__item:hover a, .menu__item:hover span").toggleClass( "stay-gray" );
});
along with this is the sass:
.menu__item:hover a,
.menu__item:hover span {
color: $orange;
border-color: $orange;
&.stay-gray {
color: $darkGray;
border-color: $darkGray;
}
}
Maybe you could try stop propagating the event on the span.expand elements:
$("span.expand").mouseover(function(e) {
e.stopPropagation();
});
EDIT: stopPropagating didn't work. So, retaking the idea proposed by the OP, we figured out this solution:
Add two new CSS rules:
.stay-gray a.menu__link {
border-bottom-color: #474E51 !important;
}
.stay-gray, .stay-gray a.menu__link {
color: #474E51 !important;
}
And then add this lines at the end of the jQuery(document).ready(function(){ ...:
toggleStayGray=function(e){ jQuery(e.target).siblings().toggleClass('stay-gray') };
jQuery('.menu span.expand').mouseover(toggleStayGray).mouseout(toggleStayGray);
This way:
jQuery(document).ready(function(){
jQuery(".not-front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand'> </span>");
jQuery(".front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand collapse'> </span>");
jQuery("#block-menu-block-1 ul li li").css({ display: "block" });
jQuery(".not-front #block-menu-block-1 ul li li").css({ display: "none" });
jQuery('#block-menu-block-1 .menu__item.is-expanded').click(function(){
jQuery('#block-menu-block-1 ul li li').toggle('fast');
jQuery( ".menu__item.is-expanded.last.expanded span.menu__link.nolink.expand" ).toggleClass( "collapse" );
});
toggleStayGray=function(e){ jQuery(e.target).siblings().toggleClass('stay-gray') };
jQuery('.menu span.expand').mouseover(toggleStayGray).mouseout(toggleStayGray);
});
This way, when you hover over the span.expand element, the stay-gray class is toggled on at its siblings, and the new styles are applied on them and its a.menu__link descendants. When the mouse is out, the stay-gray class is toggled off.

Remember menu state on reload

I want to create a navigation menu with the exact same functionality as the one on this site: http://www.rex-ny.com/
I would prefer to do it only using HTML and CSS, but I tried all day and couldn't find a solution.
When I select a menu item, I want that menu to stay open after the page loads. Is this possible?
I want to also make the Main menu items clickable, so that they load a new page AND when that page loads that menu is open.
Here is what I have so far:
http://jsfiddle.net/MEL9d/
Here is the jquery:
$(document).ready(function () {
$('#menu > li > a').click(function(){
if ($(this).attr('class') != 'active'){
$('#menu li ul').hide();
$(this).next().toggle();
$('#menu li a').removeClass('active');
$(this).addClass('active');
}
});
});
And CSS:
#menu {
float: left;
}
#menu li a {
display: block;
}
#menu li ul {
display: none;
}
You can do this is plain HTML and CSS. Assuming you have a structure like this:
- site
+ css
+ js
index.html
about.html
You can add a class to the body of each page, so index for index.php and about for about.php:
<body class="about">
Then in your menu, add an id (or a class if you plan on having the menu in many places) to each item that corresponds to the page:
<ul id="menu">
<li id="index" class="active"><a href="index.html"></li>
<li id="about"><a href="about.html"></li>
</ul>
Finally, using CSS you can style the menu items for each page specifically:
.index #index,
.about #about,
#menu .active {
// styles for active item
}

Categories

Resources