Prevent elements moving when dynamically adding a border - javascript

In my code, when you mouseover elements, a red border will appear around them. When you mouseout, the border is removed.
As you can see, when you do mousoevers, the elements are jumping around as the border adds width and height to it.
Is there a way to prevent the jumping around?
document.addEventListener("mouseover", eOnMouseOver, true);
document.addEventListener("mouseout", eOnMouseOut, true);
function eOnMouseOver(e) {
e.target.style.border = "2px solid red";
}
function eOnMouseOut(e) {
e.target.style.border = "";
}
<div style="border:1px black solid;">Mouseover me</div>
Mouseover me

Yes, there is. You must use box-sizing: borde-box together with vendor prefixes to achieve this. Here is what I mean:
document.addEventListener("mouseover", eOnMouseOver, true);
document.addEventListener("mouseout", eOnMouseOut, true);
function eOnMouseOver(e) {
e.target.style.outline = "2px solid red";
}
function eOnMouseOut(e) {
e.target.style.outline = "";
}
* {
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
}
<div style="border:1px black solid;">Mouseover me</div>
Mouseover me
However, you do not need to use javascript in this case. Use CSS pseudo-classes instead, like this:
* {
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-sizing: border-box;
-ms-sizing: border-box;
-o-sizing: border-box;
}
*:hover {
outline: 2px solid red;
}
<div style="border:1px black solid;">Mouseover me</div>
Mouseover me

How about using a box shadow instead? It does not influence your layout, is purely visual and keeps the border property of your div intact:
document.addEventListener("mouseover", eOnMouseOver, true);
document.addEventListener("mouseout", eOnMouseOut, true);
function eOnMouseOver(e) {
e.target.style.boxShadow = "0 0 0 2px red";
}
function eOnMouseOut(e) {
e.target.style.boxShadow = "none";
}
<div style="border:1px black solid;">Mouseover me</div>
Mouseover me

assign a transparent border, when mouse over add color to the border
div,
a {
border: 1px solid transparent;
}
div:hover,
a:hover {
border-color: red;
}
<div>Mouseover me</div>
Mouseover me

function eOnMouseOver(e) {
e.target.style.border = "2px solid red";
e.target.style.marginLeft = "-2px";
e.target.style.marginTop = "-2px";
}
function eOnMouseOut(e) {
e.target.style.border = "";
e.target.style.marginLeft = "";
e.target.style.marginTop = "";
}
Try that. The margin offset should pull the element up and left by the 2px your border is pushing, theoretically keeping the element stable. Untested.
EDIT: Another solution would be to do the following...
function eOnMouseOver(e) {
e.target.style.border = "2px solid red";
}
function eOnMouseOut(e) {
e.target.style.border = "2px solid transparent";
}
Then simply apply the border in the eOnMouseOut(e) function to the base element so it doesn't bounce on the first mouseOver.

Related

How to use Input Type Color with Javascript to style css selector?

I have the following CSS for a button:
.btn {
background-color:#0d0d0d;
color: #00b0f0;
border: .74px solid currentcolor;
font-size: 16px;
padding: 16px 32px;
cursor: pointer;
}
.btn:hover {
background-color: #00b0f0;
color: #0d0d0d;
}
.btn:active {
background-color: #00b0f0;
box-shadow: 0 5px #666;
transform: translateY(4px);
}
I also have this color input eyedropper tool in my HTML:
<input type="color" id="s0r4c52" value="#00b0f0" style="border:none;">
Finally, I have this function I found on the internet that allows me to style CSS selectors with any color input that I choose.
let picker1;
const defaultColor = "#00b0f0";
window.addEventListener("load", startup, false);
function startup() {
picker1 = document.querySelector("#s0r4c52");
picker1.value = defaultColor;
picker1.addEventListener("input", updateFirst, false);
picker1.addEventListener("change", updateAll, false);
picker1.select();
}
function updateFirst(event) {
const p = document.querySelector("td,input,select,.ce31,.slider,.nav li,.nav,.nav li a,.btn");
if (p) {
p.style.color = event.target.value;
}
}
function updateAll(event) {
document.querySelectorAll("td,input,select,.ce31,.slider,.nav li,.nav,.nav li a,.btn").forEach((p) => {
p.style.color = event.target.value;
});
}
My question is how do I style the :hover and :active background of the button with the color picker. I want the button to have black (#0d0d0d) text when hovered and clicked, but have the button background change color to whatever I choose with the color picker.
I have found all these codes on the internet and through many hours of trial have gotten it to work for styling at least some CSS selectors. Is there a more efficient way to do all of this??

Drag and Drop Quiz Vanilla Javascript

I'm currently building a simple drag and drop Quiz but I'm allowed only to use html css and vanilla javascript.
The idea is there is a div with the answers and a div with the questions. In the questions text there are some blank divs where you can drop the draggable answers.
For example you have the answers "a,b,c" and "x,y,z" and the question is "The 1st three letters of the alphabet are: ___"
I need help on two main things:
I want to have the question's blank divs allow only one element drop per div. (I can stack them atm)
After drop I want to check if the answers in the current questions divs are correct.
How can I do?
P.S. I'm a newbie on html/css/js so maybe tell me just if it's not possible to impement this without external libraries and php.
/* Events fired on the drag target */
document.addEventListener("dragstart", function(event) {
// The dataTransfer.setData() method sets the data type and the value of the dragged data
event.dataTransfer.setData("Text", event.target.id);
// Output some text when starting to drag the p element
document.getElementById("demo").innerHTML = "Started to drag the p element.";
// Change the opacity of the draggable element
event.target.style.opacity = "0.4";
});
// While dragging the p element, change the color of the output text
document.addEventListener("drag", function(event) {
document.getElementById("demo").style.color = "red";
});
// Output some text when finished dragging the p element and reset the opacity
document.addEventListener("dragend", function(event) {
document.getElementById("demo").innerHTML = "Finished dragging the p element.";
event.target.style.opacity = "1";
});
/* Events fired on the drop target */
// When the draggable p element enters the droptarget, change the DIVS's border style
document.addEventListener("dragenter", function(event) {
if ( event.target.className == "droptarget" ) {
event.target.style.border = "3px dotted red";
}
});
// By default, data/elements cannot be dropped in other elements. To allow a drop, we must prevent the default handling of the element
document.addEventListener("dragover", function(event) {
event.preventDefault();
});
// When the draggable p element leaves the droptarget, reset the DIVS's border style
document.addEventListener("dragleave", function(event) {
if ( event.target.className == "droptarget" ) {
event.target.style.border = "";
}
});
/* On drop - Prevent the browser default handling of the data (default is open as link on drop)
Reset the color of the output text and DIV's border color
Get the dragged data with the dataTransfer.getData() method
The dragged data is the id of the dragged element ("drag1")
Append the dragged element into the drop element
*/
document.addEventListener("drop", function(event) {
event.preventDefault();
if ( event.target.className == "droptarget" ) {
document.getElementById("demo").style.color = "";
event.target.style.border = "hidden";
var data = event.dataTransfer.getData("Text");
event.target.appendChild(document.getElementById(data));
}
});
.droptarget {
display: inline-block;
min-width: 50px;
height: 25px;
border: 1px solid #aaaaaa;
color: #000;
text-align: center;
}
.container {
display: inline-block;
padding: 15px;
margin: 10px;
background: #eee;
border: 2px solid black;
border-radius: 5px;
box-sizing:border-box;
}
.dragtarget {
background-color: red;
padding: 5px;
border-radius: 5px;
color: #fff;
font-weight: bold;
text-align: center;
}
.domande {
display: inline-block;
padding: 15px;
margin: 10px;
background: #eee;
border: 2px solid black;
border-radius: 5px;
box-sizing:border-box;
}
<p>Trascina la risposta nel quadrato giusto</p>
<div class="container">
<p draggable="true" class="dragtarget" id="dragtarget">A,B,C</p>
<p draggable="true" class="dragtarget" id="dragtarget">1,2,3</p>
</div>
<div class="domande">
<h3>Prime tre lettere dell'alfabeto<div class="droptarget"></div></h3>
<h3>Primi tre numeri<div class="droptarget"></div></h3>
</div>
<p id="demo"></p>
Using the same id is really bad, it can only get the first element encounter with getElementById. Instead, I'll capture dragging DOM with dragstart and use it later on drop. In drop you just need to check if is there any child element inside of it. If it does, append that child back to .container.
You didn't include any details about how you will check so it's hard to help, I can only help you get the question and answer out.
var dragP;
/* Events fired on the drag target */
document.addEventListener("dragstart", function (event) {
// The dataTransfer.setData() method sets the data type and the value of the dragged data
// event.dataTransfer.setData("Text", event.target.id);
dragP = event.target;
// Output some text when starting to drag the p element
document.getElementById("demo").innerHTML = "Started to drag the p element.";
// Change the opacity of the draggable element
event.target.style.opacity = "0.4";
});
// While dragging the p element, change the color of the output text
document.addEventListener("drag", function (event) {
document.getElementById("demo").style.color = "red";
});
// Output some text when finished dragging the p element and reset the opacity
document.addEventListener("dragend", function (event) {
document.getElementById("demo").innerHTML = "Finished dragging the p element.";
event.target.style.opacity = "1";
});
/* Events fired on the drop target */
// When the draggable p element enters the droptarget, change the DIVS's border style
document.addEventListener("dragenter", function (event) {
if (event.target.className == "droptarget") {
event.target.style.border = "3px dotted red";
}
});
// By default, data/elements cannot be dropped in other elements. To allow a drop, we must prevent the default handling of the element
document.addEventListener("dragover", function (event) {
event.preventDefault();
});
// When the draggable p element leaves the droptarget, reset the DIVS's border style
document.addEventListener("dragleave", function (event) {
if (event.target.className == "droptarget") {
event.target.style.border = "";
}
});
/* On drop - Prevent the browser default handling of the data (default is open as link on drop)
Reset the color of the output text and DIV's border-color
Get the dragged data with the dataTransfer.getData() method
The dragged data is the id of the dragged element ("drag1")
Append the dragged element into the drop element
*/
document.addEventListener("drop", function (event) {
event.preventDefault();
let targetDiv = event.target;
if (targetDiv.className == "droptarget") {
document.getElementById("demo").style.color = "";
targetDiv.style.border = "hidden";
if (targetDiv.childElementCount != 0){
let childP = targetDiv.getElementsByTagName("p")[0];
document.getElementById("answer").appendChild(childP);
}
targetDiv.appendChild(dragP);
dragP = null;
}
});
document.getElementById("checkAnswer").addEventListener("click", function () {
let questions = document.getElementsByClassName("question");
let resultP = document.getElementById("result");
resultP.innerHTML = "";
for (let index = 0; index < questions.length; index++) {
const element = questions[index];
let childP = element.getElementsByTagName("p")[0];
let question = element.childNodes[0].textContent;
let answer = childP != undefined ? childP.innerText : "no answer";
resultP.append(`${question} : ${answer} ; `);
}
})
.droptarget {
display: inline-block;
min-width: 50px;
height: 25px;
border: 1px solid #aaaaaa;
color: #000;
text-align: center;
}
.container {
display: inline-block;
padding: 15px;
margin: 10px;
background: #eee;
border: 2px solid black;
border-radius: 5px;
box-sizing: border-box;
}
.dragtarget {
background-color: red;
padding: 5px;
border-radius: 5px;
color: #fff;
font-weight: bold;
text-align: center;
}
.domande {
display: inline-block;
padding: 15px;
margin: 10px;
background: #eee;
border: 2px solid black;
border-radius: 5px;
box-sizing: border-box;
}
<p>Trascina la risposta nel quadrato giusto</p>
<div class="container" id="answer">
<p draggable="true" class="dragtarget" id="dragtarget">A,B,C</p>
<p draggable="true" class="dragtarget" id="dragtarget">1,2,3</p>
</div>
<div class="domande">
<h3 class="question">Prime tre lettere dell'alfabeto<div class="droptarget"></div>
</h3>
<h3 class="question">Primi tre numeri<div class="droptarget"></div>
</h3>
</div>
<p id="demo"></p>
<button id="checkAnswer">Check</button>
<p id="result"></p>

Hover , Focus and Blur conflict

I want to apply 4 effects on an element:
On hovering over the element.
On hovering away from the element.
On focusing on the element.
On blur.
But there is a conflict happens , When I focus on the element the hover in and out runs , and when I click outside the element the effect that should happens on blur doesn't happen , I think it's because of the hover out.
var el = $('input');
el.focus(function() {
el.css('border', '1px solid green');
});
el.hover(function() {
el.css('border', '1px solid green');
}, function() {
el.css('border', '1px solid grey');
});
el.blur(function() {
if (el.val == '') {
el.css('border', '1px solid red');
} else {
el.css('border', '1px solid grey');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input type='text' />
On hovering in the border color turns green , on hovering out it turns grey.
But on focusing on the input the color is grey not green, and in blur it's grey too not red.
The issue is due to the logic in your if condition. el.val returns the reference of the function, which will never equate to an empty string. You need to use el.val() instead to get the actual value of the control:
var el = $('input');
el.focus(function() {
el.css('border', '1px solid green');
});
el.hover(function() {
el.css('border', '1px solid green');
}, function() {
el.css('border', '1px solid grey');
});
el.blur(function() {
if (el.val() == '') {
el.css('border', '1px solid red');
} else {
el.css('border', '1px solid grey');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input type='text' />
That being said I would suggest combining CSS rules with this where possible, and definitely using classes over joining the styling rules with the JS code so tightly. Something like this:
var el = $('input');
el.blur(function() {
$(this).toggleClass('empty', $(this).val().trim() === '');
});
input {
outline: 0;
border: 2px solid grey;
}
input:hover,
input:focus {
border: 2px solid green;
}
input.empty {
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input type='text' />

Background color not changing in Chrome when mouse up

I have 4 buttons in a page out of 4 one button is multi select button (like selection box). When I mouse over the color of the button will change and while mouse out the color of the button will change to normal. But if I click on the multiselect button the color is changing (which is fine) and it shows the data like dropdown but, if I mousehover to other button then the color of the multiselect button is not changing to normal, this happens only in Chrome and in IE11 it is working fine.
Below is my code:
<div id="ButtonDiv" class="btn"><a class="btn-a-normal" id="MORE_ACT" onmousedown="BtnUtilities.buttonDown(this)" onmouseup="BtnUtilities.buttonUp(this)" onmouseleave="BtnUtilities.buttonUp(this)" onmouseout="BtnUtilities.buttonUp(this)" onselectstart="return false" href="javascript:void(0)" data-href="javascript:void(0)">
var BtnUtilities = {
buttonDown: function(element) {
element.className = "btn-a-pressed";
},
buttonUp: function(element) {
element.className = "btn-a-normal";
}
};
.btn > a.btn-a-normal > div.btn-border, .buttonOn > a.btn-a-normal > div.btn-border {
border-style: solid ;
border-width: 1px ;
border-color: #c7c7c7 #c7c7c7 #c7c7c7 #c7c7c7 ;
}
.btn > a.btn-a-pressed > div.btn-border, .buttonOn > a.btn-a-pressed > div.btn-border {
border-style: solid ;
border-width: 1px ;
border-color: #4b4b4b #4b4b4b #4b4b4b #4b4b4b ;
}
Could you please let me know where I am wrong?
check this simple code which help you
<div id="ButtonDiv" class="btn"><a class="btn-a-normal" id="MORE_ACT" onmouseover="buttonDown(this)" onmouseout="buttonUp(this)">test</a>
</div>
<script>
function buttonDown(element) {
element.className = "btn-a-pressed";
}
function buttonUp(element) {
element.className = "btn-a-normal";
}
</script>
<style>
.btn > a.btn-a-normal {
color: red;
}
.btn > a.btn-a-pressed {
color: green;
}
</style>

How to change css li style with javascript?

I have like link like this:
My Button
and css style:
.tree li a:hover, .tree li a:hover+ul li a {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}
And my question is how to change this .tree style to another one? And if i click again the style return to the beginning style?
it can be done in plain javascript as below :
var id = 'myElementId';
var myClassName = " tree";
var d;
function changeClass() {
d = document.getElementById(id);
if (d.className == ' tree') {
d.className = d.className.replace(myClassName, "");
} else {
//d=document.getElementById('myElementId');
d.className = d.className.replace(myClassName, ""); // first remove the class name if that already exists
d.className = d.className + myClassName; // adding new class name
}
}
.tree {
background: #c8e4f8;
color: #000;
border: 1px solid #94a0b4;
}
<a id="myElementId" href="#" onclick="changeClass()">My Button</a>
now in jQuery it can be achieved using toggle as below :
var id = 'myElementId';
var myClassName = " tree";
function changeClass() {
$('#' + id).toggleClass(myClassName);
}
.tree {
background: #c8e4f8;
color: #000;
border: 1px solid #94a0b4;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<a id="myElementId" href="#" onclick="changeClass()">My Button</a>
Use classList.toggle("className") to toggle a class.
var div = document.getElementById("myDiv");
div.classList.toggle("myClassToggle");
Use this small javascript function:
function toggleClass(el, class1, class2) {
if(new RegExp("\\b"+class1+"\\b").test(el.className)) {
el.className = el.className.replace(new RegExp("\\b"+class1+"\\b",'g'),class2);
} else {
el.className = el.className.replace(new RegExp("\\b"+class2+"\\b",'g'),class1);
}
}
a {
display:block;
padding:10px;
color:white;
}
.myclass1 {
background:red;
}
.myclass2 {
background: green;
}
My Button
Edit: make sure that the classname is not in another word
A simple way to do this would be create another css class selector and assign to it your desired styles in the css file say .my-tree for example.
.my-tree {
color: red;
}
Now when your anchor is clicked you can add this css class to your tree element.
var treeEl = document.getElementById("tree");
treeEl.className = treeEl.className + " my-tree":
Similarly you can also remove this css class. You can use a variable in your code as a flag and use to add/remove the css class.
A simple way of doing this is to use the
toggleClass method of jquery which does this in a seamless manner.
Just going to throw this out there - you can do it in pure CSS:
[type=checkbox] {
display:none;
}
/* This selects the div tag immediately following the checkbox */
[type=checkbox] + div {
background:red;
cursor:pointer;
}
/* The same selector, except this is active when the checkbox is checked */
[type=checkbox]:checked + div {
background:blue;
color:#fff;
}
<label>
<input type="checkbox">
<div>Change me!</div>
</label>
This breaks a few rules for valid HTML, but if all you need is to toggle something (and not care about validation or quirksmode), this solution is pretty simple. If you do care about validation:
[type=checkbox] {
display:none;
}
[type=checkbox]:checked + label {
background:blue;
color:#fff;
}
[type=checkbox] + label {
background:red;
display:block;
}
<input id="toggler" type="checkbox">
<label for="toggler">
Change me!
</label>
Just something to chew on.
You can use jQuery
HTML:
My Button
JS:
$( "#myLink" ).click(function() {
$( "#myLink" ).toggleClass("first");
$( "#myLink" ).toggleClass("second");
});
CSS:
.first {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}
.second {
background: #000; color: #fff; border: 1px solid #94a0b4;
}

Categories