Skip to content

Commit

Permalink
Added moviesNoGlobals samples to show how to access functions from te…
Browse files Browse the repository at this point in the history
…mplates

without creating globals.
- Code is wrapped in  a function closure: (function($) {...})(jQuery);
- The formatDate function within the closure is called from within the
  template by passing it in with options:
	$( "#bookingEditTmpl" ).tmpl( booking, { formatDate: formatDate } )
- and accessing it on the template item, $item:
	${$item.formatDate()}.
See https://github.com/jquery/jquery-tmpl/issues#issue/39
  • Loading branch information
BorisMoore committed Jan 5, 2011
1 parent 4a8ce1c commit f9b00c8
Show file tree
Hide file tree
Showing 2 changed files with 363 additions and 4 deletions.
4 changes: 0 additions & 4 deletions demos/movies/PagesCore/movies.html
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,6 @@ <h1>Netflix: Book a Movie...</h1>
function formatDate( date ) {
return date.toLocaleDateString();
}

function removeContext( item ) {
$( item.nodes ).remove();
}
</script>

</body>
Expand Down
363 changes: 363 additions & 0 deletions demos/movies/PagesCore/moviesNoGlobals.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!--
This sample illustrates using templates for a more complete and
realistic scenario.
It uses the NetFlix OData JSONP services as a source of data.
This version of the movies sample demo uses the
$( templateSelector ).tmpl( data ).appendTo( targetSelector )
pattern, and does not use the tmplCmd plugin or the rendered event.
Notice that in the example there are no global variables:
Code is wrapped in a function closure: (function($) {...})(jQuery);
The formatDate function within the closure is called from within the
template by passing it in with options:
$( "#bookingEditTmpl" ).tmpl( booking, { formatDate: formatDate } )
and accessing it on the template item, $item:
${$item.formatDate()}.
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>jQuery + OData + Netflix Catalog API</title>
<link href="../css/jquery-ui-1.8.1.custom.css" rel="stylesheet" type="text/css" />
<link href="../css/movies.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="pageBody">
<h1>Netflix: Book a Movie...</h1>

<ul id="genres">
<li class="selected">Cartoons</li>
<li>Drama</li>
<li>Foreign</li>
<li>Action Classics</li>
<li>Horror</li>
<li>Sci-Fi Cult Classics</li>
</ul>

<div id="pager"><ul class="pages"><li class="pgEmpty">first</li><li class="pgEmpty">prev</li></ul></div>

<div id="movieList"></div>
<table id="bookingsList">
<tbody><tr class="cart"><td class="cart-false" colspan="4">
<span class="text">0 items in Cart...</span>
</td></tr></tbody>
</table>
<br/>
</div>
<script src="http://code.jquery.com/jquery.js"></script>
<script src="../../../jquery.tmpl.js" type="text/javascript"></script>
<script src="../components/jquery.pager.js" type="text/javascript"></script>
<script src="../components/jquery-ui-1.8.1.custom.js" type="text/javascript"></script>

<script id="movieTmpl" type="text/x-jquery-tmpl">
<div>
<div><img src="${BoxArt.LargeUrl}" /> </div>
<strong>${Name}</strong>
<p>{{html Synopsis}}</p>
<input type="button" title="Buy tickets for '${Name}'" value="Add to cart..." class="buyButton"/>
<br/>
</div>
</script>

<script id="cartTmpl" type="text/x-jquery-tmpl">
<td class="cart-${!!count}" colspan="4">
<span class="text">${count} items in Cart...</span>
{{if count}}
<span id="submit">Checkout</span>
<span id="cancel">Remove All</span>
{{if count>1}}
<span id="sort"><span id="sortBtn">Sort</span>:
<select>
<option value="0" {{if sortBy==="0"}}selected{{/if}}>Name A-Z</option>
<option value="1" {{if sortBy==="1"}}selected{{/if}}>Name Z-A</option>
<option value="2" {{if sortBy==="2"}}selected{{/if}}>Date</option>
</select>
</span>
{{/if}}
</select>
{{/if}}
</td>
</script>

<script id="bookingTitleTmpl" type="text/x-jquery-tmpl">
<tr class="bookingTitle${$item.mode}">
<td>${movie.Name}</td><td>${movieTheater}</td>
<td>${$item.formatDate()}</td>
<td>
${quantity}
<span class="ui-icon close"></span>
</td>
</tr>
</script>

<script id="bookingEditTmpl" type="text/x-jquery-tmpl">
{{tmpl($data, { mode: "Edit", formatDate: $item.formatDate }) "#bookingTitleTmpl"}}
<tr class="bookingEdit">
<td colspan="4">
<div class="fields">
<span>Movie Theater: </span><input class="theater" type="text" value="${movieTheater}" /><br/>
<span>Date: </span><input class="date" type="text" value="${$item.formatDate()}" /><br/>
<span>Quantity: </span><input class="quantity" type="text" value="${quantity}" />
</div>
<div><img src="${movie.BoxArt.LargeUrl}" /></div>
</td>
</tr>
</script>

<script type="text/javascript">
(function($) {
var genre="Cartoons", pageIndex = 1, pageSize = 3, pageCount = 0,
cart = { bookings: {}, count: 0, sortBy:0 }, bookingTmplItems = {}, selectedBooking;

getMovies( pageIndex );

$( "#genres li" ).click( selectGenre );

$( ".cart" )
.delegate( "select", "change", sort )
.delegate( "#sortBtn", "click", sort )
.delegate( "#submit", "click", function() {
alert( cart.count + " bookings submitted for payment...");
removeBookings();
})
.delegate( "#cancel", "click", function() {
removeBookings();
})
.empty();

$( "#cartTmpl" )
.tmpl( cart )
.appendTo( ".cart", cart );

var cartTmplItem = $( ".cart td" ).tmplItem();

function selectGenre() {
$( "#genres li" ).removeClass( "selected" );
$( this ).addClass( "selected" );

pageIndex = 1;
genre = encodeURI( $(this).text() );
getMovies( pageIndex );
}

function sort() {
var compare = compareName, reverse = false, data = [];
cart.sortBy = $( "#sort select" ).val();
switch ( $( "#sort select" ).val() ) {
case "1":
reverse = true;
break;
case "2":
compare = compareDate;
break;
}

for ( var item in cart.bookings ) {
data.push( cart.bookings[item] );
}
data = data.sort( compare );

for ( var i = 0, l = data.length; i < l; i++ ) {
$( bookingTmplItems[data[i].movie.Id].nodes ).appendTo( "#bookingsList" );
}

function compareName( a, b ) {
return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1);
}
function compareDate( a, b ) {
return a.date - b.date;
}
}

function getMovies( index ) {
var query = "http://odata.netflix.com/Catalog/Genres('" + genre + "')/Titles" +
"?$format=json" +
"&$inlinecount=allpages" + // get total number of records
"&$skip=" + (index-1) * pageSize + // skip to first record of page
"&$top=" + pageSize; // page size

pageIndex = index;

$( "#movieList" )
.fadeOut( "medium", function () {
$.ajax({
dataType: "jsonp",
url: query,
jsonp: "$callback",
success: showMovies
});
});
}

function showMovies( data ) {
pageCount = Math.ceil( data.d.__count/pageSize ),
movies = data.d.results;

$( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: getMovies });

$( "#movieList" ).empty();

$( "#movieTmpl" )
// Render movies using the movieTemplate
.tmpl( movies )

// Display rendered movies in the movieList container
.appendTo( "#movieList" )

// Animate
.find( "div" ).fadeIn( 4000 ).end()

// Add click handler
.find( ".buyButton" ).click( function() {
buyTickets( $(this).tmplItem().data );
});

$( "#movieList" ).fadeIn( "medium" )
}

function buyTickets( movie ) {
// Add item to cart
var booking = cart.bookings[movie.Id];
if ( booking ) {
booking.quantity++;
} else {
cart.count++;
cartTmplItem.update();
booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" };
}
selectBooking( booking );
}

function selectBooking( booking ) {
if ( selectedBooking ) {
if ( selectedBooking === booking ) {
updateBooking( bookingTmplItems[selectedBooking.movie.Id]);
return;
}
// Collapse previously selected booking, and switch to non-edit view
var oldSelected = selectedBooking;
$( "div", bookingTmplItems[oldSelected.movie.Id].nodes ).animate( { height: 0 }, 500, function() {
switchView( oldSelected );
});
}
selectedBooking = booking;
if ( !booking ) {
return;
}
if ( cart.bookings[booking.movie.Id] ) {
switchView( booking, true );
} else {
cart.bookings[booking.movie.Id] = booking;

var bookingNode = $( "#bookingEditTmpl" )

// Render the booking for the chosen movie using the bookingEditTemplate
.tmpl( booking, { animate: true, formatDate: formatDate } )

// Append the rendered booking to the bookings list
.appendTo( "#bookingsList" )

// Get the 2nd <tr> of the appended booking
.last()[0];

// Get the template item for the 2nd <tr>, which is the template item for the "bookingEditTmpl" template
var newItem = $.tmplItem( bookingNode );
bookingTmplItems[booking.movie.Id] = newItem;

// Attach handlers etc. on the rendered template.
bookingEditRendered( newItem );
}
}

function bookingEditRendered( item ) {
var data = item.data, nodes = item.nodes;

$( nodes[0] ).click( function() {
selectBooking();
});

$( ".close", nodes ).click( removeBooking );

$( ".date", nodes ).change( function() {
data.date = $(this).datepicker( "getDate" );
updateBooking( item );
})
.datepicker({ dateFormat: "DD, d MM, yy" });

$( ".quantity", nodes ).change( function() {
data.quantity = $(this).val();
updateBooking( item );
});

$( ".theater", nodes ).change( function() {
data.movieTheater = $(this).val();
updateBooking( item );
});

if ( item.animate ) {
$( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 );
}
}

function bookingRendered( item ) {
$( item.nodes ).click( function() {
selectBooking( item.data );
});
$( ".close", item.nodes ).click( removeBooking );
}

function switchView( booking, edit ) {
if ( !booking ) {
return;
}
var item = bookingTmplItems[booking.movie.Id],
tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).template();
if ( item.tmpl !== tmpl) {
item.tmpl = tmpl;
item.update();
(edit ? bookingEditRendered : bookingRendered)( item );
}
}

function updateBooking( item ) {
item.animate = false;
item.update();
(item.data === selectedBooking ? bookingEditRendered : bookingRendered)( item );
item.animate = true;
}

function removeBooking() {
var booking = $.tmplItem(this).data;
if ( booking === selectedBooking ) {
selectedBooking = null;
}
delete cart.bookings[booking.movie.Id];
cart.count--;
cartTmplItem.update();
$( bookingTmplItems[booking.movie.Id].nodes ).remove();
delete bookingTmplItems[booking.movie.Id];
return false;
}

function removeBookings() {
for ( var item in bookingTmplItems ) {
$( bookingTmplItems[item].nodes ).remove();
delete bookingTmplItems[item];
}
bookingTmplItems = {};
cart.count = 0;
cart.bookings = {};
selectedBooking = null;
cartTmplItem.update();
}

function formatDate() {
return this.data.date.toLocaleDateString();
}
})(jQuery);
</script>

</body>
</html>

0 comments on commit f9b00c8

Please sign in to comment.