Add an outline to the currently hovered element - javascript

I would like all elements with the class "hoverOutline" to have an outline when you hover over them. This CSS works mostly fine:
.hoverOutline :hover {
outline: 2px solid black;
}
Only problem is this causes any parent elements with that class to have an outline as well. I understand that this is intended (as you are hovering over them too), but I would like to only outline the innermost child.(the one that would trigger an event first onclick).
I would like to add that I have looked into this, and most people use JQuery or some hacky work-around in pure CSS. For me, Javascript is 100% okay.
EDIT: This is for a bookmarklet, so I can't know in advance what elements will be on the page. This must work for ALL elements with that class, but that don't have a child with that class..

The element Selector are used to "find" (or select) HTML elements based on their element name, id, class, attribute, and more.
that mean you can have the same class but define the tag with that class to handle see examlpe
a.hoverOutline:hover {
outline: 2px solid black;
}
a {
width:220px;
height:50px;
display:inline-block;
background-color:blue;
color:white;
line-height:50px;
text-align:center;
margin:auto;
}
div.hoverOutline{
width:420px;
height:100px;
display:inline-block;
background-color:green;
}
<div class="hoverOutline"><a class="hoverOutline"> This a tag mast outline on hover</a></div>

Update
Demo 2 uses JavaScript to isolate and outline elements that meet two requirements:
Must have the .hover class
Must not have any descendants with the class .hover
Note: The <legend> has .hover class as well (actually everything has .hover), so as it fulfills the requirements, it too has the hover effects.
If the post you have submitted has no typos then the problem is pretty simple. A pseudo-class like :hover has a specific syntax in that it suffixes the targeted selector like so:
.hoverOutline:hover {
outline: 2px solid black;
}
To address the parent having the same class and you need to exclude the parent, try using the parent's tagName like so:
.hoverOutline:hover {
outline: 2px solid black;
}
section.hoverOutline:hover {
outline: 0 none transparent;
}
In these 2 rulesets the second one is applied to the parent by specifying it's a <section> and placing it after the original ruleset which is more general and lower in specificity.
Demo 1
.hoverOutline :hover {
outline: 2px solid black;
}
.hover:hover {
outline: 2px solid black;
}
fieldset.hover:hover{
outline:0 none transparent;
}
<fieldset>
<legend>Incorrectly Syntax</legend>
<button class='hoverOutline'>HOVER</button>
<button class='hoverOutline'>HOVER</button>
<button class='hoverOutline'>HOVER</button>
<button class='hoverOutline'>HOVER</button>
<button class='hov'>hover</button>
<button class='hoverOutline'>HOVER</button>
<button class='hoverOutline'>HOVER</button>
</fieldset>
<fieldset class='hover'>
<legend>Correct Syntax</legend>
<button class='hover'>HOVER</button>
<button class='hover'>HOVER</button>
<button class='hover'>HOVER</button>
<button class='hover'>HOVER</button>
<button class='hov'>hover</button>
<button class='hover'>HOVER</button>
<button class='hover'>HOVER</button>
</fieldset>
Demo 2
window.addEventListener('mouseover', mouseEnter, false);
window.addEventListener('mouseout', mouseLeave, false);
function mouseEnter(e) {
/* if hovered node is NOT the registered
|| event listener...
*/
if (e.target !== e.currentTarget) {
// Reference hovered element
var tgt = e.target;
// Reference the first child with .hover
var kid = tgt.querySelector('.hover');
/* if hovered node has class .hover and
|| does NOT have a child with class .hover...
*/
if (tgt.classList.contains('hover') && !kid) {
// add class .outline to hovered node
tgt.classList.add('outline');
// Otherwise do nothing and end function
} else {
return;
}
// Stop the bubbling phase
e.stopPropagation();
}
}
function mouseLeave(e) {
if (e.target !== e.currentTarget) {
var tgt = e.target;
tgt.classList.remove('outline');
}
e.stopPropagation();
}
form {
border: 1px solid black;
}
.outline {
outline: 3px solid red
}
<form id='form' class='hover'>
<fieldset class='hover'>
<legend class='hover'>Correct Syntax</legend>
<button class='hover'>HOVER</button>
<button class='hover'>HOVER</button>
<button class='hover'>HOVER</button>
<button class='hover'>HOVER</button>
<button class='hov'>hover</button>
<button class='hover'>HOVER</button>
<button class='hover'>HOVER</button>
</fieldset>
</form>

try this
$(".hoverClass1").hover(function(){
$(".hoverClass2").removeClass("hoverClass2");
$(this).addClass("hoverClass2");
},function(){
$(this).removeClass("hoverClass2");
});
.hoverClass:hover{
border:1px solid red
}
.hoverClass1{
}
.hoverClass2{
border:1px solid green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="hoverClass1">
<input type="text" class="hoverClass1" placeholder="hover me !!">
</div>

Related

I want to remove only the parent tag I clicked

There are 3 buttons in my code.
One is to add more files. (.btn-plus)
One is to remove the one added. (.btn-minus)
One is to reset the file. (.btn-reset)
I could add more input with (.btn-plus) button.
How could I delete only the one I click among every input I add with (.btn-plus)?
$(".btn-plus").click(function(){
$('.board-box__attachments').prepend('<li><div class="th">files</div><div class="td"><input type="file"><button class="btn btn-minus"> - </button></div></li>');
return false;
})
$(".btn-minus").click(function(){
$(this).nextUntil('li').remove()
})
$(".btn-reset").click(function(){
$(".board-box__attachments input").value = "";
})
li {
width : 60%;
background : lightblue;
list-style : none;
padding : 0.5em;
border-bottom : 1px solid white;
}
.th {
width : 100px;
float: left;
}
.td {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="board-box__attachments">
<li>
<div class="th">files</div>
<div class="td">
<input type="file">
<button class="btn btn-plus"> + </button>
<button class="btn-reset">Reset</button>
</div>
</li>
</ul>
You have to use on() to attach event to dynamically added element. Then use closest() to find currently clicked element's parent.
$("body").on("click", ".btn-minus", function(){
$(this).closest('li').remove();
})
$(this).nextUntil("li") doesn't match anything. It only searches siblings of this, and the button doesn't have any li siblings. If you want to select the li containing the button, use $(this).closest("li").
You also need to use event delegation to bind an event handler to dynamically-created elements.
$(".btn-plus").click(function(){
$('.board-box__attachments').prepend('<li><div class="th">files</div><div class="td"><input type="file"><button class="btn btn-minus"> - </button></div></li>');
return false;
})
$(".board-box__attachments").on("click", ".btn-minus", function(){
$(this).closest("li").remove()
})
li {
width : 50%;
background : lightblue;
list-style : none;
padding : 1em;
border-bottom : 1px solid white;
}
.th {
width : 100px;
float: left;
}
.td {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="board-box__attachments">
<li>
<div class="th">files</div>
<div class="td">
<input type="file">
<button class="btn btn-plus"> + </button>
</div>
</li>
</ul>
There are 2 issues with you code:
Your element which contains btn-minus is being created dynamically. So the click event would not work instead you need to use on event.
$(".btn-minus").click(function(){
So instead of this you need to use
$(document).on('click', '.btn-minus', function() {
Also you need to use following code to remove element.
$(this).closest('li').remove();
Please see the updated JSFiddle
Here you can creating elements dynamically so once the page is loaded, browser has no knowledge of '.btn-minus'
Try this:
$(document).on('click', '.btn-minus', function(){
$(this).closest('li').remove()
})
Hope this helps!

How to temporarily add an outline to :hover elements

I'm creating a bookmarklet that displays some information on the first element you click on after running the bookmarklet. I would love to have it so the element you are hovering over has an outline, but only before you click. After you have selected an element, the outline would no longer appear when hovering (except if it already did so before my bookmarklet).
To get the clicked element, this works fine for me:
function getClickedElement(e) {
document.removeEventListener("click", getClickedElement);
e.preventDefault();
clickedElement = e.target || e.srcElement;
// Some code that displays information on clickedElement...
}
document.addEventListener("click", getClickedElement);
But I don't know how to do the CSS. It would work like all elements gain this CSS:
:hover {
outline: 1px solid black;
}
while selecting an element, but that stops once an element has been selected. Hope that all made sense.
Small example with the principle explained!
If the user clicks on the element, add a specific class.
CSS Rule adds outline-border only if the element does not match the selector inside the :not pseudo class!
document.addEventListener('click', function(evt) {
var target = evt.target || evt.source;
if(!target.classList.contains('element')) return;
if(target.classList.contains('selected'))
target.classList.remove('selected');
else
target.classList.add('selected');
}, true);
div.element {
width:100px;
height:100px;
background-color:silver;
display:inline-block;
}
.element.selected {
background-color:black;
}
.element:not(.selected):hover {
outline: 1px solid red;
}
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>

CSS nth-child doesn't work on dynamically hidden element [AngularJS]

I'm trying to implement CSS nth-child on every number of elements. If a certain number is reached I want to hide the first element and make it reappear if the number reduces again.
The problem is that somehow the nth-child still counts the hidden element and thus wrongly implements the styling. Is this a bug or am I doing it wrong?
NOTE: The same thing also happens if I use jQuery
http://jsfiddle.net/bedex78/uZ5wn/23/
The View:
<div ng-app>
<div ng-controller="TheCtrl">
<p>Amount to add: <input type="text" ng-model="amount" ng-init="amount=1"></p>
<div class='holder'>
<div ng-class='elements.length < 6 ? "inside" : ""'
ng-hide="elements.length >= 6">
<button class='button' ng-click="add(amount)">Add more</button>
</div>
<div class='inside' ng-repeat="(k,v) in elements">
{{ $index }} Remove
</div>
</div>
</div>
</div>
The JS (AngularJS):
function TheCtrl($scope) {
$scope.elements = [{id:1},{id:2}]
$scope.add = function(amount) {
for (i=0; i < amount; i++){
$scope.elements.push({id:$scope.elements.length+1});
}
};
$scope.remove = function(index) {
$scope.elements.splice(index, 1);
};
}
The CSS:
.holder {
width: 300px;
height: 400px;
border: 1px solid black;
}
.inside {
height: 30px;
border: 1px solid black;
}
.inside:nth-child(3n+1) {
background-color: yellow;
}
.inside a {
float: right;
}
It happens because hidden element is still in DOM. So it is count as a child and styles applied accordingly.
You can try to use ng-if instead of ng-hide. It will make div disappear from DOM and styles will work fine.
Example

How to let onclick disappear after clicking on something else

I am just working on my new webspace and I have a small problem.
I know have to input tags with an onclick function
<script>
function mark( el ) {
el.style.borderBottom= "3px solid white";
}
</script>
When I click on the first input the border appears as I want but when I click on the other input the border of the first input tag is still there.
So how can I let the function only work when it's only clicked on the input tag itself and not when another input is clicked as well
Thanking you in anticipation
Just use CSS's :focus pseudo class:
input:focus {
border-bottom:3px solid red;
}
<input type="text">
<input type="text">
MDN Docs
You can easily use CSS Focus selector. input:focus
input:focus {
background-color: yellow;
border-bottom:3px solid white;
}
<div><input type="text"></div>
<br/>
<div><input type="text"></div>
Before you add style to this specific element you can remove style of all inputs or something like this:
function mark( el ) {
var input = document.getElementsByTagName("input");
for(var i =0;input.length>i;i++){
input[i].removeAttribute("style");
}
el.style.borderBottom= "3px solid white";
}
Here is what I would do. First, create a mark and an unmark functions. Then trigger the mark function at "onmousedown" and unmark at "onmouseup" event. Therefore, this border will only be shown when you have the mouse button pressed.
<script>
function mark( el ) {
el.style.borderBottom= "3px solid white";
}
function unmark( el ) {
el.style.borderBottom= "none";
}
</script>

How do I get this code working which is intended to change the text of a button upon clicking?

I'm trying to change the text and color of a button when the user clicks it.
I am trying to change the text from "Search" to "Close".
I have attempted to code it, and have posted what I tried in jsfiddle.
now another problem is I can't figure out why jsfiddle isn't running the code, haha, but maybe someone can figure it out regardless of the jsfiddle glitches.
Without further ado, my code...
HTML:
<form>
<p>
<button class="btn submit" type="submit" onClick="changeHeight();">Search</button>
<button class="btn cancel" onClick="changeHeight2();">Reset</button>
<div id="SearchDiv">Here I am</div>
</p>
</form>
CSS
p{
text-align:center;
background-color: rgb(222,222,222);
}
.btn{
margin-top:10px;
margin-bottom:10px;
font-size: 22px;
color:rgb(255,255,255);
width: 150px;
height: 60px;
outline: none;
border-radius:5px;
border:0;
}
.submit{
background-color: rgb(44,228,191);
}
.submit:hover{
background-color: rgb(24, 188, 156)!important;
}
.submit:active{
background-color: rgb(15,121,100)!important;
}
.cancel{
background-color: rgb(244,123,130);
}
.cancel:hover{
background-color: rgb(237,28,36)!important;
}
.cancel:active{
background-color: rgb(154,12,19)!important;
}
#SearchDiv {
background-color:purple;
height:50px;
display:none;
}
JS
function changeHeight() {
$('#SearchDiv').fadeIn(500);
}
function changeHeight2() {
$('#SearchDiv').fadeOut(200);
}
http://jsfiddle.net/fdkzp9dm/8/
You have a couple of things you need to change:
You need to change the fiddle from onload to No wrap in <body> as #Shaunak correctly commented.
You need to pass the element if you're not selecting it in the function. So you either do onClick="changeHeight($(this))" or inside the JS function you do $(el).
You need to check for el.text() == "Search" and to set using el.text("Close"), since you're checking the text inside and not a value attribute if you're doing el.value (that returns undefined for your example).
The last glitch is because the button is of type submit, and whenever clicking it the request failed and it overwritten the HTML.
So, basically:
function changeHeight(el) {
$('#SearchDiv').fadeToggle(500);
if (el.text()=="Search") {
el.text("Close");
}
else {
el.text("Search");
}
}
Fiddle
Using thecss and the text jquery's attributes will do the work:
$(document).ready(function() {
$('#button_id').click(function(){
$(this).text('another text')
$(this).css('height', '100px')
})
})
Here's a demo
Change your button like:
<button class="btn submit" type="submit" onClick="changeHeight($(this), $('#SearchDiv'));">Search</button>
Change your javascript function like so:
function changeHeight(btn, div)
{
if (div.is(":visible") )
{
btn.val("Search").css("color", "#ffffff"); // Color: White
div.fadeOut(500);
}
else
{
btn.val("Close").css("color", "#000000"); // Color: Black
div.fadeIn(500);
}
}

Categories