How to change a Javascript singleton to something that can be used multiple times?
<p>A bit of an architectural question...</p>

<p>I originally created a Javascript singleton to house methods needed to operate a photo gallery module in a template file for a CMS system.  The original specification only called for one instance of this photo gallery module on a page.  (The code below is a gross simplification of what I actually wrote.)</p>

<p>Shortly after releasing the code, it dawned on me that even though the specification called for one instance of this module, this code would fall apart if a page had two instances of the module (i.e. the user adds two photo galleries to a page via the CMS).  Now, the HTML markup is safe, because I used class names, but how would I go about restructuring my Javascript and jQuery event listeners to be able to handle multiple modules?  You may assume that each photo gallery has its own JSON-P file (or you may assume a single JSON-P file if you think it can be handled more elegantly with one JSON-P file).</p>

<p>I think my original jQuery event listeners might have to be converted to $.delegate(), but I have no clue what to do after that and what to do about converting my singleton.  Any leads would be appreciated.  If you offer code, I prefer readability over optimization.  </p>

<p>I'm not asking this question, because I have an immediate need to solve the problem for work.  I am asking this question to be forward-thinking and to be a better Javascript developer, because I am expecting to run into this problem in the future and want to be prepared.</p>

<p>Thank you for reading.</p>

<p><strong>HTML</strong></p>

<pre><code>&lt;div class="photoGalleryMod"&gt;
    &lt;div class="photoGalleryImgBox"&gt;&lt;img src="http://www.test.org/i/intro.jpg" alt="Intro Photo" /&gt;&lt;/div&gt;
    &lt;div class="photoGalleryImgCap"&gt;&lt;p&gt;Caption&lt;/p&gt;&lt;/div&gt;
    &lt;a href="#" class="photoGalleryPrevImgLnk"&gt;&lt;/a&gt;
    &lt;a href="#" class="photoGalleryNextImgLnk"&gt;&lt;/a&gt;  
&lt;/div&gt;
</code></pre>

<p>The Javascript is an external static file and makes a call to a JSON-P file via $.getSCript(), created by the CMS.</p>

<p><strong>Javascript/jQuery</strong></p>

<pre><code>(function($) {
    photoGalleryModule = {
        json: '',
        numSlidesInJson: '',
        currentSlide: '',
        updateSlide: function (arg_slidNum) {
            /* Update the slide here */
        },
        init: function (arg_jsonObj) {
            this.json = arg_jsonObj;
            this.numSlidesInJson = this.json.photoGallerySlides.length;
            this.currentSlide = 0;
        }
    };

    $(document).ready(function() {
        $.getScript('./photogallery.json');

        $('.photoGalleryPrevImgLnk').live('click', function(event) {
            photoGalleryModule.currentSlide = photoGalleryModule.currentSlide - 1;
            photoGalleryModule.updateSlide(photoGalleryModule.currentSlide);
            event.preventDefault();
        });

        $('.photoGalleryNextImgLnk').live('click', function(event) {
            photoGalleryModule.currentSlide = photoGalleryModule.currentSlide + 1;
            photoGalleryModule.updateSlide(photoGalleryModule.currentSlide);
            event.preventDefault();
        });
    });
})(jQuery);
</code></pre>

<p><strong>Contents of photo-gallery.json</strong></p>

<pre><code>photoGalleryModule.init(
{
    photoGallerySlides:
        [
            {
                type: 'intro',
                pageTitle: 'Intro Photo',
                imgUrl: 'http://www.test.org/i/intro.jpg',
                imgAltAttr: 'Intro photo',
                captionText: 'The intro photo',
            },
            {
                type: 'normal',
                pageTitle: 'First Photo',
                imgUrl: 'http://www.test.org/i/img1.jpg',
                imgAltAttr: 'First photo',
                captionText: 'the first photo',
            },
            {
                type: 'normal',
                pageTitle: 'Second Photo',
                imgUrl: 'http://www.test.org/i/img2.jpg',
                imgAltAttr: 'Second photo',
                captionText: 'the second photo',
            }
        ]
});
</code></pre>
