tommychoo
tommychoo

Reputation: 653

jQuery Plugin Callback $this can't return element

I am learning to write a mini jQuery Plugin Tools.

My plugin is helping user to check if user mousewheel whether scroll up or scroll down to trigger the callback function.

I have a four divs, when my mouse pointer hover it and scroll up with mouse wheel, the plugin callback will change this div 's background color.

Unfortunately, my callback 's $this is not working to point this element. I need some help.

Style

    body {background: #2A2B30;}
    .wrapper {margin-top: 100px;}
    .wrapper div.content {border-radius: 7px; border: 1px solid #000; min-height: 300px; margin-top: 30px; background: #ededed; padding: 30px; font-size: 20px;}

Html

    <div class="container">
    <div class="wrapper clearfix">
        <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
            <div class="blk content"> </div>
        </div>
        <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
            <div class=" content"> </div>
        </div>
        <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
            <div class="blk content"> </div>
        </div>
        <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
            <div class=" content"> </div>
        </div>
    </div>
</div>

Call Plugin

$(function() {
    $('.blk').scroll({
        lastAnimation   : 0,
        quietPeriod     : 500,
        animationTime   : 800,
        ScrollUp : function() {
            $(this).css('background', 'red');
        },
        ScrollDown : function() {
            alert('Scroll Down');
        }
    });
});

My Plugin

(function($) {
$.fn.scroll = function( options ) {

    var settings = $.extend({
        // selector         : $(this),
        lastAnimation    : null,
        quietPeriod      : null,
        animationTime    : null,
        ScrollUp         : null,
        ScrollDown       : null
    }, options);

    return this.each( function() {
        var lastAnimation = settings.lastAnimation;
        var quietPeriod = settings.quietPeriod;
        var animationTime = settings.animationTime;

        function init(event, delta) {
            deltaOfInterest = delta;
            var timeNow = new Date().getTime();
            if( timeNow - lastAnimation < quietPeriod + animationTime ) {
                event.preventDefault();
                return;
            }

            if ( deltaOfInterest < 0 ) {
                // Call Back
                if ( $.isFunction( settings.ScrollUp ) ) {
                    settings.ScrollUp.call(this);
                }
            } else {
                // Call Back
                if ( $.isFunction( settings.ScrollDown ) ) {
                    settings.ScrollDown.call(this);
                }
            }

            lastAnimation = timeNow;
        }

        $(this).bind('mousewheel DOMMouseScroll', function(event) {
            event.preventDefault();
            var delta = event.originalEvent.wheelDelta || -event.originalEvent.detail;
            init(event, delta);
        });

       });
       }
      }(jQuery));

Upvotes: 1

Views: 135

Answers (2)

Emmanuel Delay
Emmanuel Delay

Reputation: 3679

See if this helps.

I use jQuery .hover() to store which div the mouse is over.
Then just use that variable (var hoverDiv) instead of "this"

<style>
  body {background: #2A2B30;}
  .wrapper {margin-top: 100px;}
  .wrapper div.content {border-radius: 7px; border: 1px solid #000; min-height: 120px; margin-top: 30px; background: #ededed; padding: 30px; font-size: 20px;}
</style>
  <div class="container">
  <div class="wrapper clearfix">
    <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
      <div class="blk content"> </div>
    </div>
    <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
      <div class=" content"> </div>
    </div>
    <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
      <div class="blk content"> </div>
    </div>
    <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
      <div class=" content"> </div>
    </div>
  </div>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
/*
@see http://stackoverflow.com/questions/31340479/jquery-plugin-callback-this-cant-return-element
*/
(function($) {
  $.fn.scroll = function( options ) {
    var settings = $.extend({
      // selector     : $(this),
      lastAnimation  : null,
      quietPeriod    : null,
      animationTime  : null,
      ScrollUp     : null,
      ScrollDown     : null
    }, options);
    return this.each(function() {
      var lastAnimation = settings.lastAnimation;
      var quietPeriod = settings.quietPeriod;
      var animationTime = settings.animationTime;
      function init(event, delta) {
        deltaOfInterest = delta;
        var timeNow = new Date().getTime();
        if( timeNow - lastAnimation < quietPeriod + animationTime ) {
          event.preventDefault();
          return;
        }
        if ( deltaOfInterest < 0 ) {
          // Call Back
          if ( $.isFunction( settings.ScrollUp ) ) {
            settings.ScrollUp.call(this);
          }
        } else {
          // Call Back
          if ( $.isFunction( settings.ScrollDown ) ) {
            settings.ScrollDown.call(this);
          }
        }
        lastAnimation = timeNow;
      }
      $(this).bind('mousewheel DOMMouseScroll', function(event) {
        event.preventDefault();
        var delta = event.originalEvent.wheelDelta || -event.originalEvent.detail;
        init(event, delta);
      });
    });
  }
}(jQuery));

$(function() {
  var hoverDiv = null;
  $('.blk').hover(function(e) {
      hoverDiv = $(this);
    }, 
    function(e) {
      hoverDiv = null;
    }
  );
  $('.blk').scroll({
    lastAnimation   : 0,
    quietPeriod   : 500,
    animationTime   : 800,
    ScrollUp : function() {
      if(hoverDiv) {
        hoverDiv.css('background', 'red');
      }
    },
    ScrollDown : function() {
      if(hoverDiv) {
        hoverDiv.css('background', 'blue');
      }
    }
  });
});
</script>

Upvotes: 0

Umesh Sehta
Umesh Sehta

Reputation: 10683

This is because settings.ScrollUp.call(this); here this is not refer to div its inside function so this is becomes something else inside of the init inner function try this:-

  return this.each( function() {
     var $this=this; // create variable here 
      .....
      .....
     settings.ScrollUp.call($this); //use it here like this  in init function

Demo

Upvotes: 3

Related Questions