Skip to content
New issue

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

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

Already on GitHub? Sign in 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

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

No branches or pull requests

1 participant