I am implementing html5 drag and drop (for the first time). I have the following ng-repeat where the drop target is the outer div:
<div ng-repeat="chapter in chapters" class="chapter " ondrop="drop_handler(event);" ondragover="dragover_handler(event);">
<div><bold>{{chapter.title}}</bold></div>
<div>{{chapter.text}}</div>
</div>
However the dragover event is fired also for the inner elements (as event.target).
In my dragover_handler() I need to get hold of the outer div so that I can, for example, set a background-color. How can I achieve this?
I could do this by specifying a ondragover for each inner element and then selecting the outer div, but that is really ugly as it needs the ondragover attr for each inner element.
This can be achieved by using node.addEventListener('dragover', handler_func, true) instead of element attribute.
The 3rd function to addEventListener turns on event capturing and this allows events fired from child elements to be sent to specified handler_func.
Related
It seems that the mouseout callback from jQuery attached to the div tag containing several children elements will be called each time when user dragged a mouse away from any of these children elements. Am I right?
If so, how can I intercept the top-level tag mouse event only?
jQuery's mouseout bubbles, which means you can put an if statement to check and see if the target is the parent and put your code inside that.
https://jsfiddle.net/ck0kbowt/ for example :)
Let's say I have an element:
<section id="container">
<div id="curious">hey, there</div>
</section>
Then, after the DOM loads, I bind an event to the element, like so:
$('#curious').click(function (){
alert('Are you curious?');
});
Later on, the element gets deleted:
$('#container').html('');
What happens to the bound event? Is it deleted too? Does it linger around? Is it a good practice to clean it up?
According to the jQuery documentation for the .html() method, the event handlers are removed.
This is done to prevent memory leaks.
When .html() is used to set an element's content, any content that was in that element is completely replaced by the new content. Additionally, jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content.
Similarly, the same applies when using the .empty()/.remove() methods as well:
all bound events and jQuery data associated with the elements are removed.
If you want to retain the data and event listeners, use the .detach() method instead. The .detach() method is essentially the same as the .remove() method except for the fact that it keeps all jQuery data associated with the removed elements (which means that you can append the same element after detaching it, and the events would still be bound).
Here's a question about binding click events with jQuery that I'm trying to make sense of.
Say I have a block element I bind a click to, with a paragraph tag inside of it:
<div id="testClick" style="width:200px; height:100px'>
<p>test click</p>
</div>
and I bind a click to the div:
$('#testClick').bind('click', function(e){
//with parent div (via e.target), do something
});
Now, if I click on the text inside the p tag, e.target = the p element, and if I click on the div (around, not on the text) e.target = the div element. So e.target = the object clicked on - i.e. the event is also bound to any children of the element specified.
This is to be expected, but I need operate on the parent div. and using e.target is not a reliable way of getting a reference to the div, because depending where within the div the click occurs e.target returns a different element. If I use e.target.parent to get a reference to the div, this fails when the click occurs in the div around the text.
Is there no simple way to get e.target to always and only return the exact element to which the click was initially bound?
(For example, in actionScript there is a property "mouseChildren" that prevents events from firing on children of bound elements)
(Consider all above pseudo code)
this will reference the element to which the handler is bound.
$('#testClick').bind('click', function(e){
alert( this.id );
});
DEMO: http://jsfiddle.net/yX499/
What happens is that the event bubbles up from the most deeply element clicked all the way to the document root.
If it encounters an element along the way with a handler bound for the type of event that occurred, it invokes that handler.
e.target will always reference that deeply nested element, but this will reference the element to which the handler is bound, so if the event finds 2 elements with an appropriate handler bound on the way up to the root, e.target will not change in the 2 handlers, but this will be different based on the bound element.
Use this. jQuery calls your callback with this set for your convience:
$('#testClick').bind('click', function(e){
$(this).doStuff();
});
I want to attach a "mouseup" event on all nodes of a container, including text nodes using jQuery. How do I do that?
Update:
If I had some HTML fragment like this:
<p>Some text node <strong>strong text</strong> another text node.</p>
Currently, $("p *") will apply the event to the <p> and <strong> but not to the 2 textnodes within <p> separately. Modifying the source to add classes is not an option.
bobince is right that you cannot set event handlers on a Text node. It sounds like you want something like
<p><span>Some text node</span> <strong>strong text</strong><span> another text node.</span></p>
and the events would get attached to the span tags. However that wouldn't work if you can't change the source.
While Tatu's answer ought to work (except use .mouseup instead of .click), are you sure you actually need an event handler on every single node? If you bind using
$('#container').mouseup(function(event){//code})
the event bubbling model will call that same func anytime the mouseup event occurs on any element inside #container, and the DOM node that actually triggered the event will be contained in the event.target property. This is much more efficient in most cases.
You cannot set event handlers on a Text node. Text nodes do not implement the EventTarget interface like Element nodes, the Document node and the window object do.
You should never need to, either. Set one mouseup handler on the parent element and you will get mouseup events for all its child content. This is because the mouseup event ‘bubbles’ up through its ancestors.
$('#container *').mouseup(function() { ... });
That will bind the mouseup event handler to all nodes inside #container.
EDIT
Changed click -> mouseup to be clearer.
I think the easiest would be to add a class to all your nodes.
The jquery selector will be as simple as :
$('.yourClassName').dostuff()
So I have a parent that defines a onmouseup event that hide/display a table. The problem is that I want the ability to have nested expandable/collapsible tables but when I click one that is nested it will fire the event for the parent and collapse everything. I can do some niffy stuffy in javascript like assume that the nested event will fire first and then cancel the parent event but that seems kind of hacky. Is there a way to declare from a child element that no parent elements should fire for this event?
I don't think you can declare that kind of thing on an element
but you could, as you implied, try inside the handler of the child:
e.stopPropagation()
where e is the event ? or return false; should have the same effect, but I seem to remember having an issue (perhaps IE where it didn't work, but that could just be another factor I was missing)
Could you possibly iterate through all the parents and re-define their onMouseUp property to do nothing?