I have a set of buttons on my page, each of which calls a javascript function when clicked; when clicked, the active link color is lit, but when I click elsewhere on the page the active link color is cleared. I want it to stay lit unless I click on another button link.
Here is an example of how a link is constructed (there are 10 links):
<div class="C1"><br><button class="button_01" onclick="HideDropdown(); ShowPage(7);">FAQs</button></div>
Here's the css for the button and C1 classes:
.button_01 {
background-color: rgb(0,2,3);
border: none;
color: rgb(100,100,100);
font-family: camphorW01-Thin,calibri,arial;
text-align: left;
text-decoration: none;
font-size: 13pt;
cursor: pointer;
transition: all 150ms ease-in;
}
.button_01:hover { color: rgb(175,222,162); }
.button_01:active { color: rgb(175,222,162); }
.button_01:focus { color: rgb(175,222,162); }
.button_01:visited { color: rgb(175,222,162); }
.C1{
color:#DBDBDB;
font-family: sans-serif;
font-size: 14pt;
text-indent: 0px;
width: auto;
margin: auto;
}
I know the default behavior is for the active link color to clear when clicking elsewhere, but I should be able to use javascript or jquery to get the value of the active link and keep it the same color (unless I click on another link); I've found only two posts that come close but one is specific to list items (li), not a button class with an onclick handler (not an anchor tag) at How to get the ID of an active link. Another post at how to Keep the color of active link constant, until i press other link showed a jquery function specific to anchor tags; I modified it like this:
<script>
var items = $("button_01");
items.removeClass("active");
$(this).toggleClass("active");
});
<script>
That doesn't work and with that script in place the links do not work.
So my question is: how do I keep the active link color lit on a button that has an onclick handler to call javascript (versus a list item or an anchor tag)?
Thanks very much for any help on this.
EDIT: I solved this problem and posted the answer below.
assuming all you buttons have class="button_01"
$('.button_01').on('click', function(){
$('.button_01').removeClass('active');
$(this).addClass('active');
});
.active {
background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="button_01">Button 1</button>
<button class="button_01">Button 2</button>
<button class="button_01">Button 3</button>
you could use the .css() property within jquery if the active attribute is still clicking out on your site.
$('.button_class').on('click', function() {
$('.button_class').removeAttr('style');
$(this).css('backgroundColor', 'red');
});
I just made a quick fiddle with what I think is a possible solution to your problem. I've done in pureJs.
function ShowPage(e,page){
// do a function to reset colors to default
resetColors();
// call hide here, since you do it everytime you show a page
HideDropdown();
e.classList.add("active");
//do stuff here
}
function HideDropdown(){
// do stuff here
}
function resetColors(){
// do stuff here
}
.active{
color: red !important;
}
<div class="C1">
<button class="wathever" onclick="ShowPage(this,7);">A</button>
<button class="wathever" onclick="ShowPage(this,7);">B</button>
<button class="wathever" onclick="ShowPage(this,7);">C</button>
<button class="wathever" onclick="ShowPage(this,7);">D</button>
</div>
After much research and work, here's how I solved this problem.
Remember that I have 10 links, each with a unique ID number, so I loop through them 1-10 and create the ID name (e.g., btn04). In order to keep the current active link lit, I have to change the link color to the active link color when I click anywhere on the page except for another link of the same type (button_01 class). For that, I need to store the active element in a global var on each button click, so that on any subsequent click we know what the last active element was BUT the subsequent click will change the active element to the currently-clicked element. What to do? I set up another global var, LastActiveElement, which captures the most recently set active element. Now I know where the last click was -- if it was a hyperlink and the current click is not a hyperlink, I change the last clicked hyperlink color back to its active color, which has the effect of keeping it on the same color.
Add this to the body tag:
<body onload="ShowABC(1);" onclick="changeColor(event); getLastGAE(event); getFocusElement(event);">
<script>
function changeColor(event) {
for (i = 1; i < 11; i++) {
ID_Name = "btn0" + i.toString();
if (i >= 10){ID_Name = "btn" + i.toString();}
var elem = document.getElementById(ID_Name);
TargetClass = event.target.getAttribute('class');
TargetID = event.target.getAttribute('id');
var active = document.activeElement;
var equal = (LastActiveElement == ID_Name);
tfh = TargetID == "hamburger_container";
if ((equal == "true") && (TargetClass != "button_01") && (tfh == "false")){
var newColor = "rgb(175,222,162)";
elem.style.color = newColor; }
if (TargetClass == "button_01"){ elem.style.color = "rgb(100,100,100)"; }
if (TargetID == ID_Name){ elem.style.color = "rgb(175,222,162)"; }
}
}
</script>
<script>
var LastActiveElement;
function getLastGAE(event) {
LastActiveElement = GlobalActiveElement;
}
</script>
<script>
var GlobalActiveElement;
function getFocusElement(event) {
var active = document.activeElement;
TargetID = event.target.getAttribute('id');
GlobalActiveElement = TargetID;
}
</script>
With that, if I click anywhere on the page except another hyperlink of the same class, the active link color does not change.
Now I know some advise against global vars, but this is only two data elements added to the DOM so it takes up negligible space.
Of course, there may be other solutions but this is what I came up with.
Thanks to everyone who replied to this question.
Related
Salutations,
I am learning to code through some online resources and my brother who works in the field in an effort to get into a development career. Right now I am working on a silly web app where you are matching photos. Below each photo is a button with a unique ID. Currently, when you select a button, it will turn blue.
I am trying to create a function that will look for 2 specific buttons being clicked.
If I were to speak what I want it to do in a conversation with you, I would say "if button1 is select when button4 is selected, do this thing"
What function am I looking for?
Can anyone help this n00b out?
Below I have the function as is for when a button is clicked. The class changes in order to adjust the color.
I can post whatever code is necessary, otherwise this is all I could think to post. {BC1b is a button that should be paired with F1b}
function sbtnb1() {
document.getElementById("BC1b").className = "selected";
}
Here is an example.
https://jsfiddle.net/273rhzyw/
With Jquery
https://jsfiddle.net/agoLcuv8/8/
// All buttons with class of button
const buttons = document.querySelectorAll(".button");
// declare array to keep the match checks
let matchCheckerArray = [];
// Loop through each button and attach an onClick
buttons.forEach(function(button) {
button.onclick = function() {
clickHandler(button);
}
});
const clickHandler = function(button) {
matchCheckerArray.push(button.dataset.matchId)
console.log(matchCheckerArray);
if (matchCheckerArray.length == 2) {
if (isMatch()) {
alert('Match');
}
matchCheckerArray = [];
return;
}
}
const isMatch = function() {
if (matchCheckerArray[0] === matchCheckerArray[1]) {
return true;
}
return false;
}
I would keep two global variables (or an array/set of variables) that store what's been clicked. You can manipulate these however you'd like (e.g. clear out the selection if the user selected two photos that aren't a match; don't let the user select a second card if it doesn't match; etc...).
This can work in conjunction with what you already have. The class name will allow you to add specific selected styling, while the global variables allow you to keep track of what has been selected. The global variables will also allow you to check for match or no match.
There are many ways to do this but this is how I would go about it.
$(".checkButton").on("click", function(){
// toggle button state
if($(this).attr("data-state") == "on") {
$(this).attr("data-state", "off"); // toggle button off
$(this).removeClass("highlight"); // remove highlight
$(".myImage").removeClass("highlight"); // remove highlight
} else {
$(this).attr("data-state", "on"); // make button active
$(this).addClass("highlight"); // add highlight
}
//----------------------------------------------------------
// Here you would have to build your checks and how you want
// the comparison of buttons and images to be linked.
//----------------------------------------------------------
// For example:
// check if more than 2 buttons are active and if buttons match the if statement.
var buttonCount = 0;
$("#buttonContainer button").each(function(){
if($(this).attr("data-state") == "on"){
buttonCount += 1;
}
});
// if 2 buttons are clicked then check then allow to do something
if(buttonCount == 2){
// highlight image 1 if buttons 1 and 2 are on.
if($(".checkButton[data-id=b1]").attr("data-state") == "on" &&
$(".checkButton[data-id=b2]").attr("data-state") == "on"){
$("#image1").addClass("highlight");
}
// highlight image 2 if buttons 3 and 4 are on.
if($(".checkButton[data-id=b3]").attr("data-state") == "on" &&
$(".checkButton[data-id=b4]").attr("data-state") == "on"){
$("#image2").addClass("highlight");
}
}
//----------------------------------------------------------
});
.myImage {
width: 100px;
height: 100px;
margin: 5px;
background: black;
float: left;
}
.highlight {
outline: 2px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="width: 100%; height: 110px;">
<div class="myImage" id="image1"></div>
<div class="myImage" id="image2"></div>
</div>
<div id="buttonContainer" style="width: 100%;">
<button class='checkButton' data-id="b1" data-state='off'>button 1</button>
<button class='checkButton' data-id="b2" data-state='off'>button 2</button>
<button class='checkButton' data-id="b3" data-state='off'>button 3</button>
<button class='checkButton' data-id="b4" data-state='off'>button 4</button>
</div>
There are a bunch of div elements on the page.
I have a nested div inside of them.
I want to be able to add a class to the clicked element, and .show() the child div.
$('.container').on('click', function(){
$(this).toggleClass('red').children('.insideItem').slideToggle();
});
I can click on it, it drops down.
Click again, it goes away.
So, now I need some method to removeClass() and slideUp() all of the other ones in the event of a click anywhere except the open div. Naturally, I tried something like this:
$('html').on('click', function(){
$('.container').removeClass('red').children('div').slideUp();
});
Well, that just stops the effect from staying in the first place. I've read around on event.Propagation() but I've read that should be avoided if possible.
I'm trying to avoid using any more prebuilt plugins like accordion, as this should be a pretty straightforward thing to accomplish and I'd like to know a simple way to make it work.
Would anyone be able to show a quick example on this fiddle how to resolve this?
Show only one active div, and collapse all others if clicked off
https://jsfiddle.net/4x1Lsryp/
One way to go about it is to update your code with the following:
1) prevent the click on a square from bubbling up to the parent elements
2) make sure to reset the status of all the squares when a new click is made anywhere.
$('.container').on('click', function(){
$this = $(this);
$('.container').not($this).removeClass('red').children('div').slideUp();
$this.toggleClass('red').children('div').slideToggle();
return false;
});
See the updated JSfiddle here: https://jsfiddle.net/pdL0y0xz/
You need to combine your two approaches:
for (var i = 0; i < 10; i++) {
$('#wrap').append("<div class='container'>" + i + "<div class='insideDiv'>Inside Stuff</div></div>");
}
$('.container').on('click', function() {
var hadClassRed = $(this).hasClass('red');
$('.container').removeClass('red').children('div').slideUp();
if (!hadClassRed) {
$(this).toggleClass('red').children('div').slideToggle();
}
});
.container {
width: 200px;
height: 200px;
float: left;
background: gray;
margin: 1em;
}
.insideDiv {
display: none;
}
.red {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrap"></div>
I am trying to make webpage where there is a div in the center which is being changed, instead of going to different pages.
Ultimately, I would like to have the new div, when clicking on an arrow, to flow from right or left in to the center. But first I would like to make the divs appear and disappear when clicking on the arrows but unfortunately this doesn't work.
This is my javascript:
<script>
function changeToHome() {
document.getElementById("mainmain").style.display="block";
document.getElementById("mainmain2").style.display="none";
document.getElementById("mainmain3").style.display="none";
document.getElementById("mainmain4").style.display="none";
}
function changeToStudy() {
document.getElementById("mainmain").style.display="none";
document.getElementById("mainmain2").style.display="block";
document.getElementById("mainmain3").style.display="none";
document.getElementById("mainmain4").style.display="none";
}
function changeToJob() {
document.getElementById("mainmain").style.display="none";
document.getElementById("mainmain2").style.display="none";
document.getElementById("mainmain3").style.display="block";
document.getElementById("mainmain4").style.display="none";
}
function changeToContact() {
document.getElementById("mainmain").style.display="none";
document.getElementById("mainmain2").style.display="none";
document.getElementById("mainmain3").style.display="none";
document.getElementById("mainmain4").style.display="block";
}
function changePageRight() {
var displayValue5 = document.getElementById('mainmain').style.display;
var displayValue5 = document.getElementById('mainmain2').style.display;
var displayValue6 = document.getElementById('mainmain3').style.display;
var displayValue7 = document.getElementById('mainmain4').style.display;
if (document.getElementById('mainmain').style.display == "block") {
document.getElementById("mainmain").style.display="none";
document.getElementById("mainmain2").style.display="block";
}
else if (document.getElementById('mainmain2').style.display == "block") {
document.getElementById("mainmain2").style.display="none";
document.getElementById("mainmain3").style.display="block";
}
else if (document.getElementById('mainmain3').style.display == "block") {
document.getElementById("mainmain3").style.display="none";
document.getElementById("mainmain4").style.display="block";
}
else if (displayValue8 == block) {}
}
function changePageLeft() {
var displayValue = document.getElementById('mainmain').style.display;
var displayValue2 = document.getElementById('mainmain2').style.display;
var displayValue3 = document.getElementById('mainmain3').style.display;
var displayValue4 = document.getElementById('mainmain4').style.display;
if (displayValue == "block") { }
else if (displayValue2 == "block") {
document.getElementById("mainmain").style.display="block";
document.getElementById("mainmain2").style.display="none";
}
else if (displayValue3 == "block") {
document.getElementById("mainmain2").style.display="block";
document.getElementById("mainmain3").style.display="none";
}
else if (displayValue4 === "block") {
document.getElementById("mainmain3").style.display="block";
document.getElementById("mainmain4").style.display="none";
}
}
</script>
Now I have a few divs that look like this:
<div id="mainmain4">
<img style="width:400px;height:327px;margin-left:auto;margin-right:auto;display:block;" src="Untitled-22.png" />
<h2> My name </h2>
<p>Hi,</p>
<p>Some text</p>
</div>
With these css atributes:
#mainmain {
float: left;
width: 575px;
display: block;
position: relative;
}
And all other divs with display: none; so I can change this to block and the one that was block to none.
For some reason, after when I click on one button of the menu, which activates a changeToX() function, the arrows work great. But before that, when you first go to the website, it doesn't.
Can someone explain me what I do wrong?
You don't tell the browser which divs shall be displayed on load. You can use theonloadevent for this:
<body onload="changeToHome()">
One additional hint: you maybe don't want to use inline JavaScript and CSS.
jQuery is as this simple:
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
toggle!
<div id="mainmain">test text</div>
<script>
// you need this, only apply javascript when all html (dom) is loaded:
$(document).ready(function() {
$('.toggle-container').on('click', function(e) {
e.preventDefault(); // this prevents the real href to '#'
// .toggle() is like "on / off" switch for hiding and showing a container
$($(this).data('container')).toggle();
});
});
</script>
This function can be reused, because it is based on classes instead of id's.
Check this JSFiddle: http://jsfiddle.net/r8L6xg15/
Maybe this is of some use. I've tried to make a page control-like behaviour. You can select any container div and put elements in there that have the class 'page'. The JavaScript code will let you navigate those with buttons.
You can make it more fancy by adding the buttons through JavaScript. What you then have is basically a list of pages which are normally displayed as regular divs, but when the script kicks in, it changes them to a page control.
You can call this for any parent element, and in that sense it behaves a bit like a jQuery plugin. It is all native JavaScript, though. And not too much code, I hope. Like you said, I think it's good to learn JavaScript at first. It is very powerful by itself, and it's becoming increasingly powerful. jQuery adds a lot of convenience functions and provides fallbacks in case browser don't support certain features, or when implementations differ. But for many tasks, bare JavaScript will do just fine, and it certainly can't hurt to know your way around it.
Press the 'Run this snippet' button at the bottom to see it in action.
function Pages(element)
{
// Some initialization
var activePage;
// Find all pages within this element.
var pages = document.querySelectorAll('.page');
var maxPage = pages.length - 1;
// Function to toggle the active page.
var setPage = function(index)
{
activePage = index;
for (p = 0; p <= maxPage; p++)
{
if (p == activePage)
pages[p].className = 'page active';
else
pages[p].className = 'page inactive';
}
}
// Select the first page by default.
setPage(0);
// Handler for 'previous'
element.querySelector('.prev').onclick = function()
{
if (activePage == 0)
return;
setPage(activePage - 1);
}
// Handler for 'next'
element.querySelector('.next').onclick = function()
{
if (activePage == maxPage)
return;
setPage(activePage + 1);
}
// Add a class to the element itself. This way, you can already change CSS styling
// depending on whether this code is loaded or not. So in case of an error, the
// divs are just all show underneath each other, and the nav buttons are hidden.
element.className = element.className + ' js';
}
Pages(document.querySelector('.pages'));
.pages .page {
display: block;
padding: 40px;
border: 1px solid blue;
}
.pages .page.inactive {
display: none;
}
.pages .nav {
display: none;
}
.pages.js .nav {
display: inline-block;
}
<div class="pages">
<button class="nav prev">Last</button>
<button class="nav next">Next</button>
<div class="page">Page 1 - Introduction and other blah</div>
<div class="page">Page 2 - Who am I? Who are you? Who is Dr Who?</div>
<div class="page">Page 3 - Overview of our products
<ul><li>Foo</li><li>Bar</li><li>Bar Pro</li></ul>
</div>
<div class="page">Page 4 - FAQ</div>
<div class="page">Page 5 - Contact information</div>
</div>
To dos to make this a little more professional:
Add the navigation through JavaScript
Disable the buttons when first/last page has been reached
Support navigation by keys too (or even swipe!)
Some CSS transform (fade or moving) when toggling between pages
Smarter adding and removing of classes. Now I just set className, which sucks if someone would like to add classes themselves. jQuery has addClass and removeClass for this, which is helpful. there are also stand-alone libraries that help you with this.
Visible indication of pages, maybe with tabs at the top?
I was hoping to get some help. I set up a JSfiddle below:
http://jsfiddle.net/y7mEY/102/
I was looking to have the grey div box that appears when the input box is clicked (that will have the search options in it) to close when I click anywhere outside it.
I would like to not load jquery and therefore keep everything in javascript.
Any help?
code below:
HTML
<div id = "searchHousing">
<input type="text" name="value" id="fillIn">
</div>
CSS
.searchBox {
position: absolute;
font-family:Arial;
font-size: 10pt;
color:black;
height: 200px;
width: 200px;
padding-left: 3px;
padding-top: 1px;
border: 1px solid white;
background-color: grey;
}
#fillIn {
width: 200px;
height: 28px;
border-radius: 4px;
font-size: 16px;
margin-bottom: 2px;
#searchHousing {
float: left;
}
Javascript:
var inputSearch = document.getElementById('fillIn');
inputSearch.onclick = function() {
var searchBox = document.createElement("div");
searchBox.className = "searchBox";
document.getElementById('searchHousing').appendChild(searchBox);
};
Thanks,
Ewan
I would suggest to not create new 'div' on click event. This will result in multiple "searchBox" divs when the input box is clicked multiple times. Needless to say, it will require cleanup effort to remove duplicated divs.
Rather, create the searchBox div in HTML and toggle it's visibility on javascript events.
Updated JSFiddle: http://jsfiddle.net/y7mEY/109/
[
var inputSearch = document.getElementById('fillIn');
inputSearch.onclick = function() {
document.getElementById('searchBox').style.display = 'block';
};
inputSearch.onblur = function() {
document.getElementById('searchBox').style.display = 'none';
};
]
If you want to use your current approach, simply use the "onblur" event to remove the element when the element loses focus.
inputSearch.onblur = function() {
document.getElementById('searchHousing').removeChild(document.getElementsByClassName("searchBox")[0]);
}
But as CVG mentions, creating/deleting elements live is a fairly bad idea.
The problem with onBlur as the other answers suggest is that you will then hide the search options div every time you click anything in it (since the input field will lose focus). This is probably not what you're looking for. Instead, you can add a click handler for the document to hide the search options, and then add a click handler for the search housing to prevent event propagation (which keeps the document click handler from hiding the options).
If you click the input box, the handler shows the options
If you click the input box or the options, the event propagation stops
If you click anywhere in the document besides the input box or options, the options are hidden
Updated JSFiddle
var inputSearch = document.getElementById('fillIn');
var searchHousing = document.getElementById('searchHousing')
inputSearch.onclick = function(event) {
document.getElementById('searchBox').style.display = 'block';
};
searchHousing.onclick = function(event) {
event.stopPropagation(); // won't be passed to document.onclick
};
document.onclick = function() {
document.getElementById('searchBox').style.display = 'none';
};
You'll be creating div elements all the time, which isn't any good. You could something along the lines of toggling the display attribute.
Just to make sure, if you want the searchBox to stay open and only close if you're clicking outside the searchBox and fillin elements, then you can just follow the click events and only toggle the display if you're clicking outside both. The other methods will just close it out as long as you're not typing in the input, and if you want to place tools or something within the div, then that would be useless.
document.addEventListener('click', function(e) {
if(e.target.id != "searchBox" && e.target.id != "fillIn")
document.getElementById("searchBox").style.display="none";
});
Full demonstration: JSFiddle
here is my jsfiddle: http://jsfiddle.net/HhBEJ/3/
Despite some of the code not looking good in jsfiddle because i have background images and such - I am having a problem with my nav menu.
What I want it to do is:
When I load the page(index.htm) I want it to have a page marker ( which i have named current) to mark that I'm currently on the home page. When I click on another page to navigate to - I want it to remove current from prev page and make curPage the new current (you can see I did this in jquery (i think i did it right)) and if i click on a sub menu. for instance i go to "web > web215 > JavaScript" when I click on javaScript I want the Web parent Web215 child AND the javaScript grandchild to highlight all with the 'current' id. but it's not doing it to any of them except for a quick second when i click - it's not saving it when the page loads. I think the culprit is somewhere in here:
function youAreHere() {
var pathName = $(location).attr('pathname');
var curPage = pathName.substring(pathName.lastIndexOf('/') + 1);
$('a').each(function () {
if ($(this).attr('href') == curPage) {
$(this).attr('id', 'current');
} else if (curPage == '') {
$('a:first').attr('id', 'current');
}
}); //END function
I know when i put an alert it's calling the page correctly and it's working as intended but the current class isn't either A: staying after it loads or B: loading up at all.
your css is wrong, you are setting the id of current to the a tag but in the css you are setting the id of current to the li tag. This is what you need:
div#menu li a#current {
font-weight: bold;
font-size: 16px;
z-index: 6;
background: transparent url('../images/menu_level1_item.png') repeat-x scroll 0pt 100%;
}
div#menu li a#current ul {
font-weight: normal;
font-size: 12px;
}