Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

document.ready() analog for $(html)/$.ajax

Tags:

jquery

I use jQuery to attach some plugins in the $(document).ready() handler - for example, $(".date").datepicker(). However, when I load content using $("...html..."), for example from $.ajax(.., success(data){}), or from ajaxForm({target:...}), document.ready() is obviously not called. UPDATE: as pointed out it is called but still I don't know what portion/element was loaded.

I can't just do ready() again because it will re-attach plugins second time to elements that have it already. So I have to do it manually in every case, like, I do success(data) { item = $(data); initDatePickerEtc(item); }.

Is there a better way?

There's Live Query plugin that does it for events. Is there something that will allow me to track HTML elements creation and perform actions then? Something like

$.oncreation(".date", function() { $(this).datepicker(); });
// or at least
$.oncreation(function() { $(this).find(".date").datepicker(); });

Great if it will also process existing elements... like Live Query works for both existing at the time of click() call, and the future-created elements.

Note that I'll be happy tracking only elements created by jQuery. So it's either jQuery provides extension point to its html() function or not, I guess. Now, from the jQuery sources it does not:

html: function( value ) {
    return value === undefined ?
        (this[0] ?
            this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
            null) :
        this.empty().append( value );
},

Maybe if I replace html() so that even 3-rd party plugins (e.g. ajaxForm) will use my version (that will fire $.creation callback) instead of default jQuery one... will it work? There're problems with this approach - it's not only html(), it's append(), etc... and it would be great to get the event only if result of $("") is appended to the document... since when it's in memory I don't need datepicker().

like image 338
queen3 Avatar asked Nov 27 '25 20:11

queen3


2 Answers

If it is an option for you, you can include a $(document).ready() statement in the returned html. The function passed there will be called after the returned html is rendered.

like image 165
Jan Willem B Avatar answered Nov 30 '25 12:11

Jan Willem B


What you are probably looking for are the W3C mutation events, such as DOMNodeInserted and DOMNodeRemoved Unfortunately, they are not supported by all browsers (the IE family of browsers do not support them at all), so we need to look at other ways of achieving cross-browser functionality.

The way that live() works is to use event delegation and it is possible that you could implement event delegation in your own code. As an example,

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/base/jquery-ui.css" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<title>Demo</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<script type="text/javascript">
$(function() {
    $('.picker').datepicker();

    $('button').click(function() {
      $(this).prev().before('<br/><input type="text" class="picker" />');
    });

    $('div.container').click(function(e) { 
      var target = $(e.target);    
      if (target.hasClass('picker') && !target.hasClass('hasDatepicker')) { 
        $(e.target).datepicker().datepicker('show'); 
      }
    });
});
</script>
</head>
<body>
<div class="container">
<input type="text" class="picker" />
<br/>
<button>Add a new input</button>
</div>
</body>
</html>

Here we check the event.target on the container <div> to see if it has the class picker and not the class hasDatepicker (which is added by the datepicker plugin to indicate an input with a datepicker attached). If the event.target meets the criteria, we bind a datepicker to it and then call datepicker('show') on it. If the event.target already has a datepicker attached then clicking on the input will show the datepicker and if event.target does not have picker class or no datepicker attached, then nothing will happen.

I chose datepicker as you mentioned it in your question, but the idea of event delegation can be applied in many different circumstances, however, not all events bubble.

like image 42
Russ Cam Avatar answered Nov 30 '25 11:11

Russ Cam



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!