开发者

Issue maintaining scope with jQuery / module pattern

开发者 https://www.devze.com 2023-04-01 03:05 出处:网络
I\'m just starting out using modul开发者_JS百科e patterns (thanks to Christian Heilmann\'s original tutorial) to organize my jQuery and I\'m running into a weird issue. Consider the following javascri

I'm just starting out using modul开发者_JS百科e 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.


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).


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');
});


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号