No hover event after I used .empty() and .html() - javascript

I have a sortable list (jQuery UI) that I want to sort programmatically using the ids of the
"li" elements. (they are all numbers).
To do that, I have made this function:
function resetList()
{
var orderedItems = new Array();
var unorderedItems = $("#sortable").find('li');
for(var i = 0; i < unorderdItems.length; i++)
{
var counter = 0;
var check = false;
do {
if(unorderedItems[counter].id == (i+1))
{
check = true;
orderedItems.push(unorderedItems[counter]);
}
counter++;
} while (!check && counter < unorderedItems.length);
}
$("#sortable").empty().html(orderedItems);
}
I think that works quite well (i am new to javascript, so i don't know if that code is "professional")
The problem is that after I've called the function no jQuery hover or mouseover events are firing anymore (have been working before)
The content of my "li" elements:
<li class="ui-state-default">
<div class="image" style=\"height:100%; width:100%;">
<img class="overlay" src="img/pic.png" height="200" width="200" style="height:200px; width:200px; visibility:hidden;" />
</div>;
</li>
The JavaScript:
$(".image").hover(function(e)
{
//make overlay visible
}, function(e)
{
//hide overlay
});
Any ideas why the hover function does not work after I called resetList()?
Sorry about the bad english and thank you for any help!
-Nick

if you are using jquery 1.7 or higher use .on else use .delegate
$(".image").on("mouseover mouseout",function(evt){
if (evt.type == 'mouseover') {
// do something on mouseover
alert("over");
} else {
// do something on mouseout
alert("out");
}
});
earlier version of jquery
$("body").delegate(".image","hover",function(evt){
if (evt.type == 'mouseenter') {
// do something on mouseover
alert("over");
}else {
// do something on mouseout
alert("out");
}
});
you are right,changed to delegate
Dafen, hover wont work elements that are dynamically created from javascript, hence using .on or delegate, anyways you have found your answer, just correcting my answer so that no one does same mistake i have done.

I'm pretty sure that after you sort your elements, new dom elements get added to your page, replacing the old ones. As a result your event handlers get lost. You should be able to fix it quite easily by using delegated events with on
$(".ui-state-default").on("mouseenter", ".image", function() { .....
$(".ui-state-default").on("mouseleave", ".image", function() { .....

Just to be difficult, integers aren't valid HTML IDs (IDs should start with a letter [A-Za-z])

Related

Event listeners not working [duplicate]

the solution to this problem is probably pretty simple, but I need some help.
var x;
for(x in document.getElementsByTagName("img"))
x.addEventListener('click',openPage, false);
function openPage() {
alert("clicked");
}
I'm not getting an alert when I click on an <img src="something" /> tag. Anyone know why? Also, is my loop necessary?
This code produces an error - in a for..in statement, 'x' is the key of your object (in this case, your document.getElementsByTagName call). What you want is:
var x,
imgs = document.getElementsByTagName("img");
for(x in imgs) {
if (imgs[x] instanceof Element) {
imgs[x].addEventListener('click',openPage, false);
}
}
function openPage() {
alert("clicked");
}
Might I suggest using a Javascript framework (like jQuery), which can help simplify your code as such:
$('img').each(function() {
$(this).click(function() {
alert('Clicked!');
// Now that we're in the callback context, $(this) will be the current
// target - the specific image that was clicked.
// i.e. $(this).fadeOut() would slowly fade out the clicked image.
});
});

How to add an active class on specific “li” on user click

I've scoured the web for a straightforward answer and I have not been able to find it. Spent too long trying to figure this out, but I'd appreciate any help or the right direction.
HTML
<ul id="main-li">
<li>item1</li>
<li>item1</li>
<li>item1</li>
</ul>
JavaScript:
document.getElementById('main-li').addEventListener("click", function(e) {
if (e.target && e.target.nodeName === "LI") {
e.target.classList.add("active-class");
}
});
JSFiddle
https://jsfiddle.net/kw0rr3fv/1/
According to David Wash: https://davidwalsh.name/event-delegate
Event delegation allows you to avoid adding event listeners to
specific nodes; instead, the event listener is added to one parent.
That event listener analyzes bubbled events to find a match on child
elements
What is the best way to remove the previous active-class while attaching the class to the selected element?
The only way that exists to remove a class to each child of the UL, is to iterate over them.
If you wish to avoid frameworks like jQuery, you can simply achieve it with a very short code:
document.getElementById('main-li').addEventListener("click", function(e) {
if (e.target && e.target.nodeName === "LI") {
let elements = document.getElementById('main-li').children;
for (let i = 0; i < elements.length; ++i) {
elements[i].classList.remove("active-class");
}
e.target.classList.add("active-class");
}
}, true);
As you see I just added a very short loop to your code that removes the class (it won't block in case the element doesn't have the class).
In the last line of code you may notice I have added a true value: this is the use capture and is used to suggest that UL event must be captured by LI childrens.
I found this to be more challenging than I expected. Is this a common
way to set an active class?
You can use a framework like jQuery which will help you do it faster and in cross-browser fashion.
What is the best way to remove the previous active-class while
attaching it to the selected element?
Check the updated fiddle
document.getElementById('main-li').addEventListener("click", function(e) {
console.log(e);
Array.prototype.slice.call(document.querySelectorAll('#main-li li')).forEach( function( obj ){
obj.classList.remove("active-class");
});
if (e.target && e.target.nodeName === "LI") {
e.target.classList.add("active-class");
}
});
You need to remove the class from all li's first and then go ahead with adding the active-class
I think should be focus only tag "li" and add event listener as my simple code and easy to read below.
var elementsLi = document.querySelectorAll('ul#main-li > li');
for (var i = 0; i < elementsLi.length; i++) {
elementsLi[i].addEventListener('click', function(e) {
// console.log(e.currentTarget); // for see the current element
if (e.currentTarget.classList.contains('active-class')) {
// do something if already have class "active-class"
// remove class or blah blah blah
}
else {
e.currentTarget.classList.add('active-class')
}
});
}
Hope your success :)
Created page which add class "active" on every "li" element click.
<style>
.active { color: red; }
</style>
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
<script>
var arr = document.getElementsByTagName("li");
for(var i=0; i<arr.length; i++){
arr[i].addEventListener("click", function(){
for(var j=0; j<document.getElementsByTagName("li").length; j++){
document.getElementsByTagName("li")[j].className = "";
event.target.className = "";
};
event.target.className = "active"
});
}
</script>
You can also use Jquery for this. which is fast and shorter than your code.
$(document).ready(function(){
$('#main-li').on('click',function(){
$(this).addClass('active-class').siblings().removeClass('active-class');
});
});

disable onclick event on div when clicking on inside <a> link (No js framework)

I have this piece of code:
<div id="mydiv" onclick="ajax_call()">
Mylink
</div>
I'd like ajax_call() to be called only when clicking on empty space inside div but not on "Mylink". Is it possible without any external javascript framework?
Moreover I have this piece of css:
div#mydiv:hover{
background-color: blue;
}
Is it possible to disable the :hover stylesheet when the cursor is placed over "Mylink" (in order to suggest that clicking on "Mylink" won't trigger ajax_call() but will take to myurl)?
Attach the function at child element with click event, After clicked on child element it's handler stops the immediate propagation, As a result ajax_call() will not be invoked.
HTML
<div id="mydiv" onclick="ajax_call()">
Mylink
</div>
javaScript
function ajax_call(){
alert("empt space");
}
//this function stops the propagation and not triggered above
//function when clicked on child element.
function notCall(event) {
event.stopImmediatePropagation();
return false;
}
DEMO
I'm not sure what you want but if I keep my imagination may be that this work, lucky !
$("div#mydiv a").hover(function(){
$(this).parent().css("background-color","transparent")
})
Sure, what you need is the event target || scrElement
Like
function ajax_call() {
var target = event.target ? event.target : event.srcElement;
if(target.id==="mydiv") { alert("good to go"); }
}
See : http://jsbin.com/qujuxufo/1/edit
Edit/Update ( missed the second part ) - Started to answer this before the q was closed - but might as well as it now ..
For the second part of the question - it is not possible to set parent elements in CSS ( it flows top to bottom ) - for that some more JS is needed.
See http://jsbin.com/cileqipi/1/edit
CSS
#mydiv:hover { background-color:green; color:#fff}
#mydiv.anchorhover, #mydiv.anchorhover:hover { background-color:white;}
Then JS
var _mydiv = document.getElementById("mydiv");
var _mydiv_anchors = _mydiv.getElementsByTagName("a");
function toggleClass() {
var addClass=true, cls="anchorhover";
if((_mydiv.className).indexOf(cls) >= 0){ addClass=false; }
if(addClass) {
_mydiv.className=_mydiv.className+=' '+cls;
} else {
/* remove */
_mydiv.className=_mydiv.className.replace(new RegExp('(\\s|^)'+cls+'(\\s|$)'),' ').replace(/^\s+|\s+$/g, '');
}
}
for(var i=0, len=_mydiv_anchors.length; i<len; ++i) {
_mydiv_anchors[i].onmouseover = toggleClass;
_mydiv_anchors[i].onmouseout = toggleClass;
}
^ That feels like quite a trip compared to how simple jquery abstracts it .. >
$("#mydiv a").hover(function() {
$(this).parent().addClass("anchorhover");
}, function() {
$(this).parent().removeClass("anchorhover");
});
Either way, the principle is : to add a style class to the parent element on mouseover and remove it on mouseout

optimization jQuery for IE

I have function:
function doBlamingItem($cell, showEditMark) {
$cell.hover(function () {
$cell.toggleClass('clickable-cell', showEditMark).toggleClass('editing-cell', !showEditMark);
}, function() {
$cell.removeClass('clickable-cell editing-cell');
} );};
in $(document).ready() I apply this function for some cells in my table (~500) and when I move my mouse upon it - in FF or Chrome all is okay, but IE7-9 starts lagging and I don't know how to fix it :(
and code from $(document).ready():
var i = firstRowOnPage();
while (table.GetRow(i) != null) {
if (condition) {
var row = table.GetRow(i);
var elementInCellId = column.fieldName + '_' + rowKey;
var $cell = $(row.cells[realIndex]).attr('id',elementInCellId);
doBlamingItem($cell, true);
setClickable(editInfo, $cell);
}
i++;
}
I use doBlamingItem for every cell because for some of them showEditMark=true, for other showEditMark=false
Your code basically (1) finds those ~500 elements, (2) iterates them to (3) assign hover events (consisting of mouseenter and mouseleave). Have you heard of delegated events?
The setup time is virtually none (only 2 event handlers, instead of 1000 are registered). No elements are selected and traversed.
(function($, undefined){
// if you want it global
var showEditMark = true;
// otherwise save that state to some element's data()
$(function(){
$(document.body).delegate('.your-table-selector td', {
mousenter: function(e){
$(this)
.toggleClass('clickable-cell', showEditMark)
.toggleClass('editing-cell', !showEditMark);
},
mouseleave: function(e){
$(this).removeClass('clickable-cell editing-cell');
}
});
});
})(jQuery);
Thanks to all who answered my question, but as I realized problem was not in javascript... My page has big DOM-tree of elements and many CSS-styles, so IE has problems with rendering of it

Can't select added tr by jQuery

I add table and it's raws by jQuery when find result in database,and remove table when don't find anything.It works correctly.
$("#AdminSearch").bind("change keyup", function() {
var url = "http://localhost/PmMusic/index.php/admin/ajax/admin_search/"+$("#AdminSearch").val();
$.getJSON(url,function(data){
if (data.length == 0)
{
$("#AutoSearch").hide(1000);
$("#AutoSearchTable").remove();
}
else
{
$("#AutoSearchTable").remove();
$("#AutoSearch").append('<table id="AutoSearchTable">');
for(var i = 0;i < data.length && i < 5;i++)
{
$("#AutoSearchTable").append('<tr><td id="TableSearchTR'+i+'" value="'+data[i]+'">'+data[i]+'</td></tr>');
}
$("#AutoSearch").append('</table>');
$("#AutoSearch").show(1000);
}
});
});
but when I wanna select tr by following code
$('tr').click(function(){
alert("Hi");
});
When I click on other table tr in page it works,but it can't select tr which added by upper code).
where is the problem?
You need to use .live() or .delegate() to attach click events to dynamically-created elements.
$("#AdminSearch").delegate("tr","click",function() {
alert("Hi");
});
That's because you're binding with .click, which only applies to elements already in the page.
Change your code to
$('tr').live('click', function(){
alert("Hi");
});
If the TR is not there when your .click() function is added, then it won't have a click event attached. You should look at using the .delegate() function instead.
click() will only work for elements already in the DOM. If you're loading in some content w/ ajax then I would suggest live().
$('tr').live('click', function() {
alert("Hi");
});

Categories

Resources