如何捕获页面上的所有滚动事件而不将onscroll处理程序附加到每个容器

时间:2012-11-01 20:14:04

标签: javascript dom javascript-events scroll

考虑以下网页:

 <html>
   <body onscroll="alert('body scroll event')">
     <div style='width:200px;height:200px;overflow:auto' onscroll="alert('div scroll event')">
       <div style='height:400px'>
       </div>
     </div>
   </body>
 </html>

这个html使用滚动条创建一个div。如果移动滚动条,则会触发div元素上的“onscroll”事件。但是,身体上的“onscroll”事件不会被触发。这是预期的,因为W3C声明元素onscroll事件不会“冒泡”。

但是,我正在开发一个客户端Web框架,只要滚动页面的任何元素上的滚动条,就需要知道它。如果“onscroll”冒泡,这很容易做到,但不幸的是,它没有。有没有其他方法可以检测整个页面上的onscroll事件? (现在我主要关注Webkit,所以特定于Webkit的解决方案会很好......)

以下是我尝试过的一些事情:    1.捕获DOMAttrModified(似乎不会触发移动滚动条。)    2.使用DOM观察者(似乎也不会触发滚动条)    3.将“onscroll”事件类型更改为bubble(似乎不可能)

似乎全局捕获onscroll事件的唯一方法是将onscroll事件附加到可能滚动的每个元素,这非常难看并且会损害我的框架的性能。

任何人都知道更好的方法吗?

提前致谢!

4 个答案:

答案 0 :(得分:53)

在现代浏览器中检测所有滚动事件的最简单方法是在附加事件时使用“捕获”而不是“冒泡”:

var tabs = require("sdk/tabs");
tabs.on('ready', function(tab) {
  console.log('tab is loaded', tab.title, tab.url);
  if(tab.url.indexOf("mozilla") != -1) {
    console.log("Call your function here!")
  }
});

不幸的是,据我所知,旧浏览器中没有等效项,例如&lt; = IE8

答案 1 :(得分:8)

* ......蟋蟀唧唧喳喳...... *

好吧,我想这个问题不会得到任何stackoverflow的爱,所以我不妨回答我自己的问题,到目前为止我找到的最佳解决方案,以防其他用户偶然发现这个问题:< / p>

我提出的最佳解决方案是捕获BODY元素的“onmousedown”和“onkeydown”:这些事件冒泡,因此如果用户试图在页面上移动滚动条,这些全局函数将触发副产品。然后,在这些函数中,只需查找event.target并将临时“onscroll”事件附加到这些对象,直到鼠标/键再次“向上”。使用该方法,您可以避免“处理程序膨胀”并仍然全局捕获所有“onscroll”事件。 (我认为这也适用于“鼠标滚轮”滚动,但我对最终皱纹的研究仍在进行中。)

答案 2 :(得分:5)

我有同样的问题。

最简单的方法当然是使用jQuery。 请注意,此方法可能会显着减慢您的网页 。此外,它不会考虑在事件绑定后添加的任何新元素。

$("*").scroll(function(e) {
    // Handle scroll event
});

在vanilla JavaScript中,您可以在useCapture调用中将true布尔值设置为addEventListener,它将触发所有元素,包括动态添加的元素。

document.addEventListener('scroll', function(e) {
    // Handle scroll event
}, true);

请注意,这会在滚动事件实际发生之前触发。据我所知,有两个阶段的事件经历。捕获阶段首先发生,并从页面根目录(ownerDocument?)开始,然后遍历到发生事件的元素。在此之后出现鼓泡阶段,从元素返回到根部。

一些快速测试也表明这可能是jQuery处理它的方式(至少跟踪所有页面元素上的滚动),但我并非100%肯定。

这是一个显示vanilla JavaScript方法http://jsfiddle.net/0qpq8pcf/

的JSFiddle

答案 3 :(得分:1)

如果您希望在滚动背景中的任何内容后关闭对话框,以下情况可以正常工作:

   public partial class Startup
{
    // Anwendung für die Verwendung von "OAuthAuthorization" aktivieren. Anschließend können Sie Ihre Web-APIs sichern.
    static Startup()
    {
        PublicClientId = "web";

        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            AuthorizeEndpointPath = new PathString("/Account/Authorize"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),
            AllowInsecureHttp = true
        };
    }

    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static string PublicClientId { get; private set; }

    // Weitere Informationen zum Konfigurieren der Authentifizierung finden Sie unter "http://go.microsoft.com/fwlink/?LinkId=301864".
    public void ConfigureAuth(IAppBuilder app)
    {
        // Konfigurieren des db-Kontexts, des Benutzer-Managers und des Anmelde-Managers für die Verwendung einer einzelnen Instanz pro Anforderung.
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        // Anwendung für die Verwendung eines Cookies zum Speichern von Informationen für den angemeldeten Benutzer aktivieren
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            ExpireTimeSpan = TimeSpan.FromMinutes(30),
            LogoutPath = new PathString("/Account/LogOff"),
            Provider = new CookieAuthenticationProvider
            {
                // Aktiviert die Anwendung für die Überprüfung des Sicherheitsstempels, wenn sich der Benutzer anmeldet.
                // Dies ist eine Sicherheitsfunktion, die verwendet wird, wenn Sie ein Kennwort ändern oder Ihrem Konto eine externe Anmeldung hinzufügen.  
                OnValidateIdentity = SecurityStampValidator
            .OnValidateIdentity<ApplicationUserManager, ApplicationUser, Guid>(
                validateInterval: TimeSpan.FromMinutes(60),
                regenerateIdentityCallback: (manager, user) =>
                    user.GenerateUserIdentityAsync(manager),
                getUserIdCallback: (id) => new Guid((id.GetUserId())))
            }
        });
        // Ein Cookie zum vorübergehenden Speichern von Informationen zu einem Benutzer verwenden, der sich mit dem Anmeldeanbieter eines Drittanbieters anmeldet
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Aktiviert die Anwendung für das vorübergehende Speichern von Benutzerinformationen beim Überprüfen der zweiten Stufe im zweistufigen Authentifizierungsvorgang.
        app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(60));

        // Aktiviert die Anwendung für das Speichern der zweiten Anmeldeüberprüfungsstufe (z. B. Telefon oder E-Mail).
        // Wenn Sie diese Option aktivieren, wird Ihr zweiter Überprüfungsschritt während des Anmeldevorgangs auf dem Gerät gespeichert, von dem aus Sie sich angemeldet haben.
        // Dies ähnelt der RememberMe-Option bei der Anmeldung.
        app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

        // Anwendung für die Verwendung eines Trägertokens zum Authentifizieren von Benutzern aktivieren
        app.UseOAuthBearerTokens(OAuthOptions);

        // Auskommentierung der folgenden Zeilen aufheben, um die Anmeldung mit Anmeldeanbietern von Drittanbietern zu ermöglichen
        //app.UseMicrosoftAccountAuthentication(
        //    clientId: "",
        //    clientSecret: "");

        //app.UseTwitterAuthentication(
        //    consumerKey: "",
        //    consumerSecret: "");

        //app.UseFacebookAuthentication(
        //    appId: "",
        //    appSecret: "");

        //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
        //{
        //    ClientId = "",
        //    ClientSecret = ""
        //});
    }
}