I want to build a JS library, so I am not using any jQuery. This is Pure JavaScript.
I created a div after mouse entered the specific element then display some info inside the div just created and after mouse leave, the info will disappear.
The mouse enter part worked fine, it showed with correct text and css style, but when moving mouse out, it only run the function first time. the created div will stay there ignoring the mouseleave function after first try.
Here is the JS code
document.getElementById(id).addEventListener("mouseenter", function(){
var elemDiv = document.createElement('div');
elemDiv.id ="demo";
document.body.appendChild(elemDiv);
elemDiv.innerHTML = "something";
}, false);
document.getElementById(id).addEventListener("mouseleave", function(){
document.getElementById("demo").innerHTML="";
}, false);
I have tried the other method before, it gives same result
document.getElementById(id).onmouseenter = function(){...}
document.getElementById(id).onmouseleave = function(){...}
On every "mouseenter" you create a new element but you never delete it. On "mouseleave" you only delete the content of the first one, the second (third, ...) is still there and keeps its content.
You should probably create the element outside the event handlers and only change "innerHTML". Or you remove it on "mouseLeave" from the DOM.
You are creating multiple elements with the same ID and then querying with document.getElementById. This has unpredictable browser results (typically the first is returned) - you need to ensure that for each ID in your DOM, only one ID is present.
With that in mind, your mouseenter function is actually broken as it is creating extra copies of the same div when it needs to determine if one already exists.
document.getElementById(id).addEventListener("mouseenter", function(){
// Find the 'demo' div
var elemDiv = document.getElementById('demo');
// If it doesn't exist, create a div, give it the unique ID 'demo' and add it to the DOM'
if (!elemDiv) {
elemDiv = document.createElement('div');
elemDiv.id = 'demo';
document.body.appendChild(elemDiv);
}
// Whether it was already on the DOM or had to be created, the text is reset.
elemDiv.innerHTML = "something";
}, false);
See my JSFiddle for a complete example: http://jsfiddle.net/ckned3mx/6/
On every mouseenter event you are making a new element with the same id="demo" which is invalid HTML (ID should be unique).
Then on mouseleave the .getElementById() function will return the first element found with that ID, which is the one created by the first mouseenter.
This means you end up with multiple demo elements that don't get cleaned up.
You should either re-use the same element (don't create it if it already exists) or remove the element on mouseleave.
here is a Demo:
http://jsfiddle.net/hxzgpdoz/
i made some changes in your mouseenter event function:
var elemDiv = document.getElementById("demo");
if( elemDiv ){
elemDiv.innerHTML = "something";
}else{
elemDiv = document.createElement('div');
elemDiv.id ="demo";
document.body.appendChild(elemDiv);
elemDiv.innerHTML = "something";
}
Related
I am trying to target a class called 'horizontal-video' in a div within an AEM component and if the author has clicked a checkbox that has an ID of 'coral-id-540' I want to add a second class called 'flipped' to the div. Here is the code I wrote that isn't working. Could someone help me figure out why it's not working? The console does not show errors.
var x = document.getElementsByClassName("horizontal-video");
$('#coral-id-540').change(function(){
if($(this).is(":checked")) {
$(this).addClass("flipped");
} else {
$(this).removeClass("flipped");
}
});
It's quite possible you're not waiting for the DOM to completely load, (or at least have this bit of code below the element in question on the page during page load)
Is your code wrapped in $(document).ready(function(){ //your code });?
Also, be aware that any element that is dynamically added to the page by JavaScript/jQuery after page load will not have a listener attached using the method you're using.
To allow dynamically added elements to be included in your listener, you should target an ancestor node and add the listener to that node. In plain English: attach the listener to a "higher up" element. The safest (although slowest) node being document itself, but it's better to target something closer:
$(document).ready(function () {
var $horizontalVideo = $(".horizontal-video"); //You're using jQuery - why not use it here? Also, I always name jQuery objects with a `$` in front as a shorthand to know it's wrapped in a jQuery object. Plus, a more descriptive name will help you immensely.
//replace parent-of-coral with the ID of a parent element that you know exists on DOM ready:
$("#parent-of-coral").on("change", "#coral-id-540", function (e) { //get used to using "e" as the event variable for preventing default / stopping propagation / etc
$this = $(this); //cache $(this) reference rather than creating another jQuery object each time you use it
if ($this.is(":checked")) {
$this.addClass("flipped");
} else {
$this.removeClass("flipped");
}
});
});
I've started to do a visualization using svg. it's a simple column chart thing and working fine that far. I'm loading the data from an external XML file and display a column chart.
Now I want to add a hover-effect, that will change the color of the bar when hovering a column.
So the question is how do I add an eventhandler to a previously generated svg element.
I tried different ways:
(1) When generating the element trying to add the eventhandler already:
newElement.onmouseclick="highlightOn(this)";
(2) adding the event handler this supposedly more advanced way I don't know how to select the right element that fired the event inside the SVG.
newElement.addEventListener("mouseover", highlightOn, false)
(3) some forum showed this as a possibility (doesn't work either: contentDocument returns null)
theSVG.addEventListener("click", function(){
console.log("svg hovered");
var svgDoc = theSVG.contentDocument; //get the inner DOM of alpha.svg
console.log(svgDoc);
var allColums= svgDoc.getElementsByTagName("rect");
for (var i = 0; i < allColums.length; i++) {
allColums[i].addEventListener("click", function(){
console.log("clicked!"); })
};
});
so all in all, I'm quite confused and have no idea how to proceed.
Here is how I'm generating the svg:
for (var i = 0; i < allLogs.length; i++) {
//reading data
date =allLogs[i].getElementsByTagName("date")[0].firstChild.data;
console.log("date "+date);
time5000m =allLogs[i].getElementsByTagName("TimeFivethousandMeter")[0].firstChild.data;
if (time5000m==" ") {time5000m=0;};
console.log("time 5000m"+time5000m);
//adding data to SVG
//>> colum
var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'rect'); //Create a rect in SVG's namespace
newElement.setAttribute("width",width);
newElement.setAttribute("height",time5000m*scaleFactor);
var xPos=width*i+i*offset+sideMargins/2;
newElement.setAttribute("x",xPos);
var yPos=height-time5000m*scaleFactor-verticalMargin/2;
newElement.setAttribute("y", yPos);
newElement.style.fill = "#cf004e"; //Set fill colour
newElement.style.opacity="0.75";
theSVG.appendChild(newElement);
};
How to deal with this?
Looking at your first attempt:
newElement.onmouseclick="highlightOn(this)";
You have one mistake: onmouseclick should just be onclick
I've had trouble using this in mouse events, so the best method I've used is to set an ID for the element in question, then use a helper function to assign to the onlick, so add something like this to your element creation loop:
var id = 'el'+i;
newElement.id = id;
newElement.onclick = funcHighlightOn(id);
Then, use a function like this that you can use to assign the onclick action:
function funcHighlightOn(id) {
return function() {
highlightOn(id);
}
}
The reason for the weirdness of the above is that it's difficult to pass parameters (in this case, the element's ID) into the mouse events when assigned this way.
There are a few things odd here. First, why in (3) are you trying to add click handlers inside a click handler? It may be that every click is being intercepted by the SVG click handler, and all you are ever doing is replacing the rect click handlers.
Why don't you just add the click handler when you create each <rect> in the first place? Add your handler to newElement when you append it.
I'm building a lightbox as a school project, and I can't use jQuery. I've got an image. When you click it, Javascript makes a transparent div with the ID "overlay". I want the div to remove itself, or the parent to remove it but it doesn't work. I think it has to do with the fact that you can't link 'onclick' to an element that doesn't exists yet.
You have to remove the element from the parent. Something like this:
d = document.getElementById('overlay');
d.parentNode.removeChild(d);
Or you could just hide it:
d.style.display = 'none';
And, oh: you can add Javascript code to a (newly created) element by assigning a function to the onclick attribute.
d = document.createElement('div');
d.onclick = function(e) { this.parentNode.removeChild(this) };
You can remove the element like the following
var el = document.getElementById('div-02');
el.remove(); // Removes the div with the 'div-02' id
Click here for more details
Don't use the onclick handler in the tag, use Javascripts event functions such as addEventListener to dynamically add the event to the elements. You should also make sure that when you remove the elements you properly clean up all your references (in other words, unregister the event handlers).
I've got it :)
I was doing it like bart sad, but it didn't work. my code looked something like this:
image.onclick = function(){ *create overlay*};
overlay.oncklick = function() {*overlay.parentNode.removeChild(overlay)*};
the browser goes like wtf? cause it reads the code and thinks "i cant check if the user clicked a non-existing element."
So I did this:
image.onclick = function(){
*create overlay*
overlay.onclick = function() {*remove overlay*};
};
I've been struggling with what seems to be a simple problem for a few hours now. I've written a REGEX expression that works however I was hoping for a more elegant approach for dealing with the HTML. The string would be passed in to the function, rather than dealing with the content directly in the page. After looking at many examples I feel like I must be doing something wrong. I'm attempting to take a string and clean it of client Events before saving it to our Database, I thought jQuery would be perfect for this.
I Want:
Some random text click here and a link with any event type
//to become:
Some random text click here and a link with any event type
Here's my code
function RemoveEvilScripts(){
var myDiv = $('<div>').html('testing this Do it! out');
//remove all the different types of events
$(myDiv).find('a').unbind();
return $(myDiv).html();
}
My results are, the onClick remains in the anchor tag.
Here's a pure Javascript solution that removes any attribute from any DOM element (and its children) that starts with "on":
function cleanHandlers(el) {
// only do DOM elements
if (!('tagName' in el)) return;
// attributes is a live node map, so don't increment
// the counter when removing the current node
var a = el.attributes;
for (var i = 0; i < a.length; ) {
if (a[i].name.match(/^on/i)) {
el.removeAttribute(a[i].name);
} else {
++i;
}
}
// recursively test the children
var child = el.firstChild;
while (child) {
cleanHandlers(child);
child = child.nextSibling;
}
}
cleanHandlers(document.body);
working demo at http://jsfiddle.net/alnitak/dqV5k/
unbind() doesn't work because you are using inline onclick event handler. If you were binding your click event using jquery/javascript the you can unbind the event using unbind(). To remove any inline events you can just use removeAttr('onclick')
$('a').click(function(){ //<-- bound using script
alert('clicked');
$('a').unbind(); //<-- will unbind all events that aren't inline on all anchors once one link is clicked
});
http://jsfiddle.net/LZgjF/1/
I ended up with this solution, which removes all events on any item.
function RemoveEvilScripts(){
var myDiv = $('<div>').html('testing this Do it! out');
//remove all the different types of events
$(myDiv)
.find('*')
.removeAttr('onload')
.removeAttr('onunload')
.removeAttr('onblur')
.removeAttr('onchange')
.removeAttr('onfocus')
.removeAttr('onreset')
.removeAttr('onselect')
.removeAttr('onsubmit')
.removeAttr('onabort')
.removeAttr('onkeydown')
.removeAttr('onkeypress')
.removeAttr('onkeyup')
.removeAttr('onclick')
.removeAttr('ondblclick')
.removeAttr('onmousedown')
.removeAttr('onmousemove')
.removeAttr('onmouseout')
.removeAttr('onmouseover')
.removeAttr('onmouseup');
return $(myDiv).html();
}
Why is this "copy"(click) wrong, it binds all the previous handlers as well:
var add = function(element) {
var ele = element.clone(true);
$('.container').append(ele);
$('.copy', new).click(function(){ add(ele); });
}
Idea: I want to have an element text next to a "copy" button.
When I click "copy", it clones the current row and append it to the container.
But this seems to be recursive...
The true parameter says:
Normally, any event handlers bound to the original element are not copied to the clone. The optional withDataAndEvents parameter allows us to change this behavior, and to instead make copies of all of the event handlers as well, bound to the new copy of the element.
So you keep adding click event handlers to the .clone element. Depending on your actual case, just don't bind the event handler again:
var add = function(element) {
var cloned = element.clone(true);
$('.container').append(cloned);
}
$('.container .copy').click(function(){
add($(this).closest('tr'));
});
(I used $(this).closest('tr') to get the parent row. Obviously you have to adjust it to your needs.)
Update:
Or don't pass true:
var add = function(element) {
var cloned = element.clone();
$('.container').append(cloned);
$('.copy', cloned).click(function(){ add(cloned); });
}
new is JS keyword. Change it to something else and it should work.
( Your code does not have call of add() except of from itself. So it is not clear how code gets there initially. And recursive declaration of functions as in your code is a path to programmers hell )