Mura CMS Full Day Training Course on April 21, 2010

How would you like to spend a full day with the folks who created Mura CMS from the ground up? Are you in or around the Minneapolis, Minnesota region ... and if not, can you get there by April 21, 2010?

Well, Team Mura recently announced they would be offering an in-depth, full-day "Programmers Guide to Mura CMS" on Wednesday, April 21st, 2010. This is technically a "cf.Objective() 2010 Pre-Conference" event, however, you don't have to attend the full conference to take advantage of this great opportunity.

Here are a few of the topics that will be covered:

  • Programmatically working with content in Mura CMS
  • Working with Mura CMS objects
  • Understanding the Mura CMS event model
  • Integrating Existing or 3rd Party Applications
  • Building Mura CMS Plugins
  • Extending and customizing Mura CMS while staying on the upgrade path

This full day course will be limited to the first 20 students and costs only $500. Considering the number of Team Mura developers that will be on hand, you probably won't be able to find a better student to instructor ratio. Oh, and for what it's worth, I'll be there too!

Before you say no to this awesome deal, I ask you to take something else into consideration. Have you ever attended a training event only to go back to your office, sit at your desk and not truly applied the newly learned knowledge? If you are a web site developer and have either looked at, used Mura CMS, or are even a seasoned Mura CMS developer and want to build sites more efficiently while allowing your clients the ability to manage their own content ... then you will most definitely be able to bring what you've learned back to your office and apply it to your job the very next day. Yes, I mean that if you attend on Wednesday, by Thursday you will be more productive, period.

Again, only the first 20 students will be accepted, so register now before it's too late!

Using jQuery to Pass an Index Value to a Shadowbox.js Gallery

I ran into a bit of a hair-pulling incident recently and I really couldn't find any help on the web with this one. So I thought I'd share my frustration and the solution I came up with in case anyone else runs into a similar problem ... or heck, maybe you've got a better solution for me. In short, I needed to be able to pass an index value to Shadowbox.js when a gallery was launched so that it would begin at the desired position. However, I personally find it more interesting to understand the evoution of the problem and the eventual solution. If you're not like me, feel free to jump down to the jQuery and HTML code below.

The Problem Challenge

Well, this all started out when one of my clients wanted one of those fancy-dancy "hover-over-a-group-of-thumbnails-and-swap-a-medium-sized-image" thing-a-ma-bobs. Trust me, this was not the challenge ... using a few lines of jQuery and fancy-dancy-be-done.

Then, after looking things over a bit, the client wanted to be able to click on the thumbnail and open a modal window of the original, much larger, image. Again, no worries ... using a bit of Shadowbox.js magic, and client-be-happy.

Finally, after reviewing my jQuery/Shadowbox/programming magic, the client was happy ... but they wanted one more thing ... to be able to click on the medium-sized image and have it launch a modal window of the original, much larger, image too. So, after a little extra thought and tweaking around, I got it working ... well, sort of.

Here's the Deal

Everything worked just fine except for the fact that if I enabled the 'continuous' attribute so that people could click "Next" and "Previous" links, something odd occurred.

If I clicked a thumbnail, the Shadowbox opened and did its thing as expected. If there were four (4) image thumbnails, then when the modal window opened, the "Next" and "Previous" links would cycle through four (4) images. But when I clicked the medium-sized image, the larger version of the image would appear twice in the modal window for a total of five (5) images.

Anyway, I realized fairly quickly that by default, Shadowbox creates a cached array of things such as all links with a 'rel' attribute of 'shadowbox' when the page loads. You can easily override this feature in the Shadowbox init() method by setting the 'skipSetup' attribute to true. But that's not what I really needed, or wanted, to do. I already had the thumbnails working and just wanted to get the 'Medium' sized image to also open the Shadowbox.

The My Solution

Ultimately, I needed a way to keep track of the index of each Shadowbox link element so that I could use it when calling a Shadowbox function I hadn't used before called "Shadowbox.open()." I knew there just had to be a way of passing the index value to Shadowbox so that way when the modal window would open, it would just cue up to the cached index in Shadowbox.

So I created a custom attribute for the "a" link of the thumbnail images called "idx" and since I was already outputting the thumbnails from a query, this was pretty easy to do. However, since I was using a ColdFusion loop to output an array of the images, I couldn't just use the index value of the loop since ColdFusion arrays start at 1 while just about every other programming language, including JavaScript, have their arrays start at zero (0). So for you ColdFusion peeps, just remember you'll want to add your own "counter" variable that starts at zero and then increment it at the end of each iteration of the loop.

Once I had an attribute I could access using jQuery, I knew I was in business. The next thing I needed to find out was how to pass this index value to Shadowbox. Again, nothing on the web helped me out here. I did stumble across someone's post in the Shadowbox forum about how they modified the source code to accommodate something like this, but I chose not to go that route. In addition, this was a site using Mura CMS and I really didn't want to make any alterations to any included third-party code if I really didn't have too.

After studying the Shadowbox source code for a bit, I found this line of code in the Shadowbox.open() method (around line 2122):


// is it a link?
if(isLink(obj)){
    if(typeof obj.shadowboxCacheKey == 'undefined' || typeof cache[obj.shadowboxCacheKey] == 'undefined'){
        // link element that hasn't been set up before
        // create an object on-the-fly
        obj = this.buildCacheObj(obj, opts);
    }else{
        // link element that has been set up before, get from cache
        obj = cache[obj.shadowboxCacheKey];
    }
}

Notice the "shadowboxCacheKey" bit? Bingo! Now I knew all I needed to do was tweak my jQuery code to add this sweet little attribute to the link and then call the Shadowbox.open() method along with some options to tell Shadowbox which gallery I wanted to use and at what index to begin! Can you tell I was a little excited?

So instead of continuing to bore the crap out of you, I'll just go ahead and show you what I came up with.

The jQuery


$(document).ready(function() {
    $(".imageThumb").hover(
        function() { // handlerIn
            var mediumImage = $(this).find('a').attr('medium');
            var imgLink = $(this).find('a').attr('href');
            // this holds the 'Shadowbox' cacheKey index value!
            var imgIndex = $(this).find('a').attr('idx');
            $('#swapImg').attr({src:mediumImage}).fadeIn(800);
            $('#swapLink').attr({href:imgLink,idx:imgIndex});
            return false;
        }
    );

    $("#featuredImage >
a#swapLink").click(function(event) {
        event.preventDefault();
        // grab the 'Shadowbox' cacheKey index value
        var idx = $('#featuredImage').find('a').attr('idx');
        // now add the index key to the link so that when we call open, it knows this link already exists
        this.shadowboxCacheKey = idx;
        Shadowbox.open(this,{gallery:"products",continuous:true});
    });

});

The HTML


<div id="imageThumbs">
    <div class="imageThumb"><a rel="shadowbox[products];options={continuous:true};" idx="0" href="img1.jpg" title="" medium="img1-med.jpg"><img src="img1-thumb.jpg" alt="" width="70" height="70" /></a></div>
    <div class="imageThumb"><a rel="shadowbox[products];options={continuous:true};" idx="1" href="img2.jpg" title="" medium="img2-med.jpg"><img src="img2-thumb.jpg" alt="" width="70" height="70" /></a></div>
    <div class="imageThumb"><a rel="shadowbox[products];options={continuous:true};" idx="2" href="img3.jpg" title="" medium="img3-med.jpg"><img src="img3-thumb.jpg" alt="" width="70" height="70" /></a></div>
    <div class="imageThumb"><a rel="shadowbox[products];options={continuous:true};" idx="3" href="img4.jpg" title="" medium="img4-med.jpg"><img src="img4-thumb.jpg" alt="" width="70" height="70" /></a></div>
</div>
<div id="productImages">
    <div id="featuredImage"><a idx="0" id="swapLink" href="img1.jpg" ><img id="swapImg" src="img1-med.jpg" border="0" alt="" /></a></div>
</div>

That's it! I hope this helps someone else and saves some hair pulling. Enjoy!

© 2026, Stephen J. Withington, Jr.  |  Hosted by Hostek.com

Creative Commons License   |   This work is licensed under a Creative Commons Attribution 3.0 Unported License.