3

I'm just starting out using module patterns (thanks to Christian Heilmann's original tutorial) to organize my jQuery and I'm running into a weird issue. Consider the following javascript code:

var Gallery = function(){

  var $obj, $thumbs, $mainPic;

  function init($e){

    $obj = $e;
    $thumbs = $obj.find('.thumbnail');
    $mainPic = $obj.find('.main-pic');

    $obj.find($thumbs).bind('click',updateMainPic);

  };

  function updateMainPic() {
    $thumbs.removeClass('selected');
    $thumb = $thumbs.filter(this);
    $thumb.addClass('selected');
    newPicUrl = $thumb.data('src');    
    $mainPic.attr('src',newPicUrl);    
  };

  return {
    init:init
  }

}();

Which is included and used on the follow HTML:

<div id="gallery1">
  <img src="" class="main-pic">
  <ul>
    <li class="thumbnail" data-src="photo1.jpg">Photo 1</li>
    <li class="thumbnail" data-src="photo2.jpg">Photo 2</li>
    <li class="thumbnail" data-src="photo3.jpg">Photo 3</li>
    <li class="thumbnail" data-src="photo4.jpg">Photo 4</li>
  </ul>
</div>
<script type="text/javascript">
  Gallery.init($('#gallery1'));
</script>

<div id="gallery2">
  <img src="" class="main-pic">
  <ul>
    <li class="thumbnail" data-src="photo1.jpg">Photo 1</li>
    <li class="thumbnail" data-src="photo2.jpg">Photo 2</li>
    <li class="thumbnail" data-src="photo3.jpg">Photo 3</li>
    <li class="thumbnail" data-src="photo4.jpg">Photo 4</li>
  </ul>
</div>
<script type="text/javascript">
  Gallery.init($('#gallery2'));
</script>

The problem I'm running into is that clicking the thumbnails on #gallery1 is swapping the image of #gallery2, yet #gallery2 is working as expected. It would seem the the $obj variable is being shared across the instances, but I thought it remained scoped to the private instance of the function.

Any advice on how to get this properly scoped and working would be greatly appreciated.

3 Answers 3

4

Problem is that Gallery is a singleton. The moment you call the second init, you're replacing the internal $obj variable.

I wouldn't use a module pattern in this situation. If you're using jQuery anyway, it'd be easier to write a jQuery plugin (simple) or a jQuery UI Widget (is really good at maintaining state).

Sign up to request clarification or add additional context in comments.

1 Comment

@Bjork24 No problem - on a related note, check out this free e-book on javascript design patterns (addyosmani.com/resources/essentialjsdesignpatterns/book). Good luck in your studies.
0

I played around with your scenario for awhile, trying to see if a moduler pattern can be used; and it looks like a huge hurdle occurs during the binding. It becomes very difficult to determine the scope for 'this' inside your updateMainPic() function. Even with a powerful library like underscore.js, with their _.bind() function that allows biding to an object, cannot overcome this scenario easily.

Like Mike mentioned, a plugin or widget would make this particular task trivial:

$('li.thumbnail').bind('click', function() {
    $(this).closest('div').find('.main-pic').attr('src', $(this).attr('data-src'));
    $(this).addClass('selected');
    $(this).siblings().removeClass('selected');
});

Comments

0

The module pattern is more designed for singleton usage. Each time you call your init method you are repointing your $obj variable to the passed $e. So simply drop the $obj move the other two into the init and pass the three parameters to updateMainPic. If you need instance based pointers then have your singleton return a prototypal function that you can create instances of and bind directly to your dom click event.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.