Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

浏览器的overflow事件 #8

Open
zmmbreeze opened this issue Aug 31, 2016 · 0 comments
Open

浏览器的overflow事件 #8

zmmbreeze opened this issue Aug 31, 2016 · 0 comments

Comments

@zmmbreeze
Copy link
Owner

以前的旧文章,转移到这里

Webkit和Firefox其实是原生支持探测元素overflow状态改变的事件。参看这个DEMO:

See the Pen Way to detect overflow event support and use it with graceful degradation by mzhou (@zmmbreeze) on CodePen.

<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

Webkit使用的是overflowchanged事件,而Firefox则使用overflow和underflow这两个事件。虽然Webkit只提供了一个事件,但是我们可以通过event对象的属性来知道是overflow还是underflow,甚至知道是垂直方向还是水平方向。而Firefox的两个事件则没法提供溢出方向的信息。

重要地是IE和旧版的Opera(非webkit内核)是不支持的,也没有什么特别好的fallback方法。所以在使用overflow事件时一定要做好特征检测。在Webkit下,只需判断window有没有OverflowEvent即可。而在Firefox下比较麻烦了。

查看了Modernizr的源码,发现了使用setAtrribute来检测Firefox是否支持某个事件的方法。可惜尝试之下发现不能正确检测overflow事件。于是改用创建div并激活overflow事件的方法来判断是否支持。代码如下:

    var element = document.createElement('div');
    if (element.addEventListener) {
      element.style.cssText = 'overflow:scroll;height:1px;width:1px;';
      document.body.appendChild(element);

      var overflowSupport = false;
      // firefox(tested on 1.5+) support overflow/underflow event
      element.addEventListener('overflow', function () {
          overflowSupport = true;
      }, false);
      element.innerHTML = '&lt;div style=&quot;height:200px;width:1px;&quot;&gt;&lt;/div&gt;';

      var timeout;
      var end = function() {
          if (end.done) {
              return;
          }
          end.done = true;

          if (overflowSupport) {
              callback(function (element, type, cb) {
                  element.addEventListener(type + 'flow', cb, false);
              });
          } else {
              callback();
          }

          clearTimeout(timeout);
          document.body.removeChild(element);
      };
      // Use scroll event to make sure it's right after overflow event.
      element.addEventListener('scroll', end, false);
      element.scrollTop = 1000;
      // Make sure callback was called, even browser not support scroll event.
      // For example 'opera 11.*'
      timeout = setTimeout(end, 250);
    }

因为是异步的,所以一定要确保判断结果的动作是在执行过overflow事件回调之后。一个比较简单的方法是使用setTimeout延迟执行。为了保证执行顺序,时间就一定要设置长一点(250ms)。但是这样响应太慢了。幸运地是在Firefox中scroll事件是在overflow事件之后触发的,所以改为在scroll事件的回调函数中做判断。

如果你有更好的检测方法,请一定告知~ Github

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

1 participant