October 8, 2013

Using .on() and targeting elements with a specific ID

Brandon Durham’s Question:

I understand you can use .on() to attach a single click event to an element and then specify which child elements receive the click. So, for example:

$(this.el).on("click", "span", function () {
    alert("Bloop!");
});

I need to be a bit more specific and target selectors with a particular attribute, like this:

$(this.el).on("click", "span[data-placeholder]", function () {
    alert("Bloop!");
});

That doesn’t seem to work, though. As soon as I add the attribute it stops working. No errors, just doesn’t seem to find the elements.

Is that the expected behavior? Is there a way around it?

CLARITY

$(this.el) is just a div that contains a number of elements, some of which are <span data-placeholder="First Name"></span> tags. There could be dozens of those <span> tags and I didn’t want that many event listeners, so I thought I’d use .on() to add the click to the parent container.

You can choose to filter your spans

$('span', this.el).filter(function() {
     return $(this).hasAttr('data-placeholder');
}).on('click', function() {
   //This is for all the spans having data-placeholder
   //...
});

Or if the placeholder is set via data api:

$(this.el).filter(function() {
     return $(this).data('placeholder') != 'undefined';
}).on('click', function() {
   //This is for all the spans having data-placeholder
   //...
});

This functions above select those elements specifically, if event delegation on the OP is needed, then you can do the following:

$('span', this.el).on('click', 'span', function() {
     if($(this).data('placeholder') != 'undefined') {
         alert('bloop');
     }
});
March 18, 2013

How to control jQuery events when you have nested HTML?

Question by Cristian David Jimenez Duarte

For example:

<ul>
<li>
   first element
   <ul>
    <li> second element
       <ul>
          <li> third element </li>
       </ul>
      </li>
   </ul>
</li>
</ul>

<script>
$('li').click( function() {
   alert('hello world!!!');
});
</script>

The output is:

THREE ALERTS WHEN I CLICK THE THIRD ELEMENT

TWO ALERTS WHEN I CLICK THE SECOND ELEMENT

ONE ALERT WHEN I CLICK THE FIRST ELEMENT

How to prevent with jQuery this?

What I’m needing is: ONE ALERT FOR EACH CLICK IN ANY ‘LI’ ELEMENT.

Answer by Starx

As you have nested li elements. The click handler applies to all li elements including the parent li‘s.

You need to stop propagating the event bubble. So that once it execute the event handler, it does not goes up the DOM tree to trigger the same event.

$('li').click( function(e) {
   alert('hello world!!!');
   e.stopPropagation();
});
January 20, 2013

Catch browser's "zoom" event in JavaScript

Question by user123093

Is it possible to detect, using JavaScript, when the user changes the zoom in a page?
I simply want to catch a “zoom” event and respond to it (similar to window.onresize event).

Thanks.

Answer by Ian Elliott

There’s no way to actively detect if there’s a zoom. I found a good entry here on how you can attempt to implement it.

I’ve found two ways of detecting the
zoom level. One way to detect zoom
level changes relies on the fact that
percentage values are not zoomed. A
percentage value is relative to the
viewport width, and thus unaffected by
page zoom. If you insert two elements,
one with a position in percentages,
and one with the same position in
pixels, they’ll move apart when the
page is zoomed. Find the ratio between
the positions of both elements and
you’ve got the zoom level. See test
case.
http://novemberborn.net/javascript/page-zoom-ff3

You could also do it using the tools of the above post. The problem is you’re more or less making educated guesses on whether or not the page has zoomed. This will work better in some browsers than other.

There’s no way to tell if the page is zoomed if they load your page while zoomed.

Answer by Starx

There is a nifty plugin built from yonran that can do the detection. Here is his previously answered question on StackOverflow. It works for most of the browsers. Application is as simple as this:

window.onresize = function onresize() {
  var r = DetectZoom.ratios();
  zoomLevel.innerHTML =
    "Zoom level: " + r.zoom +
    (r.zoom !== r.devicePxPerCssPx
        ? "; device to CSS pixel ratio: " + r.devicePxPerCssPx
        : "");
}

Demo

April 3, 2012

How to pass click events from one div to another?

Question by Yuvals

I need to find a way to pass click events from a div on top to the div below it (and ignore the clicks on the higher div).
There is a known way of simulating the click event and passing it to the other div, but this is not a natural behavior and the least wanted option.

It seems that event bubbling will not help here since the div on the top is not contained in the one below..

Any idea?

here is a jsfiddle example:

http://jsfiddle.net/QKjUx/

If you remove the “overlay” div, you can click on either of the elements. While it’s there, you cannot. It is possible to pass the event to the div below, however, the position is important – there can be a link which I want the user to be able to click on.

Answer by viebel

add this css property to the overlay div:

   pointer-events: none;

You can read more about it at: http://robertnyman.com/2010/03/22/css-pointer-events-to-allow-clicks-on-underlying-elements/

Answer by Starx

You can trigger click event on one div, by clicking on another div.

You can create an event a click event like

//A function to fire an event
function eventFire(el, etype){
    if (el.fireEvent) {
      el.fireEvent('on' + etype);
    } else {
      var evObj = document.createEvent('cClick');
      evObj.initEvent(etype, true, false);
      el.dispatchEvent(evObj);
    }
}

var div1 = document.getElementByID("firstDiv"); //find the first div
div1.onClick = function() { //attach a onclick event
   //Now select the element and fire the event
   var div2 = document.getElementById("seconddiv"); //select the second div
   eventFire(div2, 'click'); //fire the click event
};
March 10, 2012

Click event listener on a <tr>

Question by Jonny Sooter

I have this event that listens for a click on a img then it switches the img for another, but this img can get real small and I wanted to make the entire tr click able. Any suggestions?

$('#example tbody td img').live('click', function () {
                var nTr = $(this).parents('tr')[0];
                if ( oTable.fnIsOpen(nTr) )
                {
                    /* This row is already open - close it */
                    this.src = "images/details_open.png";
                    oTable.fnClose( nTr );
                }
                else
                {
                    /* Open this row */
                    this.src = "images/details_close.png";
                    oTable.fnOpen( nTr, fnFormatDetails(oTable, nTr), 'details' );
                }
            } );

Update
I tried using this but now my img won’t change. How would I select the img to use (this) or do I just make a var for it?

$('#example tbody td').on('click', function (e) {
        var myImage = $(this).find("img");
        var nTr = $(this).parents('tr')[0];
        if ( oTable.fnIsOpen(nTr) )
        {
        /* This row is already open - close it */
        myImage.src = "images/details_open.png";
        oTable.fnClose( nTr );
        }
        else
        {
        /* Open this row */
        myImage.src = "images/details_close.png";
        oTable.fnOpen( nTr, fnFormatDetails(oTable, nTr), 'details' );
        }
    } );

Answer by Mohammed ElSayed

first: it’s now better to use delegate() or on() instead of live(), which is now deprecated by the way.

second: just add a handler for the td, and by nature, it will get the same click event that will occur on your img, then you can eaisly select the img and play with it like nomral, consider the following example which is using the better way of on()

Update: I’ve modified the code a little bit to make it better

    $('#example tbody').on('click', 'td', function (e) {
        var myImage = $(this).find("img");
        var nTr = this.closest('tr');
                if ( oTable.fnIsOpen(nTr) )
                {
                    /* This row is already open - close it */
                    myImage.src = "images/details_open.png";
                    oTable.fnClose( nTr );
                }
                else
                {
                    /* Open this row */
                    myImage.src = "images/details_close.png";
                    oTable.fnOpen( nTr, fnFormatDetails(oTable, nTr), 'details' );
                }
}

you should now be ok with this solution, let me know if you need further help.

Answer by Starx

Pretty Simple

Select td instead of img

 $('#example tbody td').on('click', function () {

P.S: Of course the live function has been deprecated so its better to use .on()

April 21, 2011

call jquery function from server

Question by user321963

In asp.net, How can i trigger client side jquery event from server. I want to implement it in my chat section… current the chat seems to work fine… but it has one problem… i have to send a request every 5 seconds from client’s browser to the his chat history.. which i feel is not a good idea…

can anyone provide any solution for my problem

Answer by Starx

Although, I am not that skilled in ASP.Net, this problem can be solved in another way.

Have the server return the name of function you need to execute, then call it in the callback function?

Kinda like this (It is just a typo but)

$.post("yourpage.aspx",
   {
      d1: "v1"
   },
   function(data) {
     //now the data will hold the name of the function
     window[data](); 
   }
);

Now you can wrap the above code, in the another function, and set up a timer, to check for the response regularly, and execute the function if a condition is matched.

P.S. I have skipped the part, where the scripts check if the condition is matched.

March 29, 2011

Method for over-riding various jQuery events if a global var is not set

Question by Dunhamzzz

I have various jQuery click and submit events on my site, but some of them I only want to activate if the user is logged in (yes I have all required server-side validation), if they are not logged in, I want a jQuery UI dialogue to pop up.

If the user is logged in the page will have a javascript variable set: with var uk = 'randomkey';

What is the best method for this? Off the top of my head some sort of global function which checks for user value and fires the dialogue and returns false? Or is there a neater/optimised way of doing it.

Answer by Richard Neil Ilagan

Since you say that you’re already performing server-side validation, I’d suggest that you take away all the JS behavior you want for logged-in users, and those for not-logged-in users to two separate JS files, and load the relevant one into the page before your server even flushes the HTML back to the browser.

Answer by Starx

It would be better if you would filter the elements while the page is loading, to avoid unauthorised access. Try to avoid complexity as much as possible.

But if you really need to do this, you can send a ajax request to detect if user is logged in (Relying on the client’s browser by setting class name is a bad idea, it can be easily tampered).

Just an example

$.post(
    "apage.php",
    { action: 'checklogged' },
    function(data) {
        //if the response come as `no` and `yes`
        if(data=='no') {
            //dialogbox code
        }
        else {
           var uk = 'randomkey';
        }
    }
);
August 16, 2010

Continuing to hide HTML input fields when page refreshes?

Question by John M

On a HTML page there is a filter section consistenting of various drop-downs and textboxes. When the ‘type_of_report’ drop-down is selected the ‘onchange’ event will hide all the non-relevant inputs for that ‘type_of_report’. The filter criteria is preserved via GET (which I retrieve via PHP $_GET).

The problem is that when I submit the form (run the report) the ‘hidden’ fields re-appear when the page refreshes.

How do I keep the non-relevant input fields hidden when the page refreshes?

NOTE: I am using jQuery (1.4.2) to hide the fields.

UPDATE1:

Final abbreviated solution (based on feedback) looks like this:

<?php
$report_type = $_GET['report_type'];
?>
<html>
<head>
   <!-- hiding/unhiding based on report type -->
   <script type="text/javascript" src="hide.js"></script>
</head>
<body onLoad="hideall('<?php echo"$report_type"; ?>');">

...rest of code

Answer by Starx

Setup a session variables to keep the status of the drop down boxes. And while you are loading it in the view port… filter them using the session variable. It should solve your problem.

...

Please fill the form - I will response as fast as I can!