Getting Awesome Category Icons in Data Views – A jQuery Variation

In a Twitter exchange with Paul Withers regarding his great post on replacing category expand/collapse icons in a Data View with Font Awesome icons, he mentioned that it would be interesting to see a jQuery alternative. Since I’m working on improving my proficiency with jQuery, I thought it would be an interesting challenge. In this post, I’ll show how I implemented it and describe the main challenge that I faced.

This code will use jQuery to replace the expand/collapse icons with related font awesome icons.

As in Paul’s post, this code depends on the category columns having a class of catColumn (although it can be done without it).

The expand and collapse icons are within an <h4> tag and an <a> link. The image source name will be collapse.gif or expand.gif, so this code reads the source to determine which type of image to replace. Since Font Awesome uses <i> tags, it adds the new icon tag and then removes the <img> tag.

This code has been placed in a client-side JavaScript library so I can call it from two different places.

Note: The application I’m testing on has Font Awesome v3, so the icon tags look different than the one in Paul’s post, where he’s using version 4.

// Replace the standard Data View expand/collapse icons with font-awesome icons (v3) using jQuery
function replaceCategoryIcons() {
  $('.catColumn a img').each(function(){
    var src=$(this).attr('src');
    if (src.indexOf('collapse') > -1) {
      $(this).after('<i class="icon-collapse"></i>&nbsp');
    } else {
      $(this).after('<i class="icon-expand"></i>&nbsp');
    }
    $(this).remove();
  });
}

This code was pretty straightforward to create; the real trick is firing it as the data view is refreshed when categories are expanded and collapsed. There’s no pure DOM event that I’m aware of that I can listen to with jQuery in order to re-execute after each partial refresh. jQuery cannot subscribe to a stream that’s published by dojo, so I can’t use code similar to Paul’s post.

I tried to use event delegation (check out Marky’s great explanation here) on the click event of the images (since that’s what triggers the update). This kind of worked, but the problem was that it replaced the icons and then, when the page refreshed, the old icons were right back in place.

So, it all came back to Tommy Valand’s great post about hijacking partial refresh events to solve this problem.

I trimmed down original code and updated the onComplete event to trigger my jQuery function to replace the icons (line 18).

function hijackPartialRefresh() {
  // Hijack the partial refresh
  XSP._inheritedPartialRefresh = XSP._partialRefresh;
  XSP._partialRefresh = function( method, form, refreshId, options ){
    // Publish init
    dojo.publish( 'partialrefresh-init', [ method, form, refreshId, options ]);
    this._inheritedPartialRefresh( method, form, refreshId, options );
  }

  // Publish start, complete and error states
   dojo.subscribe( 'partialrefresh-init', function( method, form, refreshId, options ){
    if( options ){ // Store original event handlers
      var eventOnComplete = options.onComplete;
    }

    options = options || {};
    options.onComplete = function(){
      replaceCategoryIcons();
      if( eventOnComplete ){
        if( typeof eventOnComplete === 'string' ){
          eval( eventOnComplete );
        } else {
          eventOnComplete();
        }
      }
    };
  });
}

Now, to run the code both when the page loads and then again on each partial refresh, I added this code to the onClientLoad event of the page:

// Replace the category icons with font-awesome icons
replaceCategoryIcons();

// Set up ongoing replacement of icons
hijackPartialRefresh();

Now, it replaces the default icons…

DataViewExpandCollapseIcons_Before

… with Font Awesome icons…

DataViewExpandCollapseIcons_After

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: