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> '); } else { $(this).after('<i class="icon-expand"></i> '); } $(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…
Image may be NSFW.
Clik here to view.
… with Font Awesome icons…
Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.
Clik here to view.
