onmousedown doesn't callback after changing class dynamically - javascript

I have the following divs:
<div class="celula" id="838">
</div>
<div class="celula" id="839">
</div>
<div class="celula" id="840">
</div>
I change them dynamically using jquery with an ajax response so far it works great.
Imagine that it generates the following:
<div class="checked" id="838">
</div>
<div class="checked" id="839">
</div>
<div class="checked" id="840">
</div>
Complete js callback:
$(document).ready(function () {
document.getElementById("templatenome").innerHTML = screen.width + " - " + screen.height;
$('.celula').on('mousedown', function(){
var template = $("#templatenome").attr("name");
var $div = document.getElementById (this.id);
$div.style.backgroundImage = "url('../../resources/"+template+"/images/CelulaPOP.png')";
var audio = document.getElementById("audio");
audio.play();
$(document).one('mouseup', function(){
sendAjax($div.id);
$div.style.backgroundImage = "url('../../resources/"+template+"/images/CelulaSEL.png')";
});
});
$(document).on('mousedown', '.checked', function(){
$(document).one('mouseup', function(){
});
});
});

Use a delegated event handler, attached to a non-changing ancestor of the dynamic elements:
$(document).on('mousedown', '.checked', function(){
$(document).one('mouseup', function(){
alert("I was mouse-uppped on a .checked div!");
});
});
As you do not want the previous handler to operate once the class is changed (see comments below), make that a delegated handler too:
e.g.
$(document).on('mousedown', '.celula', function(){
This applies the jQuery selector at event time only, so the elements only need to match then (and not when the event was registered).
document is the best default if nothing closer is available/convenient. Do not use 'body' as it has a bug (if styling results in a calculated body height of 0 it will not bubble mouse events to body)
Here is a little demo showing how events will fire with the delegated event handlers as the classes are changed:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/5xb6vohp/3/

Related

jquery (hover and load) events binding on dynamically created elements

I am able to bind click event to element with class name keybox. And this element is generated dynamically.
$('body').on('click','.keybox', function(){
// some code here
});
But for same element I tried binding hover and load event using following code:
$('body').on('hover','.keybox', function(){
// some code here
});
$('body').on('load','.keybox', function(){
// some code here
});
....and its not working as expected.
Can someone help with this problem? I want to bind hover and load event to my element with class name keybox and this element is generated dynamically.
Instead of hover, use mouseenter and mouseleave event. Instead of body.load use
$(document).ready(function() {
You can use following approach to bind multiple events and get object information via event object.
$('body').bind('click hover load', '.keybox', function(e){
if ( e.type === 'hover') {
// do something
}
else if(e.type === 'click') {
// do something
}
....
});
Make sure you bind events in $(document).ready(function() {} or load javascript just in bottom of html document body.
Since hover is deprecated you should use mouseenter and mouseleave for load you can write using event using on(load is equivalent to ready).
$(function(){
$(document).on('mouseenter', '.keybox', function () {
$(this).css('color','red');
});
$(document).on('mouseleave', '.keybox', function () {
$(this).css('color','black');
});
$(document).on('click', '.keybox', function () {// click on dynamically loaded events.
$(this).css('color','green');
});
$('#btn').click(function() {
$('#parent').append("<div class='keybox'>sample1</div>");
$('#parent').append("<div class='keybox'>sample2</div>");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
zdhsdhsau
</div>
<input type="button" id="btn" value="create"/>

How to setup Rx.Observable.fromEvent to work with jQuery filtered events

There are lots of examples of Rx.Observable.fromEvent(element, eventName) using a jquery selection as the element to capture events from. However is it possible for Rx listen to only events from a filtered event setup with jQuery?
//Bind the event on body but only respond to events that match the filter
$('body').on('click', '.aClass div .something', function () {...});
//Bind to 'body' but only respond to events from the binding above
Rx.Observable.fromEvent(/*something here?*/);
I have come up with something effectively similar but it seems like it would be much more costly than the jquery filter.
Rx.Observable.fromEvent($('body'), 'click')
.filter(function (e) {
return $(e.target).is('.aClass div .something');
})
.subscribe(function () {...});
Is there some way I could turn the jQuery binding into an emitter and use that event stream with Rx?
What's the best approach?
see http://jsfiddle.net/ktzk1bh3/2/
HTML:
<div class="aClass">
<div>
<a class="something">Click me</a>
</div>
</div>
Javascript:
//Bind to 'body' but only respond to events from the binding above
var source = Rx.Observable.create(function(o) {
$('body').on('click', '.aClass div .something', function(ev) {
o.onNext(ev);
})
});
var sub = source.subscribe(function(ev) { console.log("click", ev) });
You can use Rx.Observable.fromEventPattern.
Rx.Observable.fromEventPattern(
function add(handler) {
$('body').on('click', '.aClass div .something', handler);
},
function remove(handler) {
$('body').off('click', '.aClass div .something', handler);
}
);
This way it will automatically remove event handler on unsubscribe from observable subscription.
<div class='radios'>
<input type='radio' name='r' value='PM'>PM
<input type='radio' name='r' value='PCE'>PCE
<input type='radio' name='r' value='PCS'>PCS
</div>
<textarea class='textarea'>
</textarea>
Rx.Observable.fromEvent(document.querySelector('.radios'),'click')
.subscribe((e)=>console.log(e.target.value));

jQuery click handler only fires once

Appended images used as buttons to show/hide content below a heading:
<!DOCTYPE html>
<html>
<body>
<h2>
the heading
</h2>
<p>
the content
</p>
</body>
</html>
$(document).ready(function () {
var $imag = $("<img src='arrow_down.jpg'>");
var $imag2 = $("<img src='arrow_up.jpg'>");
$("h2").append($imag);
$($imag).on("click", function(){
$("p").hide();
($imag).remove();
$("h2").append($imag2);
});
$($imag2).on("click", function () {
$("p").show();
($imag2).remove();
$("h2").append($imag);
});
});
$(document).main(ready);
At first the images work when clicked. but the next time you click it, it doesn't
without having to refresh the page. Why?
This is because event handlers like click() have to be appended to elements that are already in the DOM when the page is loaded. For elements that are added later the event has to be delegated from a static parent element using on(), like:
$(document).on("click", $imag, function(){
$("p").hide();
($imag).remove();
$("h2").append($imag2);
});
$(document).on("click", $imag2, function () {
$("p").show();
($imag2).remove();
$("h2").append($imag);
});
Just added a Fiddle with an adjustment as I wasn't sure if this would work with the variables $imag / $imag2 (it doesn't). Instead you should just add classes to your images, e.g. like this:
var $imag = $("<img class='down' src='arrow_down.jpg'>");
var $imag2 = $("<img class='up' src='arrow_up.jpg'>");
with adjusted code
$(document).on("click", '.down', function(){
$("p").hide();
$('.down').remove();
$("h2").append($imag2);
});
$(document).on("click", '.up', function () {
$("p").show();
$('.up').remove();
$("h2").append($imag);
});
For reference: https://api.jquery.com/on/#on-events-selector-data-handler, section "Direct and delegated events":
"Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on()."

Applying the same change function to multiple divs?

What is the best way to bind a functions to multiple div's?
$('#trigger1').change(function(){
// same code
});
$('#trigger3').change(function(){
// same code
});
Either use class (imo is class the best way)
<div class="trigger"></div>
<div class="trigger"></div>
$('.trigger').change(function(){
});
or do this
$('#trigger1,#trigger3').change(function(){
});
You can include multiple ids in the same function call:
$('#trigger1, #trigger3').change(function(){
// code goes here
});
Or you can give them the same class, e.g. triggerClass and then call it like such:
$('.triggerClass').change(function(){
// code goes here
});
add a common class name to those div
<div class="myClass" id="trigger1">
</div>
<div class="myClass" id="trigger2">
</div>
here is the script for it
$(".myClass").click(function(){
// your code
});
$('#trigger1, #trigger3').change(some_function);
Or:
$('#trigger1').add('#trigger3').change(some_function);
simply apply a same class to all elements then write
$('.classname').change(function(){
});
you could use
$('#trigger1, #trigger3').change(function(){
same code
});
to group the triggers
Add a common class:
<div class="rowTrigger">trigger 1</div>
<div class="rowTrigger">trigger 2</div>
Script
$(function(){
$("body").on("click", ".rowTrigger", function(e){
e.preventDefault();
var row = $(this); //row element
});
});
each "rowTrigger" will fire on the "click" handler, this can be changed to other or multiple events. See
http://api.jquery.com/on/ for more detail.
The scope of the events handled can be changed by changing "body" to "table" for example, so it will only fire when those 'div' rows from a table are clicked.
More simply it can be written as (firing for 'click' and 'hover' ... but you get the idea) :
$("div.rowTrigger").on("click hover", function(e){
e.preventDefault();
var row = $(this); //row element
//some extra code
});

Event handler triggered twice instead of once

I am sorry that I have asked two questions in a few minutes.
In a html file, I got three child DIV tags in a parent DIV tag:
<div id="container">
<div id="frag-123">123</div>
<div id="frag-124">124</div>
<div id="frag-125">125</div>
</div>
Now when I click either the three child DIV tags, I will see two alert boxes pop up instead of one:
The first alert box will show something like this:
frag-123, and the second alert box will show something like this:
container
I dont know why.
I just want to get the ID value of a child DIV, not the one from the parent DIV.
<script>
$(function() {
$("div").click(function() {
var imgID = this.id;
alert(imgID);
});
});
</script>
Please help.
This is a case of event bubbling. You can stop event bubbling by giving
e.stopPropagation()
inside the click event handler.
Try
$(function() {
$("div").click(function(e) {
var imgID = this.id;
alert(imgID);
e.stopPropagation() // will prevent event bubbling
});
});
If you want to bind click event to only child elemets inside the container div then you can give like this
$("#container div").click(function(){
var imgID = this.id;
alert(imgID);
});
That's because you're binding the event handler to all DIVs. Instead, what you want is bind it only to DIVs within container:
<script type="text/javascript">
$(function() {
$("#container div").click(function() {
var imgID = this.id;
alert(imgID);
});
});
</script>

Categories