<?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>Jetpack Flight Log &#187; act_as_list</title>
	<atom:link href="http://jetpackweb.com/blog/tags/act_as_list/feed/" rel="self" type="application/rss+xml" />
	<link>http://jetpackweb.com/blog</link>
	<description>Rock{et}ing the interweb</description>
	<lastBuildDate>Wed, 19 May 2010 22:21:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>jQuery Sortables: Getting DOM element position for an efficient ajax update in Rails</title>
		<link>http://jetpackweb.com/blog/2009/09/02/jquery-sortables-getting-element-position-for-an-efficient-ajax-update-in-rails/</link>
		<comments>http://jetpackweb.com/blog/2009/09/02/jquery-sortables-getting-element-position-for-an-efficient-ajax-update-in-rails/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 02:23:47 +0000</pubDate>
		<dc:creator>Brian Racer</dc:creator>
				<category><![CDATA[jquery]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[act_as_list]]></category>
		<category><![CDATA[haml]]></category>

		<guid isPermaLink="false">http://jetpackweb.com/blog/?p=308</guid>
		<description><![CDATA[The jQuery UI library has some excellent interaction functionality, especially &#8216;sortables&#8217; to make cool things like rearrangeable lists. Although there are lots of tutorials on sortable lists, one problem I have with them is the amount of database queries a single update can generate. They generally make use of the Sortable.serialize method, send *all* the [...]]]></description>
			<content:encoded><![CDATA[<p>The jQuery UI library has some excellent interaction functionality, especially &#8216;sortables&#8217; to make cool things like rearrangeable lists. Although there are lots of tutorials on sortable lists, one problem I have with them is the amount of database queries a single update can generate. They generally make use of the <a href="http://jqueryui.com/demos/sortable/#method-serialize" target="_blank">Sortable.serialize</a> method, send *all* the elements back to the server, and update each element with something like ActiveRecord&#8217;s <a href="http://apidock.com/rails/ActiveRecord/Base/update_all/class" target="_blank">update_all</a>(which can be smart), or worse, separate SQL queries for each list element.</p>
<p>What we can do instead is just send the id and position of the single element that has moved, and use <b>acts_as_list</b> to adjust the positions in the database. Lets say we have an <i>unordered list</i> of Video models <i>(I am using <a href="http://haml-lang.com" target="_blank">HAML</a> in this example)</i>:</p>

<div class="wp_syntax"><div class="code"><pre class="haml" style="font-family: Monaco, monospace;">%h3= &quot;Videos&quot;
%ul(class=&quot;sortable&quot;)
  - @videos.each do |video|
    %li{ :id =&gt; &quot;video_#{video.id}&quot; }= video.title</pre></div></div>

<p>That might output something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family: Monaco, monospace;">&lt;h3&gt;Videos&lt;/h3&gt;
&lt;ul class='sortable'&gt;
  &lt;li id='video_5'&gt;Batman Begins&lt;/li&gt;
  &lt;li id='video_6'&gt;Ghostbusters&lt;/li&gt;
  &lt;li id='video_7'&gt;Indiana Jones and the Temple of Doom&lt;/li&gt;
 &lt;/ul&gt;</pre></div></div>

<p>We have the video&#8217;s database id&#8217;s in each of the element id&#8217;s, and we have given the <b>ul</b> element the <i>sortable</i> class so we can select it later. Now lets select that <b>ul</b> element and make it &#8216;sortable&#8217;:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family: Monaco, monospace;">$<span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
  $<span class="br0">&#40;</span><span class="st0">'.sortable'</span><span class="br0">&#41;</span>.<span class="me1">sortable</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>With that we can now drag each list item around. Now comes the important part. When we finish dragging a single list element we will send a single ajax request to the server that contains the numeric value of the element&#8217;s id, and it&#8217;s position in the list:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family: Monaco, monospace;">  $<span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    $<span class="br0">&#40;</span><span class="st0">'.sortable'</span><span class="br0">&#41;</span>.<span class="me1">sortable</span><span class="br0">&#40;</span><span class="br0">&#123;</span>
      <span class="kw3">stop</span><span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>event<span class="sy0">,</span> ui<span class="br0">&#41;</span> <span class="br0">&#123;</span>
        $<span class="br0">&#40;</span>ui.<span class="kw1">item</span><span class="br0">&#41;</span>.<span class="me1">effect</span><span class="br0">&#40;</span><span class="st0">&quot;highlight&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw2">var</span> video_id <span class="sy0">=</span> $<span class="br0">&#40;</span>ui.<span class="kw1">item</span><span class="br0">&#41;</span>.<span class="me1">attr</span><span class="br0">&#40;</span><span class="st0">'id'</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="co2">/[^\d]+/g</span><span class="sy0">,</span> <span class="st0">''</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
        <span class="kw2">var</span> position <span class="sy0">=</span> ui.<span class="kw1">item</span>.<span class="me1">prevAll</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">length</span><span class="sy0">;</span>
        $.<span class="me1">post</span><span class="br0">&#40;</span><span class="st0">'/videos/update_position'</span><span class="sy0">,</span> <span class="br0">&#123;</span>
          <span class="st0">'video_id'</span><span class="sy0">:</span> video_id<span class="sy0">,</span>
          <span class="st0">'position'</span><span class="sy0">:</span> position
         <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
         $<span class="br0">&#40;</span>ui.<span class="kw1">item</span><span class="br0">&#41;</span>.<span class="me1">effect</span><span class="br0">&#40;</span><span class="st0">&quot;highlight&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="br0">&#125;</span>
    <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span><span class="br0">&#41;</span></pre></div></div>

<p>Couple of notes:</p>
<p><b>ui.item</b> is the DOM element we are dragging</p>
<p><b>$(ui.item).attr(&#8216;id&#8217;).replace(/[^\d+]+/g, &#8221;))</b> is pulling out the list item&#8217;s DOM id and removing anything that isn&#8217;t numeric, so we are left with the model&#8217;s ID</p>
<p><b>ui.item.prevAll().length</b> is what gives us the list item&#8217;s position in relation to it&#8217;s parent <b>ul</b></p>
<p>Now our controller action can be as simple as:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco, monospace;">Video.<span class="me1">find</span><span class="br0">&#40;</span>params<span class="br0">&#91;</span><span class="re3">:video_id</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">insert_at</span><span class="br0">&#40;</span>params<span class="br0">&#91;</span><span class="re3">:position</span><span class="br0">&#93;</span><span class="br0">&#41;</span></pre></div></div>

<p>Again this requires <b>acts_as_list</b>.  I believe this should never do more that 4 queries: One to find the model, one to update it&#8217;s position, and possibly two more to shift what was above and below it previously. Hopefully this saves you some SQL queries on larger lists.</p>
]]></content:encoded>
			<wfw:commentRss>http://jetpackweb.com/blog/2009/09/02/jquery-sortables-getting-element-position-for-an-efficient-ajax-update-in-rails/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
