admin管理员组

文章数量:1410712

I'm currently using jQuery.appear to change the class of elements as they e into the viewport. The plugin works great, except that it fires right as the top of the element es into view. I am wanting to adapt it so it only fires when the entire element is inside the viewport, or near to being.

CODE:

$('someselector').appear();
$('someselector').on('appear', function() {
    $(this).removeClass('on').addClass('off');
    $(this).siblings().removeClass('off').addClass('on');
});

I'm currently using jQuery.appear to change the class of elements as they e into the viewport. The plugin works great, except that it fires right as the top of the element es into view. I am wanting to adapt it so it only fires when the entire element is inside the viewport, or near to being.

CODE:

$('someselector').appear();
$('someselector').on('appear', function() {
    $(this).removeClass('on').addClass('off');
    $(this).siblings().removeClass('off').addClass('on');
});
Share Improve this question asked Jan 31, 2013 at 5:11 LeaLea 9349 gold badges17 silver badges34 bronze badges 3
  • Define "as they e into the viewport" – Explosion Pills Commented Jan 31, 2013 at 5:13
  • As the user scrolls down the page, and the element scrolls into view – Lea Commented Jan 31, 2013 at 5:19
  • I've changed the appear plugin as I needed some exersise making jQuery extensions. It's not finished but will work. Removed the part that will trigger event. You can only add either full view or part visible to a certain selector string so $("#myid") cannot have both full and partly assigned on them. – HMR Commented Feb 1, 2013 at 12:03
Add a ment  | 

2 Answers 2

Reset to default 1

jQuery Waypoints plugin could be useful also. It triggers an action, when the element became to be visible on the screen.

$('.entry').waypoint(function() {
   alert('The element is appeared on the screen.');
});

There are some examples on the site of the plugin.

I have changed some of the code so you can check if an element is fully visible. Removed the code that will trigger an event since it's harder to clean up using destroy (not implemented yet). I will try and make it according to the documentation: http://docs.jquery./Plugins/Authoring

Here is the html page:

<!DOCTYPE html>
<html>
<head>
<script src="jquery.js"></script>
<script src="appear.js"></script>
<script>
    $(document).ready(function(){
        //TODO: not sure if there is such a thing as selector
        //  namespaces but could try that to add both appear and
        //  fully-appear to same selector elements
        $('#fully').appear(function(){
            console.log("full view");
        },{fullView:true});
        $('#partly').appear(function(){
            console.log("partly visible");
        });
        $(window).scrollTop(1400).scrollLeft(1000);
    });
</script>
</head>
<body >
    <div style="width:3000px;height: 3000px"></div>
    <div id="fully" style="width:50px;height:75px;
    position: absolute;left:1500px;top:1500px;
    background: black">
    </div>
    <div id="partly" style="width:50px;height:75px;
    position: absolute;left:1450px;top:1350px;
    background: yellow">
    </div>
</body>
</html>

And the changed appear.js

/*
* jQuery appear plugin
*
* Copyright (c) 2012 Andrey Sidorov
* licensed under MIT license.
* Edit by HRM 2013 02 01
* https://github./morr/jquery.appear/
*
* Version: 0.2.1
*/
(function($) {
  var selectors = [];
  var $window = $(window);
  var $document = $(document);

  function process(p) {
    p.checkLock = false;
    var $appeared = p.elements.filter(function() {
        return $(this).is(p.filterName);
    });
    if($appeared.length==0){
      return;
    }
    p.callback($appeared);
  }

  // "appeared" custom filter
  $.expr[':']['appeared'] = function(element) {
    var $element = $(element);
    if (!$element.is(':visible')) {
      return false;
    }

    var window_left = $window.scrollLeft();
    var window_top = $window.scrollTop();
    var offset = $element.offset();
    var left = offset.left;
    var top = offset.top;
    if (top + $element.height() >= window_top &&
        top - ($element.data('appear-top-offset') || 0)
          <= window_top + $window.height() &&
        left + $element.width() >= window_left &&
        left - ($element.data('appear-left-offset') || 0)
          <= window_left + $window.width()) {
      return true;
    } else {
      return false;
    }
  }

   // "in-full-view" custom filter
  $.expr[':']['fully-appeared'] = function(element) {
    var $element = $(element);
    if (!$element.is(':visible')) {
      return false;
    }
    wLeft=$window.scrollLeft();
    wTop=$window.scrollTop();
    var offset = $element.offset();
    var left = offset.left- ($element.data
      ('appear-left-offset') || 0);
    var right = (offset.left+$element.width()) -
      ($element.data('appear-left-offset') || 0);
    var top = offset.top - ($element.data
      ('appear-top-offset') || 0);
    var bottom = offset.top+$element.height();
    var window_left = wLeft;
    var window_top = wTop;
    var window_right = wLeft+ $window.width();
    var window_bottom = wTop+$window.height();

    if (window_bottom>=bottom&&
        window_top<=top&&
        window_left<=left&&
        window_right>=right ) {
      return true;
    } else {
      return false;
    }
  }

  function pare(o1,o2){
    //simple pare, assumes all properties of o1 and o2 are
    //  simple types make sure that o1 is not undefined
    //  paring goes much further but requires writing another
    //  extension
    if(typeof o2=="undefined"){
      return false;
    }
    var i;
    for(i in o1){
      if(typeof o2[i]=="undefined"){
        return false;
      }
    }
    for(i in o1){
      if(o1[i]!=o2[i]){
        return false;
      }
    }
    return true;
  }

  function checkExist(selector){
    return !(typeof selectors[selector]=="undefined");
  }

  $.fn.extend({
    // watching for element's appearance in browser viewport
    appear: function(callback, options) {
      if(typeof callback != "function"){
        throw("Have to provide a callback: "
          +"$('selector').appear(function()....");
      }
      var defaults = {
        interval: 250
      }
      var index=this.selector;
      if(index==""){
        throw("Can't use an empty selector with this function.");
      }
      $.extend(defaults, options || {});
      var exist=checkExist(index);
      if(!exist){
        selectors[index]=defaults;
      }
      var checkBind=pare(defaults,
        selectors[index]);
      selectors[index]=defaults;
      var p={
        checkLock:false,
        filterName:(defaults.fullView)?":fully-appeared":":appeared",
        callback:callback,
        elements:this
      }
      if ((!checkBind)||(!exist)) {
        $(window).off("scroll."+index,on_check)
          .on("resize."+index,on_check);
        var on_check = function() {
          if (p.checkLock) {
            return;
          }
          p.checkLock = true;
          setTimeout(function(){
            process(p);
          }, defaults.interval);
        };

        $(window).on("scroll."+index,on_check)
          .on("resize."+index,on_check);
      }

      if (options && options.force_process) {
        setTimeout(process, defaults.interval);
      }
      return $(this.selector);
    }
  });

  $.extend({
    // force elements's appearance check
    force_appear: function() {
      if (check_binded) {
        process();
        return true;
      };
      return false;
    }
  });
})(jQuery);

本文标签: javascriptjQueryappear to fire only when the entire element in is viewportStack Overflow