<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Grubbsian &#187; jQuery</title>
	<atom:link href="http://www.thegrubbsian.com/category/jquery/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thegrubbsian.com</link>
	<description>Writings on .NET, Ruby, JavaScript, HTML/CSS, Design, and all things Web.</description>
	<lastBuildDate>Sun, 01 Aug 2010 20:57:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>jQuery.ganttView a Lightweight Gantt Chart for jQuery</title>
		<link>http://www.thegrubbsian.com/2010/06/11/jquery-ganttview-a-lightweight-gantt-chart-for-jquery/</link>
		<comments>http://www.thegrubbsian.com/2010/06/11/jquery-ganttview-a-lightweight-gantt-chart-for-jquery/#comments</comments>
		<pubDate>Fri, 11 Jun 2010 16:05:16 +0000</pubDate>
		<dc:creator>JC Grubbs</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thegrubbsian.com/?p=311</guid>
		<description><![CDATA[I just wanted to drop a quick post about a new jQuery plugin that I&#8217;ve been working on for a recent project. As the title of the post implies it renders a simple HTML based Gantt chart using jQuery and the excellent date.js library. The screenshot below should give you an idea of what can [...]]]></description>
			<content:encoded><![CDATA[<p>I just wanted to drop a quick post about a new jQuery plugin that I&#8217;ve been working on for a recent project.  As the title of the post implies it renders a simple HTML based Gantt chart using jQuery and the excellent <a href="http://www.datejs.com/">date.js</a> library.  The screenshot below should give you an idea of what can be done with the plugin.<br />
<br/><br />
<img src="http://www.thegrubbsian.com/wp-content/uploads/2010/06/jquery-ganttview.png"/><br />
<br/><br />
The current version is fairly stable and has been tested in FireFox 3.6, Safari 4, Chrome 5, and IE8 and works well in all those browsers.  There are likely a few issues with it in IE7 and I wouldn&#8217;t even bother checking IE6, unless someone sends me a patch I have no interest in supporting IE6.<br />
<br/><br />
The source code and documentation can be found on GitHub: <a href="http://github.com/thegrubbsian/jquery.ganttView">http://github.com/thegrubbsian/jquery.ganttView</a><br />
<br/><br />
Let me know what you think and if there are any specific features you&#8217;d like to see added.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thegrubbsian.com/2010/06/11/jquery-ganttview-a-lightweight-gantt-chart-for-jquery/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>jQuery Plugin: tablePager</title>
		<link>http://www.thegrubbsian.com/2009/06/05/jquery-plugin-tablepager/</link>
		<comments>http://www.thegrubbsian.com/2009/06/05/jquery-plugin-tablepager/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 18:38:18 +0000</pubDate>
		<dc:creator>JC Grubbs</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thegrubbsian.com/?p=211</guid>
		<description><![CDATA[Here&#8217;s a quick table pager plugin for jQuery. Unlike a number of the other plugins out there, this one doesn&#8217;t alter the DOM tree of the table itself it just hides the rows that are not available for the current page. In this way you can still get access to all the elements of the [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a quick table pager plugin for jQuery.  Unlike a number of the other plugins out there, this one doesn&#8217;t alter the DOM tree of the table itself it just hides the rows that are not available for the current page.  In this way you can still get access to all the elements of the table throughout the lifetime of the page.</p>
<p>Plugin Source:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    $.<span style="color: #660066;">fn</span>.<span style="color: #660066;">tablePager</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>options<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">/*
        options = {
        firstBtn: Element,
        prevBtn: Element,
        nextBtn: Element,
        lastBtn: Element,
        indicator: Element,
        sizeSelect: Element,
        pageSize: Number,
        onPageChange: Callback,
        onPageSizeChange: Callback
        };
        */</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">var</span> tbl <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> defaults <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> pageSize<span style="color: #339933;">:</span> <span style="color: #CC0000;">10</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> opts <span style="color: #339933;">=</span> $.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span>defaults<span style="color: #339933;">,</span> options<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">var</span> pageIndex <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> pageSize <span style="color: #339933;">=</span> opts.<span style="color: #660066;">pageSize</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> rowCount <span style="color: #339933;">=</span> getRows<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">length</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> pageCount <span style="color: #339933;">=</span> getPageCount<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            bindControlHandlers<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            updatePaging<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            updateIndicator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> getRows<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">return</span> tbl.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;tbody tr&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> bindControlHandlers<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>opts.<span style="color: #660066;">firstBtn</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
	        opts.<span style="color: #660066;">firstBtn</span>.<span style="color: #660066;">unbind</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;click&quot;</span><span style="color: #339933;">,</span> 
		    <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> changePage<span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
            <span style="color: #009900;">&#125;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>opts.<span style="color: #660066;">prevBtn</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
		opts.<span style="color: #660066;">prevBtn</span>.<span style="color: #660066;">unbind</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;click&quot;</span><span style="color: #339933;">,</span> 
			<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> changePage<span style="color: #009900;">&#40;</span>pageIndex <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	    <span style="color: #009900;">&#125;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>opts.<span style="color: #660066;">nextBtn</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
		opts.<span style="color: #660066;">nextBtn</span>.<span style="color: #660066;">unbind</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;click&quot;</span><span style="color: #339933;">,</span> 
			<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> changePage<span style="color: #009900;">&#40;</span>pageIndex <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	    <span style="color: #009900;">&#125;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>opts.<span style="color: #660066;">lastBtn</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
		opts.<span style="color: #660066;">lastBtn</span>.<span style="color: #660066;">unbind</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;click&quot;</span><span style="color: #339933;">,</span> 
			<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> changePage<span style="color: #009900;">&#40;</span>pageCount <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	    <span style="color: #009900;">&#125;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>opts.<span style="color: #660066;">sizeSelect</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
		opts.<span style="color: #660066;">sizeSelect</span>.<span style="color: #660066;">unbind</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;change&quot;</span><span style="color: #339933;">,</span> 
                    <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> changePageSize<span style="color: #009900;">&#40;</span>parseInt<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	    <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> getPageCount<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span>rowCount <span style="color: #339933;">%</span> pageSize<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> 
		Math.<span style="color: #660066;">floor</span><span style="color: #009900;">&#40;</span>rowCount <span style="color: #009966; font-style: italic;">/ pageSize) + 1 : (rowCount /</span> pageSize<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> changePage<span style="color: #009900;">&#40;</span>toIndex<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>toIndex <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">0</span> <span style="color: #339933;">&amp;&amp;</span> toIndex <span style="color: #339933;">&lt;=</span> <span style="color: #009900;">&#40;</span>pageCount <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                pageIndex <span style="color: #339933;">=</span> toIndex<span style="color: #339933;">;</span>
                updatePaging<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                updateIndicator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>opts.<span style="color: #660066;">onPageChange</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    opts.<span style="color: #660066;">onPageChange</span>.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span>pageIndex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> changePageSize<span style="color: #009900;">&#40;</span>toSize<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            pageSize <span style="color: #339933;">=</span> toSize<span style="color: #339933;">;</span>
            pageCount <span style="color: #339933;">=</span> getPageCount<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            updatePaging<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            updateIndicator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>opts.<span style="color: #660066;">onPageSizeChange</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                opts.<span style="color: #660066;">onPageSizeChange</span>.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span>pageSize<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> updateIndicator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>opts.<span style="color: #660066;">indicator</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            	opts.<span style="color: #660066;">indicator</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>pageIndex <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;/&quot;</span> <span style="color: #339933;">+</span> pageCount<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> updatePaging<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> start <span style="color: #339933;">=</span> pageIndex <span style="color: #339933;">*</span> pageSize<span style="color: #339933;">;</span>
            <span style="color: #003366; font-weight: bold;">var</span> end <span style="color: #339933;">=</span> start <span style="color: #339933;">+</span> pageSize<span style="color: #339933;">;</span>
            <span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
            <span style="color: #003366; font-weight: bold;">var</span> rows <span style="color: #339933;">=</span> getRows<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            rows.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">&gt;=</span> start <span style="color: #339933;">&amp;&amp;</span> i <span style="color: #339933;">&lt;</span> end<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    $<span style="color: #009900;">&#40;</span>rows<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
                    $<span style="color: #009900;">&#40;</span>rows<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                i<span style="color: #339933;">++;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span>
            changePage<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>moveTo<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> changePage<span style="color: #009900;">&#40;</span>moveTo <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
            getPageSize<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> pageSize<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
            getPageIndex<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> pageIndex<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>jQuery<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Usage:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> pager <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#testTable&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">tablePager</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    firstBtn<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.first&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// The element that pages to the first page</span>
    prevBtn<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.prev&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// The element that pages to the previous page</span>
    nextBtn<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.next&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// The element that pages to the next page</span>
    lastBtn<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.last&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// The element that pages to the last page</span>
    indicator<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.curpage&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// The input element that stores the current page (i.e. &quot;1/5&quot;)</span>
    sizeSelect<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.pagesize&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// The select element that indicates the current page size</span>
    pageSize<span style="color: #339933;">:</span> <span style="color: #CC0000;">5</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// The initial page size</span>
    onPageChange<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>newIndex<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>newIndex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// Page change callback</span>
    onPageSizeChange<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>newSize<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>newSize<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span> <span style="color: #006600; font-style: italic;">// Page size change callback</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
pager.<span style="color: #660066;">changePage</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Causes the page to change from outside the plugin</span>
<span style="color: #003366; font-weight: bold;">var</span> pageIndex <span style="color: #339933;">=</span> pager.<span style="color: #660066;">getPageIndex</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Returns the current page index</span>
<span style="color: #003366; font-weight: bold;">var</span> pageSize <span style="color: #339933;">=</span> pager.<span style="color: #660066;">getPageSize</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Returns the current page size</span></pre></div></div>

<p>And here&#8217;s some example markup for the pager elements:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;span class=&quot;first&quot;&gt;First&lt;/span&gt;&amp;nbsp;&amp;nbsp;
&lt;span class=&quot;prev&quot;&gt;Prev&lt;/span&gt;&amp;nbsp;&amp;nbsp;
&lt;span class=&quot;next&quot;&gt;Next&lt;/span&gt;&amp;nbsp;&amp;nbsp;
&lt;span class=&quot;last&quot;&gt;Last&lt;/span&gt;
&lt;br&gt;&lt;br&gt;
&lt;input type=&quot;text&quot; class=&quot;curpage&quot; /&gt;&amp;nbsp;&amp;nbsp;
&lt;select class=&quot;pagesize&quot;&gt;
    &lt;option value=&quot;5&quot;&gt;5&lt;/option&gt;
    &lt;option value=&quot;10&quot;&gt;10&lt;/option&gt;
    &lt;option value=&quot;20&quot;&gt;20&lt;/option&gt;
&lt;/select&gt;</pre></div></div>

<p>As you can see it&#8217;s really simple and flexible.  You can supply any elements you want to the pager.  If you don&#8217;t supply a first and last button elements for example then those will be ignored, if you don&#8217;t specify an indicator then that will be ignored too.  The most important thing is that your DOM stays intact, this allows you to continue to manipulate the &#8220;hidden&#8221; portions of the table (i.e. the stuff not on the current page) without having to access some crazy expando property that other pager plugins use to stash the un-shown portions of the table.</p>
<p>As always, I&#8217;d appreciate any feedback.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thegrubbsian.com/2009/06/05/jquery-plugin-tablepager/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>jQuery vs. the ASP.NET Update Panel Revisited &#8211; Event Delegation</title>
		<link>http://www.thegrubbsian.com/2008/12/05/jquery-vs-the-aspnet-update-panel-revisited-event-delegation/</link>
		<comments>http://www.thegrubbsian.com/2008/12/05/jquery-vs-the-aspnet-update-panel-revisited-event-delegation/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 21:17:46 +0000</pubDate>
		<dc:creator>JC Grubbs</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thegrubbsian.com/?p=107</guid>
		<description><![CDATA[Recently I was again struggling with the ASP.NET Update Panel killing my JavaScript interactions because it replaces the DOM elements it surrounds on every refresh.&#0160; My previous solution for this was simply to rebind those events after each Update Panel refresh was completed.&#0160; This works perfectly well, but it always seemed a little heavy handed [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was again struggling with the ASP.NET Update Panel killing my JavaScript interactions because it replaces the DOM elements it surrounds on every refresh.&#0160; My previous solution for this was simply to rebind those events after each Update Panel refresh was completed.&#0160; This works perfectly well, but it always seemed a little heavy handed to me.</p>
<p>So in digging into this issue a little more, I came upon a few posts that talked about using event delegation to solve this problem (thanks to everyone out there who wrote about delegation, cause you&#39;re smarter than I am).&#0160; The basic idea is that you attach events at a higher level in the DOM tree and use the DOM&#39;s event bubbling mechanism to catch them.&#0160; For example, let&#39;s say we have the following ASPX snippet:</p>
<p style="font-size: 12px; font-family: Courier;">&lt;div id=&quot;container&quot;&gt;<br />&#0160;&#0160;&#0160; &lt;ul&gt;<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &lt;asp:UpdatePanel&gt;<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &lt;li class=&quot;listItem&quot;&gt;Item One&lt;/li&gt;<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &lt;li class=&quot;listItem&quot;&gt;Item Two&lt;/li&gt;<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &lt;li class=&quot;listItem&quot;&gt;Item Three&lt;/li&gt;<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &lt;li class=&quot;listItem&quot;&gt;Item Four&lt;/li&gt;<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &lt;/asp:UpdatePanel&gt;<br />&#0160;&#0160;&#0160; &lt;/ul&gt;<br />&lt;/div&gt;</p>
<p>Now let&#39;s assume that you&#39;ve done this somewhere in JavaScript:</p>
<p style="font-size: 12px; font-family: Courier;">function bindLiEvents() {<br />&#0160;&#0160;&#0160; $(&quot;li.listItem&quot;).bind(&quot;click&quot;, function() { alert($(this).html()); });<br />}</p>
<p>When this JavaScript is executed jQuery loops over all the found elements and individually attaches an event handler to each.&#0160; So already there is an inherent performance gain to be had by not doing this looping.&#0160; Furthermore there is now the problem with the Update Panel.&#0160; If the user takes some action that causes the panel to refresh, then the four <span style="font-size: 12px; font-family: Courier;">&lt;li&gt;</span> elements are destroyed and recreated and unless I call <span style="font-size: 12px; font-family: Courier;">bindLiEvents</span> again after the refresh I loose this functionality.</p>
<p>Enter the event delegation concept.&#0160; Why not attach my handler to a DOM element that&#39;s outside the Update Panel &#8211; the <span style="font-size: 12px; font-family: Courier;">&lt;div&gt;</span> element in this case.&#0160; This may seem a bit counter intuitive, but if you&#39;re aware of how event bubbling works in the DOM you can see how this might work.</p>
<p>Event bubbling simply means that events at lower levels in the DOM tree are propagated to higher levels.&#0160; For example when an <span style="font-size: 12px; font-family: Courier;">&lt;li&gt;</span> is clicked in our example, the click event is also fired on the <span style="font-size: 12px; font-family: Courier;">&lt;ul&gt;</span> and the <span style="font-size: 12px; font-family: Courier;">&lt;div&gt;</span> and beyond.&#0160; We can use this behavior to our advantage in this instance because event bubbling is intrinsic to DOM elements &#8211; when new elements are added they automatically exhibit this behavior.</p>
<p>So now let&#39;s look at how we might attach an event to the <span style="font-size: 12px; font-family: Courier;">&lt;div&gt;</span> element:</p>
<p style="font-size: 12px; font-family: Courier;">function bindLiEvents() {<br />&#0160;&#0160;&#0160; $(&quot;#container&quot;).delegate(&quot;click&quot;, &quot;li.listItem&quot;, <br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; function() { alert($(this).html()); });<br />}</p>
<p>Don&#39;t worry about where the <span style="font-size: 12px; font-family: Courier;">delegate</span> method comes from &#8211; it&#39;s not native to jQuery but I&#39;ll get to that.&#0160; What&#39;s happening here is that I&#39;m binding a very generic event handler to the <span style="font-size: 12px; font-family: Courier;">&lt;div&gt;</span> element, and telling that handler to listen for click events on elements that match the &quot;li.listItem&quot; selector.&#0160; So now, when an event bubbles up from an <span style="font-size: 12px; font-family: Courier;">&lt;li&gt;</span> element the handler on the &lt;div&gt; fires, tests if the event originated on an <span style="font-size: 12px; font-family: Courier;">&lt;li&gt;</span> with a class of &quot;listItem&quot; and then calls the function callback.</p>
<p>There are advantages to using the approach.&#0160; First, event handlers are attached only once, and only at a single point which saves time when doing the initial bind.&#0160; Second, any new elements added to the Update Panel will automatically fire the delegated event handler &#8211; no rebind is required.</p>
<p>So if you want to try this out for yourself, here is a jQuery plugin for the delegate method:</p>
<p style="font-size: 10px; font-family: Courier;">(function ($) {<br />&#0160;&#0160;&#0160; var bubbledEvents = [&#39;click&#39;, &#39;dblclick&#39;, &#39;mousedown&#39;, &#39;mouseup&#39;, &#39;mousemove&#39;, <br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#39;mouseover&#39;, &#39;mouseout&#39;, &#39;keydown&#39;, &#39;keypress&#39;, &#39;keyup&#39;];<br />&#0160;&#0160;&#0160; var allowedEvents = { };<br />&#0160;&#0160;&#0160; $.each(bubbledEvents, function(idx,event) { allowedEvents[event] = true; });<br />&#0160;&#0160;&#0160; $.fn.extend({<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; delegate: function (event, selector, func) {<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; return $(this).each(function () {<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; if (allowedEvents[event])<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; $(this).bind(event, function (e) {<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; var el = $(e.target), result = false;<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; while (!$(el).is(&quot;body&quot;)) {<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; if ($(el).is(selector)) {<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; result = func.apply($(el)[0], [e]);<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; if (result === false) { e.preventDefault(); }<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; return;<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; }<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; el = $(el).parent();<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; }<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; });<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; });<br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; },<br />&#0160;&#0160;&#0160; &#0160;&#0160;<br />
&#0160; undelegate: function (event) { return $(this).each(function () { <br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; $(this).unbind(event); }); }<br />&#0160;&#0160;&#0160; });<br />})(jQuery);</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thegrubbsian.com/2008/12/05/jquery-vs-the-aspnet-update-panel-revisited-event-delegation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Use jQuery.post to submit to ASP.NET MVC Actions</title>
		<link>http://www.thegrubbsian.com/2008/11/26/use-jquerypost-to-submit-to-aspnet-mvc-actions/</link>
		<comments>http://www.thegrubbsian.com/2008/11/26/use-jquerypost-to-submit-to-aspnet-mvc-actions/#comments</comments>
		<pubDate>Thu, 27 Nov 2008 03:02:40 +0000</pubDate>
		<dc:creator>JC Grubbs</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thegrubbsian.com/?p=109</guid>
		<description><![CDATA[Recently, Microsoft announced that jQuery will be shipping with future versions of Visual Studio. &#0160;In fact, today the ASP.NET MVC bits already ship with jQuery. &#0160;ASP.NET MVC is extremely friendly with jQuery.&#0160; One of the things that ASP.NET MVC gives you over web forms is an easy way to expose actions to the client. &#0160;Here&#39;s [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, Microsoft announced that jQuery will be shipping with future versions of Visual Studio. &#0160;In fact, today the ASP.NET MVC bits already ship with jQuery. &#0160;ASP.NET MVC is extremely friendly with jQuery.&#0160;</p>
<p>One of the things that ASP.NET MVC gives you over web forms is an easy way to expose actions to the client. &#0160;Here&#39;s where AJAX using jQuery really shines. &#0160;In the past if you wanted to initiate some server side action using JavaScript, you&#39;d need to expose a web service of some kind and then call into your server from there. &#0160;With ASP.NET MVC you can simply submit a post to an action via a URL and you&#39;re off.</p>
<p>For example, I might have the following action called &#39;DoSomething&#39; on my &#39;Thing&#39; controller:</p>
<p><span style="font-size: 12px; font-family: Courier;">public ActionResult DoSomething(int thingId, string thingName,&#0160;</span><span><span style="white-space: pre; font-size: 12px; font-family: Courier;"></span><span style="font-size: 12px; font-family: Courier;"><br /></span></span>&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; <span><span style="font-size: 12px; font-family: Courier;">DateTime thingDate) {</span></span><span class="Apple-tab-span" style="white-space: pre;"></span><span style="font-size: 12px; font-family: Courier;"></span></p>
<p>&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; <span style="font-size: 12px; font-family: Courier;">var db = new ThingEntities();</span><span class="Apple-tab-span" style="white-space: pre;"><span style="font-size: 12px; font-family: Courier;"><br /></span></span>&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; <span style="font-size: 12px; font-family: Courier;">var thing = (from Thing t in db.Things</span><br />&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160;&#0160;&#0160; <span><span style="font-size: 12px; font-family: Courier;">where t.ID == thingId, </span><span style="white-space: pre; font-size: 12px; font-family: Courier;"><br /></span></span>&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160; &#0160;&#0160;&#0160;&#0160;&#0160; <span><span style="white-space: pre; font-size: 12px; font-family: Courier;"></span><span style="font-size: 12px; font-family: Courier;">select t).First&lt;Thing&gt;();</span></span><span class="Apple-tab-span" style="white-space: pre;"><span style="font-size: 12px; font-family: Courier;"></p>
<p></span></span>&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; <span style="font-size: 12px; font-family: Courier;">thing.Name = thingName;</span><span class="Apple-tab-span" style="white-space: pre;"><span style="font-size: 12px; font-family: Courier;"></span></span><span style="font-size: 12px; font-family: Courier;"><br /></span>&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; <span style="font-size: 12px; font-family: Courier;">thing.ThingDate = thingDate;</span><span class="Apple-tab-span" style="white-space: pre;"><span style="font-size: 12px; font-family: Courier;"></p>
<p></span></span>&#0160;&#0160;&#0160; &#0160;&#0160;&#0160; <span style="font-size: 12px; font-family: Courier;">db.SaveChanges(true);</span></p>
<p><span class="Apple-tab-span" style="white-space: pre;"><span style="font-size: 12px; font-family: Courier;">	</span></span><span style="font-size: 12px; font-family: Courier;">return Content(&quot;true&quot;);<br />}</span></p>
<p>Calling this method from JavaScript becomes almost trivial using the jQuery.post method:</p>
<p><span style="font-size: 12px; font-family: Courier;">$.post(&quot;/Thing/DoSomething&quot;,&#0160;{ thingId: 7, thingName: &#39;New Thing&#39;, thingDate: &#39;1/1/2008&#39; }, function(data) { alert(data); });</span></p>
<p>So the post method has three parameters:</p>
</p>
<ol>
<li>The URL of the action to post to.&#0160;</li>
<li><span>An object comprising the data to send with the post.</span>&#0160;</li>
<li><span>A callback method which fires when the request returns.&#0160;</span></li>
</ol>
</p>
<p>It&#39;s as simple as that. &#0160;So now making calls back to your server from JavaScript is as easy as writing a controller action that takes simple types as parameters. &#0160;There are several different jQuery AJAX methods to chose from and obviously some more advanced things that you can do, but as you can see the basics are pretty simple.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thegrubbsian.com/2008/11/26/use-jquerypost-to-submit-to-aspnet-mvc-actions/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Optimizing jQuery Selector Performance</title>
		<link>http://www.thegrubbsian.com/2008/10/20/optimizing-jquery-selector-performance/</link>
		<comments>http://www.thegrubbsian.com/2008/10/20/optimizing-jquery-selector-performance/#comments</comments>
		<pubDate>Mon, 20 Oct 2008 19:12:00 +0000</pubDate>
		<dc:creator>JC Grubbs</dc:creator>
				<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thegrubbsian.com/?p=112</guid>
		<description><![CDATA[Despite the fact that the capacity of modern JavaScript engines is expanding rapidly, I found myself recently fighting with JS performance on a very large web page.&#0160; This was an ASP.NET application with one very complex page, very large DOM tree, lots of elements and lots of JS interactions. As the page became larger and [...]]]></description>
			<content:encoded><![CDATA[<p>Despite the fact that the capacity of modern JavaScript engines is expanding rapidly, I found myself recently fighting with JS performance on a very large web page.&#0160; This was an ASP.NET application with one very complex page, very large DOM tree, lots of elements and lots of JS interactions.</p>
<p>As the page became larger and more data was pumped into the DOM the time it took to locate an element or set of elements in the DOM began to lengthen. &#0160;My attempts to locate any solid information in Google on improving this situation was fruitless. &#0160;So, I starting digging through the jQuery source code to see how the selector engine worked&#8230;this was also useless. &#0160;Clearly the skills of the JS Ninjas that created jQuery are far superior to mine.</p>
<p>So, then it just became a thought experiment. &#0160;Knowing that jQuery uses a context sensitive combination of XPath, native browser API&#39;s, and some fancy string parsing for CSS3 selectors there are a few optimizations that come to mind.</p>
<p><span style="font-weight: bold;">Qualify your selector strings when searching by class.<br /><span style="font-weight: normal;">Because one way that jQuery can find DOM elements is XPath style searching, it&#39;s important to qualify your selector strings. &#0160;Turning <span style="font-family: Courier;">$(&quot;.some-class&quot;)</span> into <span style="font-family: Courier;">$(&quot;div.container &gt; div.head &gt; div.some-class&quot;) </span>can really make a difference. &#0160;This is especially true when the branches of your DOM tree become very deep.</span></span></p>
<p><span style="font-weight: bold;">Don&#39;t Qualify your selector when searching by id.</span><br />Because searching by id uses the browsers native getElementById method (which is very fast) it doesn&#39;t make sense to overly qualify a selector string that&#39;s looking for a unique element. &#0160;So <span style="font-family: Courier;">$(&quot;div#someid&quot;)</span> is actually slower than <span style="font-family: Courier;">$(&quot;#someid&quot;)</span>.</p>
<p><span style="font-weight: bold;">Select By Element(s)</span><br />Don&#39;t forget that your argument to <span style="font-family: Courier;">$()</span> can also be a reference to an element directly. &#0160;One of the techniques that I&#39;ve used to get over huge numbers of DOM elements is to do some pre-caching of element objects before doing any manipulation. &#0160;For example I might keep an array in JavaScript of all of the elements of a particular group. &#0160;</p>
<p>Say you have a bunch of textboxes on a page and they&#39;re scattered all around in deeply nested trees. &#0160;Half of the textboxes belong to group A and the other group B. &#0160;I might set up two JavaScript arrays (elementsAarray, and elementsBarray) and before the page is rendered I&#39;ll go and grab all of those elements and plop them into my arrays. &#0160;This way I can simply grab that array of elements in group A with <span style="font-family: Courier;">$(elementsAarray)</span> which completely cuts out the need for DOM traversal.</p>
<p>- &#8211; - &#8211; -</p>
<p>There are likely other ways to tweak your selectors and I&#39;d love to hear how other people have tackled this issue. &#0160;Here&#39;s hoping that JavaScript engines get so fast that we don&#39;t have to care!</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thegrubbsian.com/2008/10/20/optimizing-jquery-selector-performance/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>jQuery Plugin: wrapList</title>
		<link>http://www.thegrubbsian.com/2008/10/02/jquery-plugin-wraplist/</link>
		<comments>http://www.thegrubbsian.com/2008/10/02/jquery-plugin-wraplist/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 01:01:25 +0000</pubDate>
		<dc:creator>JC Grubbs</dc:creator>
				<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thegrubbsian.com/?p=114</guid>
		<description><![CDATA[Ok, so now I&#39;m on a roll with the jQuery plugins.&#0160; This time it&#39;s a simple plugin that takes a single unordered list and segments it at predefined intervals into additional lists.&#0160; Each list is then floated to the left making it appear to wrap content to the next &#34;column&#34;.&#0160; The plugin is extremely simple [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, so now I&#39;m on a roll with the jQuery plugins.&#0160; This time it&#39;s a simple plugin that takes a single unordered list and segments it at predefined intervals into additional lists.&#0160; Each list is then floated to the left making it appear to wrap content to the next &quot;column&quot;.&#0160; The plugin is extremely simple to use but works really well on all sorts of content.</p>
<p>Download: <a href="http://plugins.jquery.com/files/jQuery.wrapList.zip">jQuery.wrapList.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thegrubbsian.com/2008/10/02/jquery-plugin-wraplist/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>jQuery Plugin: AnchorCheck</title>
		<link>http://www.thegrubbsian.com/2008/10/01/jquery-plugin-anchorcheck/</link>
		<comments>http://www.thegrubbsian.com/2008/10/01/jquery-plugin-anchorcheck/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 21:27:00 +0000</pubDate>
		<dc:creator>JC Grubbs</dc:creator>
				<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thegrubbsian.com/?p=115</guid>
		<description><![CDATA[I recently needed a jQuery plugin to do checkbox replacement for a client.&#0160; Unfortunately, the plugins that were available really didn&#39;t fit our needs.&#0160; In this particular instance we were not concerned with being unobtrsive so we didn&#39;t need to render out an actual checkbox and the replace it with another tag.&#0160; Instead, we decided [...]]]></description>
			<content:encoded><![CDATA[<p>I recently needed a jQuery plugin to do checkbox replacement for a client.&#0160; Unfortunately, the plugins that were available really didn&#39;t fit our needs.&#0160; In this particular instance we were not concerned with being unobtrsive so we didn&#39;t need to render out an actual checkbox and the replace it with another tag.&#0160; Instead, we decided to go with plain old anchor tags.&#0160; </p>
<p>So I whipped up my very first jQuery plugin to solve the problem.&#0160; And with the recent announcement that Microsoft will be shipping jQuery with ASP.NET it seemed all the more appropriate.&#0160; In another post I&#39;m going to go through the steps needed to create a jQuery plugin but for now, here it is.</p>
<p>Download: <a href="http://plugins.jquery.com/files/jQuery.anchorCheck1.3.zip">jQuery.anchorCheck1.3.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thegrubbsian.com/2008/10/01/jquery-plugin-anchorcheck/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>jQuery Event Binding vs. ASP.NET AJAX UpdatePanel</title>
		<link>http://www.thegrubbsian.com/2007/10/09/jquery-event-binding-vs-aspnet-ajax-updatepanel/</link>
		<comments>http://www.thegrubbsian.com/2007/10/09/jquery-event-binding-vs-aspnet-ajax-updatepanel/#comments</comments>
		<pubDate>Tue, 09 Oct 2007 21:05:45 +0000</pubDate>
		<dc:creator>JC Grubbs</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thegrubbsian.com/?p=125</guid>
		<description><![CDATA[UPDATE (12/5/2008): An alternative solution to this issue is found in a more recent post here:http://www.thegrubbsian.com/2008/12/jquery-vs-the-aspnet-update-panel-revisited.html While this is a simple topic, it is one that tripped me up and since the documentation for ASP.NET AJAX is pretty poor, I thought I&#39;d share how I worked it out. One of the great advantages of using [...]]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE (12/5/2008): An alternative solution to this issue is found in a more recent post here:<br /><a href="http://www.thegrubbsian.com/2008/12/jquery-vs-the-aspnet-update-panel-revisited.html">http://www.thegrubbsian.com/2008/12/jquery-vs-the-aspnet-update-panel-revisited.html</a></strong></p>
<p>While this is a simple topic, it is one that tripped me up and since the documentation for ASP.NET AJAX is pretty poor, I thought I&#39;d share how I worked it out.
</p>
<p>One of the great advantages of using a JavaScript library like jQuery is easy event binding.&#0160; In jQuery you can bind an event in a cross-browser compliant manner with very little code:</p>
<p><code>$(&quot;someElement&quot;).click(function() { alert(&#39;I&#39;m Clicked!&#39;);});</code>
</p>
<p>Another convenience of modern JS libraries is a loaded event, basically detecting when the browser has finished receiving and parsing the DOM from the server.&#0160; For example, in jQuery we can test for DOM completion thusly:</p>
<p><code>$(window).ready(function() { ... });</code>
</p>
<p>Anything within the function here will be executed only after the entire DOM has been downloaded and parsed by the rendering engine.</p>
<p>Now, when you wrap parts of markup with an ASP.NET AJAX UpdatePanel you create a scenario in which a certain portion of the DOM will be reloaded asynchronously while other parts are not.&#0160; Even though you will often be merely updating nodes within this area of the DOM, the UpdatePanel is heavy handed&#8230;it basically just wipes out whatever was in there and replaces it fresh from the server.&#0160; When this happens all your fancy events bound to those elements are blown away.&#0160; Thanks UpdatePanel!</p>
<p>Happily, there is a solution that works with any library, not just jQuery.&#0160; You will need to abstract your jQuery event bindings away from their handlers into new JS functions.&#0160; For example:</p>
<p><code>$(window).ready(function() {<br />&#0160; &#0160; $(&quot;#someElement&quot;).click(function() {<br />&#0160; &#0160;&#0160; &#0160;&#0160; alert(&#39;I&#39;ve been clicked!&#39;);<br />&#0160; &#0160; });<br />});</code>
</p>
<p>would become:</p>
<p><code>$(window).ready(function() {<br />&#0160; &#0160; $(&quot;#someElement&quot;).click(function() { SomeElementClicked() });<br />});</p>
<p>function SomeElementClicked() {<br />&#0160; &#0160; alert(&#39;I&#39;ve been clicked!&#39;);<br />}</code>
</p>
<p>Next, we need to replace the jQuery &quot;ready&quot; block with a function that automatically gets called by the ASP.NET AJAX client framework whenever a postback occurs (sync or async).&#0160; So our script would now be:</p>
<p><code>Sys.Application.add_load(WireEvents);</p>
<p>function WireEvents() {<br />&#0160; &#0160; $(&quot;#someElement&quot;).click(function() { SomeElementClicked() });<br />}</p>
<p></code></p>
<p><code>function SomeElementClicked() {<br />&#0160; &#0160; alert(&#39;I&#39;ve been clicked!&#39;);<br />}</code></p>
<p>Now you can continue to use jQuery to bind events (and skip using the convoluted ASP.NET AJAX way) and use the UpdatePanel to surround jQuery bound DOM elements.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thegrubbsian.com/2007/10/09/jquery-event-binding-vs-aspnet-ajax-updatepanel/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
