Using live() with create:

I am creating a star rating function using the code from the Sitepoint JQuery Novice to Ninja book and it works great… except

I am refreshing data on the page using jquery and when the data is refreshed, the function does not apply itself to the new data. I assume I need to use the live() method but am not quite sure where to place it.

I have used it before with click but in the code below, do I need to put in several live() methods, one for click, one for hover, etc. or just one for the create:. And even if I do the click and hover, that still doesn’t take care of the function creation, right? Thanks for any help on this.


var starRating = {
	create: function(selector) {
	// loop over every element matching the selector
		$(selector).each(function() {
			var $list = $('<div></div>');
			// loop over every radio button in each container
			$(this).find('input:radio').each(function(i) {
				var rating = $(this).parent().text();
				var $item = $('<a href="#"></a>').attr('title', rating).addClass(i % 2 == 1 ? 'rating-right' : '').text(rating);
				
				starRating.addHandlers($item);
				$list.append($item);
				
				if($(this).is(':checked')) {
					$item.prevAll().andSelf().addClass('rating');
				}
			});
			// Hide the original radio buttons
			$(this).append($list).find('label').hide();
		});
	},
	addHandlers: function(item) {
		$(item).click(function(e) {
			// Handle Star click
			var $star = $(this);
			var $allLinks = $(this).parent();
			
			// Set the radio button value
			$allLinks.parent().find('input:radio[value=' + $star.text() + ']').attr('checked', true);
			$x = $star.text().length;
			rating = $star.text().substr(0, $x - 6);
    
			// Set the ratings
			$allLinks.children().removeClass('rating');
			$star.prevAll().andSelf().addClass('rating');
			
			// prevent default link click
			e.preventDefault();
		}).hover(function() {
			// Handle star mouse over
			$(this).prevAll().andSelf().addClass('rating-over');
			}, function() {
			// Handle star mouse out
			$(this).siblings().andSelf().removeClass('rating-over')
		});    
	}
}

Okay, thanks for the input. I’ll look into that and change to .delegate(). And that seems to take care of the click and hover events. But I don’'t understand how that helps with the creation of the stars which is what happens in the first part of the code.

So the ‘create: function’ is the part that actually creates the stars and I have added code in part of it to to select them based on a passed value. How do I handle that? Currently the primary problem is that when I go get data and change the data, they are showing up as radio buttons, not stars. Thanks

it’s a good point actually. I’ve never actually used .live() in any production code I think, .delegate() is my preferred method, probably because it isn’t just aimed at injected content but can also be used for, you guessed it, event delegation on large sets of elements.

While .live() is nice, .delegate() is the nicer of the two :wink:

I realize it’s not really the point of this thread, but I like .delegate better than [URL=“http://api.jquery.com/live/”].live, simply because it’s more effective and a lot less strain on the browser to maintain :slight_smile:

If you’re using .live() you won’t need to call the “addHandlers()” method every time you inject a new star rating. You’d only call it once. As of jQuery 1.4.2 you can add multiple space-separated event types in the .live() method.

A quick example to illustrate:

<!DOCTYPE html>
<html>
<head>
	<title>.live()</title>
	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
	<script type="text/javascript">

		function add() {
			$("body").append("<p><a href='#' class='link'>Some link</a></p>")
		}

		$(".link").live("click hover", function(e) {
			if (e.type == "click") {
				//clicked! Put your click handler code here
			}
			else {
				//it's a mouseenter or mouseleave
			}
		});
	</script>	
</head>
<body>
	<input type="button" onclick="add();" value="Submit" />
</body>
</html>