mouseenter and mouseleave in javascript not working - javascript

I am having issue with the mouseenter and the mouseleave event in javascript. The strange thing is that the code works if you substitute these 2 events with click or dblclick events. Hope you can help me here.
PS: I'm using chrome.
don't know how to make js work on fiddle... for now
here's the code:
https://jsfiddle.net/frempong69/t7du0kte/
(function() {
window.onload = function() {
var box = document.getElementsByClassName("box")[0];
var change = function() {
box.style.backgroundColor = "green";
};
var normal = function() {
box.style.backgroundColor = "blue";
}
addEventListener("click", change, false);
addEventListener("mouseleave", normal, false);
};
}());

You are adding the mouseleave/mouseenter handlers to the window object. The click handler works because it bubbles to the window object, but the mouseenter and mouseleave events doesn't bubble so the listeners attached to the window object won't get triggered
You need add the listerns to the box element
(function() {
window.onload = function() {
var box = document.getElementsByClassName("box")[0];
var change = function() {
box.style.backgroundColor = "green";
};
var normal = function() {
box.style.backgroundColor = "blue";
}
box.addEventListener("mouseenter", change, false);
box.addEventListener("mouseleave", normal, false);
};
}());
.box {
background-color: red;
width: 400px;
height: 200px;
margin: 50px auto;
position: relative;
}
.box:after {
content: " ";
width: 0px;
height: 0px;
border-top: 100px solid transparent;
border-right: 100px solid transparent;
border-bottom: 100px solid transparent;
border-left: 100px solid red;
position: absolute;
left: 100%;
top: 50%;
margin-top: -100px
}
<div class="box">
</div>

You can simply do like this
box.onmouseenter = change;
box.mouseleave = normal;

You must change
addEventListener("click", change, false);
addEventListener("mouseleave", normal, false);
with this
box.addEventListener("click", change, false);
box.addEventListener("mouseout", normal, false);

you just use this
<div class="box" onmouseover="style.background='green'" onmouseout="style.background='red'">
</div>
its work

Related

Javascript: I added an event listener to all button in every class but some button won't work

I just started studying JS and I'm currently simulating something that will apply to my project
Basically, I'm trying to generate new Divs with Button on it in order to do something.
And I applied the for loop on the button from the guide here
Turns out it works! but there's a bug where some buttons wont work whenever I generate more divs+button and I don't know why?
const btnCreate = document.querySelector(".myButton");
const changeBtn = document.getElementsByClassName("changeBtnStyle");
const newNewDiv = document.getElementsByClassName("newCDiv");
const createFunc = function() {
const parentDiv = document.querySelector(".parentDiv");
const newDiv = document.createElement("div");
const newChangeBtn = document.createElement("button");
parentDiv.appendChild(newDiv);
newDiv.appendChild(newChangeBtn);
newDiv.classList.add("newCDiv");
newChangeBtn.classList.add("changeBtnStyle")
newChangeBtn.innerHTML = "change"
for (let i = 0; i < changeBtn.length; i++) {
changeBtn[i].addEventListener("click", function() {
newNewDiv[i].classList.toggle("changeColor");
}, false);
}
};
btnCreate.addEventListener("click", createFunc);
.parentDiv {
margin: auto;
width: 300px;
height: 300px;
background-color: gray;
position: relative;
}
.newCDiv {
background: green;
width: 50px;
height: 50px;
position: relative;
}
.changeBtnStyle {
position: absolute;
}
.changeColor {
background: red;
}
.myButton {
margin: auto;
}
<button class="myButton">
Create Div w/ Button
</button>
<div class="parentDiv">
</div>
Here's the JSFiddle one
Every time you click on a generated button the for loop will add an event listener for each button. Even the ones that already have an event listener attached to them. So by doing that and then toggling the class, you call the classList.toggle() function more than once.
For example with 1 event listener, the toggle works fine. But with 2 event listeners you toggle and toggle again, resulting in an immediate on / off switch. 3 event listeners will toggle 3 times, on / off / on, having the right resulting but not working correctly.
So instead of looping each button again, just add the event listener only to the element that you've created in the createFunc function.
const btnCreate = document.querySelector(".myButton");
const changeBtn = document.getElementsByClassName("changeBtnStyle");
const newNewDiv = document.getElementsByClassName("newCDiv");
const createFunc = function() {
const parentDiv = document.querySelector(".parentDiv");
const newDiv = document.createElement("div");
const newChangeBtn = document.createElement("button");
parentDiv.appendChild(newDiv);
newDiv.appendChild(newChangeBtn);
newDiv.classList.add("newCDiv");
newChangeBtn.classList.add("changeBtnStyle")
newChangeBtn.innerHTML = "change"
newChangeBtn.addEventListener("click", function() {
newDiv.classList.toggle("changeColor");
}, false);
};
btnCreate.addEventListener("click", createFunc);
.parentDiv {
margin: auto;
width: 300px;
height: 300px;
background-color: gray;
position: relative;
}
.newCDiv {
background: green;
width: 50px;
height: 50px;
position: relative;
}
.changeBtnStyle {
position: absolute;
}
.changeColor {
background: red;
}
.myButton {
margin: auto;
}
<button class="myButton">Create Div w/ Button</button>
<div class="parentDiv"></div>

CSS transition with pure JS without delay

What I want to achieve is to change some property (background-color in the code above) twice from js so that transition would run between them but not from the previous state to the first one. The code above almost never works because timeout is set to zero, it works almost always when it is set at least to 10 and it works always on my machine when I set it to 100. What I also want is to avoid timeouts completely and ether run the code linearly or based on the appropriate event callback (I didn't find any useful so far).
Here is an example (also on jsFiddle):
var outter = document.getElementById('outter');
var test = document.getElementById('test');
test.onclick = function() {
outter.removeChild(test);
test.style.backgroundColor = 'green'
outter.appendChild(test);
setTimeout(function() {
test.style.backgroundColor = 'red'
}, 0);
}
#test {
position: fixed;
left: 2em;
right: 2em;
top: 2em;
bottom: 2em;
background-color:red;
transition-duration: 2s
}
<div id=outter>
<div id=test></div>
</div>
Without timeouts:
var outter = document.getElementById('outter');
var test = document.getElementById('test');
test.onmousedown= function() {
test.style.transitionDuration = "0s";
test.style.backgroundColor = 'green';
};
test.onmouseup= function() {
test.style.transitionDuration = "2s";
test.style.backgroundColor = 'red';
};
#test {
position: fixed;
left: 2em;
right: 2em;
top: 2em;
bottom: 2em;
background-color:red;
}
<div id=outter>
<div id=test></div>
</div>
I managed to do it using a very short transition when going green and using transitionend handlers (which, sadly, still require vendor prefixes — yeesh).
The following works for me with Firefox, Chrome, and IE11. (I should note that you don't have to use classes, I just prefer to keep styling in the CSS; you could use outter.style.transitionDuration = "2s"; and such.)
var outter = document.getElementById('outter');
var test = document.getElementById('test');
function onTransition(element, handler, add) {
var method = (add ? "add" : "remove") + "EventListener";
element[method]("transitionend", handler, false);
element[method]("mozTransitionEnd", handler, false);
element[method]("webkitTransitionEnd", handler, false);
}
test.onclick = function() {
// If we're running...
if (outter.classList.contains("green")) {
// ...reset
onTransition(outter, greenToRed, false);
onTransition(outter, redDone, false);
outter.classList.remove("green", "red");
}
onTransition(outter, greenToRed, true);
outter.classList.add("green");
};
function greenToRed() {
onTransition(outter, greenToRed, false);
onTransition(outter, redDone, true);
outter.classList.add("red");
}
function redDone() {
onTransition(outter, redDone, false);
outter.classList.remove("green", "red");
}
#test {
position: fixed;
left: 2em;
right: 2em;
top: 2em;
bottom: 2em;
background-color: red;
}
.green #test {
background-color: green;
transition-duration: 0.0001s;
}
.red #test {
transition-duration: 2s;
background-color: red;
}
<div id=outter>
<div id=test></div>
</div>
The above is just proof-of-concept, of course; it can be refined and cleaned up a fair bit.

File input triggers change event twice (or more)

I have a basic input[file] element which I hide. When you click on the #holder a file explorer pops up. But selecting a file triggers the console.log() line to be executed twice (on my computer).
Beware: the following code below crashes my Chrome tab.
You should better run it as a separate file. Cannot provide a "working" demo, but this is the closest I can get to MCVE.
var element = document.getElementById('holder');
element.onclick = function(e) {
var input = document.getElementById('file-input');
input.click();
input.addEventListener("change", function(evt) {
console.log(evt);
Phimij.addFiles(input.files);
}, false);
};
#holder {
border: 10px dashed #ccc;
width: 300px;
height: 300px;
margin: 20px auto;
}
#holder.hover {
border: 10px dashed #333;
}
#file-input {
display: none;
}
<div id="holder">
<input type="file" multiple id="file-input" />
</div>
click events bubble up the ancestry tree. That means a click on your input will bubble up to your #holder element and fire your click handler on it. In your click handler on #holder, you fire the click event on the input. That's why your browser crashes: You've triggered an infinite loop.
The solution is to hook click on the input and tell it not to bubble (propagate); see flagged lines (but keep reading, further notes below):
var element = document.getElementById('holder');
// **** Added vvvv
document.getElementById('file-input').addEventListener("click", function(evt) {
evt.stopPropagation();
}, false);
// *** Added ^^^^
element.onclick = function(e) {
var input = document.getElementById('file-input');
input.click();
input.addEventListener("change", function(evt) {
console.log(evt);
// Phimij.addFiles(input.files);
}, false);
};
#holder {
border: 10px dashed #ccc;
width: 300px;
height: 300px;
margin: 20px auto;
}
#holder.hover {
border: 10px dashed #333;
}
#file-input {
display: none;
}
<div id="holder">
<input type="file" multiple id="file-input" />
</div>
There are a few other things I'd change. You're adding a change handler to the input every time there's a click on #holder; you really only want to do that once. I'd also add that handler before triggering the click.
So for what it's worth, some changes I'd make:
var element = document.getElementById('holder');
var input = document.getElementById('file-input');
element.addEventListener("click", function() {
input.click();
}, false);
input.addEventListener("click", function(evt) {
evt.stopPropagation();
}, false);
input.addEventListener("change", function(evt) {
console.log(evt);
// Phimij.addFiles(input.files);
}, false);
#holder {
border: 10px dashed #ccc;
width: 300px;
height: 300px;
margin: 20px auto;
}
#holder.hover {
border: 10px dashed #333;
}
#file-input {
display: none;
}
<div id="holder">
<input type="file" multiple id="file-input" />
</div>

Override return value in event handler?

I'm sure this has been asked before, but I haven't had any luck finding an answer. There's probably a term for this which I don't know.
Can a jQuery event handler return an element other than the one from which it was triggered?
Normally, when you trigger a jQuery event for an element, that element will be returned by the event handler. Is there a way to return a different element instead? (other than event.target, event.currentTarget, etc.)
Here's my HTML:
<div id="content">
<div id="wrapper">
<div class="instance">
</div>
</div>
</div>
If I make a custom jQuery event for #wrapper, can I make its event handler return an .instance?
Here's my JavaScript:
$('#content').on('new.instance', '#wrapper', function(event) {
var wrapper = $(event.currentTarget);
var instance = wrapper.find('div.instance').first();
var newInstance = instance.clone(true, true);
newInstance.appendTo(wrapper);
return newInstance;
});
var returnValue = $('#wrapper').trigger('new.instance');
console.log('returnValue.html():', returnValue.html()); // #wrapper, not .instance
Can I make the new.instance event handler return an .instance element? If so, what am I missing in the code?
.trigger()
...
When we define a custom event type using the .on() method, the second argument to .trigger() can become useful.
You could simply add an object to the .trigger method as a second parameter and collect your instances in there.
var instances = {data:[]};
$('#content').on('new.instance', '#wrapper', function(event, instances) {
var wrapper = $(event.currentTarget);
var instance = wrapper.find('div.instance').first();
var newInstance = instance.clone(true, true);
instances.data.push(newInstance);
newInstance.appendTo(wrapper);
});
$('#wrapper').trigger('new.instance', instances);
console.log(instances.data[0].get(0));
// somewhere else at a latter time trigger new.instance again
setTimeout(function() {
$('#wrapper').trigger('new.instance', instances);
$.each(instances.data, function(index, item) {
var counter = index + 1
item.text( 'cloned instance ' + counter );
console.log(item.get(0))
})
}, 2000)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="content">
<div id="wrapper">
<div class="instance"></div>
</div>
</div>
.instance is in the event.chain so you can access it on callback during the bubbling phase. Review the Snippet by clicking each element.
Snippet
var wrp = document.getElementById('wrapper');
wrp.addEventListener('click', function(e) {
if (e.target != e.currentTarget) {
var trueTarget = e.target.className;
alert(trueTarget + ' has been clicked!');
}
e.stopPropagation();
}, false);
#content {
border: 2px dashed grey;
width: 50vw;
height: 50vh;
background: rgba(0, 0, 0, .3);
text-align: right;
color: white;
}
#wrapper {
border: 3px dotted orange;
background: rgba(0, 0, 0, .5);
width: 50%;
height: 50%;
text-align: right;
font-size: small;
color: orange;
}
.instance {
border: 1px solid yellow;
width: 50%;
height: 50%;
background: rgba(0, 0, 0, .7);
text-align: center;
font-size: smaller;
color: yellow;
}
<div id="content">
CONTENT
<div id="wrapper">
WRAPPER
<div class="instance">
INSTANCE
</div>
</div>
</div>

change size of div function doesn't work

I have a function that alters the size of a div when I click on it. Now I have to write the onclick command in my html page, but I want it to stand in the extern .js file.
Now in html:
<div id="box1" class="kaesten" onclick="changeSize('box1')"> Title 1 </div>
What I want:
<div id="box1" class="kaesten" > Title 1 </div>
Tried something in jquery but it didn't work:
function changeSize(id) {
var elem = document.getElementById(id);
var currentAbsoluteElem = document.getElementById('dummy');
var text = elem.innerHTML;
currentAbsoluteElem.innerHTML = text;
currentAbsoluteElem.setAttribute('style', 'display:block');
/*Extra styling neeed to be done here*/
}
var elems = document.getElementsByClassName('kaesten');
for (var i = 0; i < elems.length; i++) {
elems[i].onclick = function() {
changeSize(this.id);
}
}
var absoluteCl = document.getElementsByClassName('absoluteclass');
absoluteCl[0].onclick = function() {
console.log(document.getElementsByClassName('absoluteclass'))
document.getElementsByClassName('absoluteclass')[0].setAttribute('style', 'display:none');
}
$(document).ready(function() {
$('.kaesten').click(function() {
changeSize($(this).attr('id'));
});
});
.kaesten {
width: 240px;
height: 300px;
background-color: darkgrey;
background-position: center;
background-repeat: no-repeat;
text-shadow: 0px 0px 3px #000;
border: 5px solid #F0F8ff;
vertical-align: top;
text-shadow: 3px 3px 4px #777;
float: left;
margin-left: 30px;
}
.absoluteclass {
position: absolute;
background-color: darkgrey;
width: 600px;
height: 600px;
left: calc(30%);
display: none;
}
<div id="box1" class="kaesten">title1</div>
<div id="box2" class="kaesten">title2</div>
<div id="box3" class="kaesten">title3</div>
<div id="box4" class="kaesten">title4</div>
<div id="dummy" class="absoluteclass"></div>
I know it works in the fiddle, but I don't know why it doesn't work on my homepage without writing the function in the div's.
I guess the problem is that you are trying to assign the onclick event handler before the DOM is actually rendered and ready. My suggestion is to wrap your "initialization code" inside a $(document).ready() method. As follows:
$(document).ready(function() {
// Apply the on click event handlers here, using jQuery or not
// For instance:
$('.kaesten').click(function() {
changeSize($(this).attr('id'));
});
});
if you want to pass the id from jquery to your function you should do it like this:
$(function(){
$(".kaesten").click(function(){
changeSize($(this).attr("id"));
});
});
you can use .css in jquery
$(function(){
$(".kaesten").click(function(){
$(this).css({'width' : '600px' , 'height' : '600px'});;
});
});

Categories

Resources