Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have two div . div-1 and div-2 .it need to stay all the time but i want some menu items using another div name div-3 which is visible when button clicks. i want div-3 over div-1 and div-2 at the same time .how can i do that ?
JavaScript Notes
An IIFE is a very common design pattern in JavaScript commonly used to hide your code so that it doesn't get changed by other scripts.
You can add event listeners to elements using the addEventListner function.
You can get an HTMLElement using the querySelector function which accepts a selector. So to get the first div you could use document.querySelector("div"). To get the element with id "item" you can use document.querySelector("#item"). To get the first element element with class "active" you can use document.querySelector(".active"). You can also use document.querySelector("div#item.active") to get the item the fills all the previous requirements or document.querySelector("div, #item, .active") to get the item that fills any of the requirements. As you can see this works the same as CSS selectors.
To check if a variable is an instance of a Class you can use instanceof.
There are several ways to change how an Element looks using JavaScript.
One is to change the class name element.className = "active", another is to directly change the styling element.style = "opacity: 1;".
Styling Notes
To position an element on top of other elements you need to set its position to absolute and the container's element to relative. When you absolutely position an element then its positioned relatively to the last container that is positioned relatively (default is <html> element).
There are 2 main ways to position elements next to each other: float: left; and display: inline-block;. This works like writing on a notepad, it fits as many elements on next to each other and the repeats the same process below them.
There are 3 common ways to hide an element. 1: opacity: 0; which just makes the item invisible but it it's still there so you should probably also use pointer-events: none; so that it doesn't stop you from clicking what's behind it. 2: height: 0; This just shrinks the element so that it has no height which essentially makes it invisible. 3: display: block; this essentially completely removes the element.
Example
// IIFE Design Pattern
(function() {
// Run onLoad function if page is fully loaded
if (document.readystate === "complete") onLoad();
// Else add an event listener to call onLoad function when page gets fully loaded
else document.addEventListener("DOMContentLoaded", onLoad);
var divIsActive = false;
/**
* Function to be called when page is fully rendered
* #returns {void}
*/
function onLoad() {
// Find button
var button = document.querySelector("#toggle");
// Check if the button was found
if (button instanceof HTMLElement) {
// Add an click event listener
button.addEventListener("click", toggle);
}
}
/**
* Toggles the div to open/close
* #returns {void}
*/
function toggle() {
// Find Div
var div = document.querySelector("#div-3");
// Check if the div was found
if (div instanceof HTMLElement) {
// swap the boolean value
divIsActive = !divIsActive;
// change the classname based on the boolean value
div.className = divIsActive ? "active" : "";
}
}
})();
html,
body {
height: 100%;
width: 100%;
margin: 0;
}
#container {
position: relative;
height: 100%;
width: 100%;
}
#div-1, #div-2 {
height: 100%;
float: left;
width: 50%;
}
#div-1 {
background-color: brown;
}
#div-2 {
background-color: pink;
}
#div-3 {
background-color: green;
pointer-events: none;
transition: all 0.4s;
position: absolute;
height: 40%;
opacity: 0;
right: 0;
left: 0;
top: 0;
}
#div-3.active {
pointer-events: all;
opacity: 1;
}
#toggle {
position: absolute;
cursor: pointer;
z-index: 99999;
right: 10px;
top: 10px;
}
<div id="container">
<button id="toggle">Toggle</button>
<div id="div-1"></div>
<div id="div-2"></div>
<div id="div-3"></div>
</div>
Related
This question already has answers here:
JavaScript and getElementById for multiple elements with the same ID
(13 answers)
Closed 1 year ago.
Good day,
I have a CSS grid of 9 square divs, and I would like to add a click event for all of them so that their color changes from limegreen to black, and then changes back to limegreen when the mouse leaves. I am able to do so if I give each div a unique ID and use .addEventListener, but then the issue is I have to write a click event for each div. When I try to give each div the same ID and use .addEventListener, the click event only happens with the first div.
I have spent the past hour or two searching Stackoverflow, Google, forums, and other websites, along with tinkering with my code based on what I've found, but I can't find anything that has helped so far.
Here is my code, but I've only included the HTML/CSS for the first two divs, since the rest of the divs are like the 2nd div and don't respond to clicks:
const dude = document.getElementById("dude");
dude.addEventListener("click", function(){
dude.style.backgroundColor = "black";
});
dude.addEventListener("mouseleave", function(){
dude.style.backgroundColor = "limegreen";
})
.container {
display: grid;
margin: 7rem;
position: relative;
grid-template-columns: auto auto auto;
align-items: center;
justify-content: center;
column-gap: 2.5rem;
row-gap: 2.5rem;
}
.box {
background: limegreen;
width: 10rem;
height: 10rem;
position: relative;
}
.box2 {
background: limegreen;
width: 10rem;
aspect-ratio: 1/1;
position: relative;
}
<div class="container">
<div class="box" id="dude"></div>
<div class="box2" id="dude"></div>
</div>
Thank you very much for your help!
In HTML, two or more elements cannot have the same ID.
In your HTML, add a common class to the div(s) inside of .container.
<div class="container">
<div class="box gridbox"></div>
<div class="box2 gridbox"></div>
</div>
Now use this Javascript code:
/**
* Use this because we're getting the elements with
* their class, not id. This method returns an array
* of the elements with matching class.
*/
const dudes = document.getElementsByClassName("gridbox");
/** Loop over the whole array */
for(let dude of dudes){
/** Add click event handler */
dude.addEventListener("click", () => {
dude.style.backgroundColor = "black";
});
/** Add mouseleave event handler */
dude.addEventListener("mouseleave", () => {
dude.style.backgroundColor = "limegreen";
});
}
This should work fine.
I've got a simple text button with an image of an arrow next to it. I'm wanting the arrow image to move when someone hovers over the button.
I currently have this working in one instance with JS 'document.getElementById...', but I have several buttons across my site that I'd like to have the same behavior. My first thought would be to use a class instead of an id, and use the same functions.
For whatever reason, document.getElementsByClassName doesn't work - even in one instance.
Here's a simpler version to demonstrate - View on Codepen: https://codepen.io/sdorr/pen/JxYNpg
HTML
<HTML>
hover over me
<div id="block"></div>
hover over me
<div class="block"></div>
CSS
* {
margin: 0;
padding: 0;
}
.button {
color: #000000;
text-decoration: none;
background-color: cyan;
margin: 0;
display: block;
width: 300px;
padding: 20px;
text-align: center;
}
#block {
width: 30px;
height: 30px;
background-color: red;
}
.block {
width: 30px;
height: 30px;
background-color: green;
}
JS
function move() {
document.getElementById("block").style.marginLeft = "35px";
}
function moveBack() {
document.getElementById("block").style.marginLeft = "0px";
}
function moveAlt() {
document.getElementsByClassName("block").style.marginLeft =
"35px";
}
function moveBackAlt() {
document.getElementsByClassName("block").style.marginLeft =
"0px";
}
First off, why isn't the behavior with a class working but an id works fine?
Secondly, would a class solve this issue and be scalable across all buttons with the same two functions (onmouseover / onmouseout)?
If not, any ideas on a solution? I currently have a solution I found using jQuery that does work, but when hovering over one button, all arrow images move across the site. I don't necessarily mind this behavior because only one button is really in view at a time - but I'm trying to learn JS and solve problems with my own solutions!
I greatly appreciate your desire to learn on your own and not rely on premade solutions. Keep that spirit and you will go places!
When it comes to getElementsById, we know this should work for one element, since the function returns a single Element.
However, what does getElementsByClassName return?
(see: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName)
It returns an HTMLCollection which you can iterate over to change an single element's style.
So, to get this to work with JavaScript you need to write a function that will be able to identify the particular div.block you want to move. But, this puts you back to where you started, needing some particular identifier, like an id or a dataset value to pass to the function.
Alternately, based on the HTML structure you provide, you could look for nextElementSibling on the a that get's clicked. But I would set up an eventListener rather than adding a JS function as a value to the onmouseenter property.
const btns = document.getElementsByTagName('a');
/*** UPDATE forEach is a NodeList method, and will fail on HTMLCollection ***/
/* this fails -> Sorry! ~~btns.forEach(button=>{~~
/* the following will work
/**********/
for (let i = 0; i < btns.length; i++){
btns[i].addEventListener('mouseenter', function(e) {
//we pass e to the function to get the event and to be able to access this
const block = this.nextElementSibling;
block.style.marginLeft = "35px";
})
btns[i].addEventListener('mouseleave', function(e) {
const block = this.nextElementSibling;
block.style.marginLeft = "0";
})
}
But with siblings, there is a CSS-only solution.
We can use the Adjacent Sibling Selector combined with the :hover state selector and no JavaScript is needed, if we are just moving back and forth.
.button:hover+.block {
margin-left: 35px;
}
See the Snipped Below
* {
margin: 0;
padding: 0;
}
.button {
color: #000000;
text-decoration: none;
background-color: cyan;
margin: 0;
display: block;
width: 300px;
padding: 20px;
text-align: center;
}
.block {
width: 30px;
height: 30px;
background-color: green;
}
.button:hover+.block {
margin-left: 35px;
}
hover over me
<div class="block"></div>
hover over me
<div class="block"></div>
As Vecta mentioned, getElementsByClassName returns an array-like. You'll need to do something like this to get the first element:
function moveAlt() {
document.getElementsByClassName("block")[0].style.marginLeft = "35px";
}
function moveBackAlt() {
document.getElementsByClassName("block")[0].style.marginLeft = "0px";
}
However a better solution might be to use document.querySelector, which operates similarly to jQuery's $() syntax:
function moveAlt() {
document.querySelector(".block").style.marginLeft = "35px";
}
function moveBackAlt() {
document.querySelector(".block").style.marginLeft = "0px";
}
This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 4 years ago.
I am following this tutorial from W3Schools on how to build a slideshow using HTML, CSS, and Javascript. On the website I am developing, I would like the thumbnails at the bottom and the arrows on the sides to be initially hidden, until the user presses a button.
To do so, in the CSS file, I have set the visibility: hidden;. The CSS code for the class dot, which is the bottom thumbnail, is as follows:
.dot {
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
visibility: hidden;
transition: background-color 0.6s ease;
}
In the Javascript action for the button, I have set the visibility of the document's elements under the class "dot" to visible, like so:
document.getElementsByClassName("dot").style.visibility="visible";
I have verified that this action is being triggered when the button is pressed through an alert() view. Every line of code seems to run as intended up until this command. Also, the thumbnails at the bottom (the "dot" elements) do not appear, so their visibility does not become visible as intended.
Any ideas on why this may be, or how I can fix it? Thanks a lot for your help!
This document.getElementsByClassName("dot") returns an array and you cannot apply a style attribute to the array.
I'll give you a couple ideas about how you might approach or reconsider this problem.
1) loop through the array and apply a style to each element
var elements = document.getElementsByClassName("dot")
for(var i = 0; i < elements.length; i++) {
elements[i].style.visibility = "visible";
}
2) give an ID to each class and call document.getElementById("someID")
<div id="one">one</div>
<div id="two">two</div>
<div id="three">three</div>
document.getElementyById("one").style.visibility = "visible";
document.getElementyById("two").style.visibility = "hidden";
document.getElementyById("three").style.visibility = "hidden";
document.getElementsByClassName() will return an array.
If you have only one element you could use the first index in the array:
document.getElementsByClassName("dot")[0].style.visibility="visible";
Else if you have more that one:
var dot = document.getElementsByClassName("dot")
for(var i = 0; i < dot.length; i++) {
dot[i].style.visibility = "visible";
}
This question already has answers here:
How can i position a dropdown at cursor position inside a textarea?
(2 answers)
Closed 9 years ago.
I've seen a few questions like this but can't find a solution. I have a textbox. When the user is typing along, if they press #, I'd like to show a list of items they can select from, at that caret's position (i.e. the place in the textbox where the next character typed will appear, not the location of the mouse cursor).
JSfiddle: http://jsfiddle.net/LR8pe/
Code:
$(".textarea").bind("keypress", function (e) {
if (String.fromCharCode(e.keyCode) == '#') {
$(".list").show();
} else{
$(".list").hide();
}
});
I have the basic mechanics down, but showing/hiding at the position of the caret is where I'm stuck.
I'm using jquery/knockout, but pure JS is fine with me.
Here is a purely CSS approach:
http://jsfiddle.net/p774G/2/
Surround your textarea and list in a container:
<div class="spacer"></div>
<div class="list-container">
<textarea class="textarea"></textarea>
<ul class="list">
<li>item</li>
</ul>
</div>
Modify your CSS so that the textarea is a fixed size, then position your list at the bottom of it:
textarea
{
width: 300px;
height: 70px;
padding: 3px;
}
.list {
list-style: none;
background-color: gray;
display: none;
position: absolute;
top: 76px;
left: 0;
margin: 0;
padding: 0;
border: 0;
}
.list-container
{
position: relative;
}
.list li
{
padding: 5px;
width: 294px;
}
EDIT:
I would not recommend spawning this box where the mouse cursor is, as you do not know where the user will have his or her cursor. It could be off the page for all you know. This is a bad user experience. Instead spawn it below the textarea as I did in my answer.
Using your jsFiddle: http://jsfiddle.net/zCLu9/1/
Basically, I created 2 global variables responsible for holding the mouse's X and Y coordinates which are updated on mousemove so they're always (well, almost always) accurate. Then those coordinates are used to set the offset of the .list element whenever it's supposed to be displayed.
I also set the element's position to absolute in the CSS.
I am applying a class (rShift) to a DIV that acts as a menu tab. The class gives it a :hover behaviour. On clicking the DIV, I bring in a menu on to the screen. On collapsing the menu, I loose the class and the :hover behaviour too.
I am using jQuery UI and have even tried .addClass('') to apply the lost class, but it did not work.
See it at: http://pastebin.com/hdb8Y2Ke | http://bharath.lohray.com/ftree/
When the page is initially loaded, you can see a tab at the top left corner of the page, just under the search box. On hovering the mouse it jumps out a few pixels. On clicking, the menu appears. On clicking the tab again, the menu collapses and the jump out effect is lost :-(.
What am I doing wrong?
The class is being added, but on click, you are applying an inline style to the leftmenutab directly via jquery. This style (left) overrides any styles you have in your style sheets.
I would remove the inline styles you are applying via jquery and add the styles you want to your css.
Create styles like this:
.leftMenuTab[data-state="expanded"] { left: 100px; }
.leftMenuTab[data-state="collapsed"] { left: 0; }
and remove these lines from your javascript:
$(".leftMenuTab").css("left", "+=100px");
$(".leftMenuTab").css("left", "-=100px");
Alternatively, add and remove classes from your leftMenuTab and leftMenu on click and style them through CSS. Something like this:
HTML:
<div class="leftMenu">Hello Menu</div>
<div class="leftMenuTab" data-state="collapsed">
<span class="charIcon"></span>
</div>
JS:
$('.leftMenuTab').click(function(e) {
$('.leftMenuTab,.leftMenu').toggleClass('expanded');
}
CSS:
.leftMenuTab .charIcon:after{
content:'>>';
}
.leftMenuTab.expanded .charIcon:after{
content:'<<';
}
.leftMenuTab {
background-color: #FFFFFF;
border-color: #000000;
cursor: pointer;
float: left;
padding-right: 5px;
position: absolute;
text-align: right;
top: 45px;
width: 30px;
z-index: 2;
left: -10px;
}
.leftMenuTab:hover {left:0;}
.leftMenuTab.expanded { left:100px;}
After you modify the style of the element, the style left: 0px; is left in the DIV, this neglated the effect of the hover.
This is the relevant code:
$('.leftMenuTab').click(function(e) {
temp = $(this);
if ($('.leftMenuTab').attr('data-state') == "collapsed") {
$(".charIcon", this).html("«");
$('.leftMenuTab').attr('data-state', 'expanded');
$(".leftMenu").css("left", "+=110px");
$(".leftMenuTab").css("left", "+=100px");
} else {
$(".charIcon", this).html("»");
$('.leftMenuTab').attr('data-state', 'collapsed');
$(".leftMenu").css("left", "-=110px");
$(".leftMenuTab").css("left", "-=100px");
$(this).addClass("rShift");
}
});
The quickest fix is to erase the left style instead of modyfing it (and you don't need to add the class again):
$('.leftMenuTab').click(function(e) {
temp = $(this);
if ($('.leftMenuTab').attr('data-state') == "collapsed") {
$(".charIcon", this).html("«");
$('.leftMenuTab').attr('data-state', 'expanded');
$(".leftMenu").css("left", "+=110px");
$(".leftMenuTab").css("left", "+=100px");
} else {
$(".charIcon", this).html("»");
$('.leftMenuTab').attr('data-state', 'collapsed');
$(".leftMenu").css("left", ""); //set to empty string
$(".leftMenuTab").css("left", ""); //set to empty string
//$(this).addClass("rShift"); //Not needed
}
});
Note: this was tested with a local copy from your web.