Bringing (Re)Order with AJAX

One very important aspect to the usability of SASS::CMS is giving the user the ability to easily set the order of certain items (such as menu items or articles in a newsletter) appear on the site. I felt the best way to accomplish this was to use AJAX to make a drag and drop sortable list.  I started with an example by Jordan Boesch at Boe Design. The example was exactly what I wanted, but I needed to translate it to Catalyst.


I wasted a bit of time by not really understanding what I was trying to do. One way SASS::CMS uses this feature is allowing a user to set the order that articles appear in the finalized version. This is a little complicated because the articles should be able to exist in in multiple newsletters, but if an article is reused it might need to be in a different spot in the ordering. So I have three tables in the database articles and newsletters which have a many-to-many relationship with newsletter_articles. The newsletter_articles table has three columns: article_id, newsletter_id and ordering.

This is using an older version of the prototype.js - version 1.5.0_rc2. I hope one day soon, I'll figure out how to make it work with the latest version.

In my <head> tag I have:



[% Catalyst.uri_for('/static/js/prototype.js') %]
[% Catalyst.uri_for('/static/js/scriptaculous.js') %]
[% Catalyst.uri_for('/static/css/reorder.css') %]

<script type="text/javascript">
function updateOrder()
  {
          var params = {
                  method : 'post',
                  parameters : Sortable.serialize('itemlist'),
                  onLoading: function(){$('msg').show()},
                  onLoaded: function(){$('msg').hide()}
            };

          [%# Since SASS::CMS uses this method for different parts of the site. We take a value #%]
          [%# that is stashed in the controller to set  appropriate function #%]
          [% IF newsletter_order == '1' %]
              new Ajax.Request('/admin/newsletters/reorder/[% newsletter.id %]', params);
          [% ELSIF reorder == '1' %]
              new Ajax.Request('/admin/menus/reorder', params);
          [% END %]
  }
</script>



You can see the CSS at http://sass-cms.net/static/css/reorder.css

Then I put this in the template for the page:



<div>
    Click and drag articles to reorder them:
</div>
<div id="msg" style="display:none">

      Updating...

</div>

<div id="itemlist" class="list" style="width: 250px;">
     
[% FOREACH article IN articles -%]
    <div class="item" id="item_[% article.id %]">
        <div class="remove">
            <a href="/admin/newsletters/remove_article/[% article.id %]/[% newsletter.id %]" title="Remove Article">
            <img src="/images/icons/delete.png" border="0" alt="Remove Article" />
            </a>
        </div>
        [% article.title %]
    </div>
[% END -%]
</div>

<script type="text/javascript">
    Sortable.create('itemlist', { onUpdate: updateOrder, treeTag: 'div', tag: 'div' });
</script>



This sends the following to the reorder function:

parameters       => { _ => "", "itemlist[]" => [1, 2, 4, 3] },

The array of parameters represents the article's id values that are called by the id="item_[% article.id %]"

So what we have to do in our reorder function is search for an entry in our newsletter_articles join table for the newsletter id that we are working on and for each article id in the order from the "itemlist[]" parameters. Once we have that in our result set, we iterate through the results' value for ordering and update them to reflect the new ordering.


 

package MyApp::Controller::Admin::Newsletter;

sub reorder : Local {
    my ($self, $c, $newsletter_id ) = @_;
   
    my $sort = 0;
   
    my $articles = $c->request->body_params->{"itemlist[]"};

    foreach my $article ( ref $articles ? @$articles : $articles ) {
        my $ordering = $c->model('MyAppDB::ArticleNewsletter')->find(
                                    {
                                    article_id => $article,
                                    newsletter_id => $newsletter_id
                                    }
        );

        ++$sort;
        $ordering->update({ordering => $sort});

    }
   
    $c->response->body('Matched YAY');

}


 


Posted by jay On: Monday April, 2008 11:08

Comments

Post Comment

Name
Email
Comment
 
Validation Key Image
Key