确定用户是点击滚动条还是内容(onclick 为原生滚动条) [英] Determine whether user clicking scrollbar or content (onclick for native scroll bar)

查看:25
本文介绍了确定用户是点击滚动条还是内容(onclick 为原生滚动条)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 JQuery 中创建自定义事件,用于检测何时单击滚动条1.
我知道有很多文本,但我所有的问题都是粗体的,并且有一个 JSFiddle 示例,您可以立即处理.

I'm trying to create custom events in JQuery that are supposed to detect when a scrollbar is clicked1.
I know there's lots of text, but all my questions are boldfaced and there's a JSFiddle example you can work on straight away.

因为我还没有找到任何内置的功能,
我必须创建一个 hasScroll 函数,检查元素是否有滚动条,

Because I haven't found any built in functionality for this,
I had to create a hasScroll function, checking if the element has a scrollbar,

$.fn.hasScroll = function(axis){
    var overflow = this.css("overflow"),
        overflowAxis;

    if(typeof axis == "undefined" || axis == "y") overflowAxis = this.css("overflow-y");
    else overflowAxis = this.css("overflow-x");

    var bShouldScroll = this.get(0).scrollHeight > this.innerHeight();

    var bAllowedScroll = (overflow == "auto" || overflow == "visible") ||
                         (overflowAxis == "auto" || overflowAxis == "visible");

    var bOverrideScroll = overflow == "scroll" || overflowAxis == "scroll";

    return (bShouldScroll && bAllowedScroll) || bOverrideScroll;
};

和一个 inScrollRange 函数,检查执行的点击是否在滚动范围内.

and an inScrollRange function, checking if the click performed was within the scroll range.

var scrollSize = 18;

function inScrollRange(event){
    var x = event.pageX,
        y = event.pageY,
        e = $(event.target),
        hasY = e.hasScroll(),
        hasX = e.hasScroll("x"),
        rX = null,
        rY = null,
        bInX = false,
        bInY = false

    if(hasY){
        rY = new RECT();
        rY.top = e.offset().top;
        rY.right = e.offset().left + e.width();
        rY.bottom = rY.top +e.height();
        rY.left = rY.right - scrollSize;

        //if(hasX) rY.bottom -= scrollSize;
        bInY = inRect(rY, x, y);
    }

    if(hasX){
        rX = new RECT();
        rX.bottom = e.offset().top + e.height();
        rX.left = e.offset().left;
        rX.top = rX.bottom - scrollSize;
        rX.right = rX.left + e.width();

        //if(hasY) rX.right -= scrollSize;
        bInX = inRect(rX, x, y);
    }

    return bInX || bInY;
}

所有滚动条的大小都统一吗?例如,在 Firefox 和 IE 中为 18 像素.
假设没有自定义滚动条,在某些浏览器中是否有任何额外的填充或大小?

Are all scrollbar sizes uniform? E.g in Firefox and IE it's 18px.
Assuming there are no customized scrollbars, is there any extra padding or sizes in some browsers?

这些功能都按预期执行(据我所知).

These functions all perform as intended (from what I can discern).

制作自定义事件有点棘手,但我让它有点工作.唯一的问题是,如果被点击的元素附加了一个 mousedown/up 事件,它也会被触发.

Making custom events was a bit trickier, but I got it to work somewhat. The only problem is that if the element clicked has a mousedown/up event attached to it, that will be triggered as well.

我似乎无法阻止其他事件同时触发,我称之为 mousedownScroll/mouseupScroll 事件.

I can't seem to stop the other events from triggering while simultaneously triggering, what I call, the mousedownScroll/mouseupScroll events.

$.fn.mousedownScroll = function(fn, data){
    if(typeof fn == "undefined" && typeof data == "undefined"){
        $(this).trigger("mousedownScroll");
        return;
    }

    $(this).on("mousedownScroll", data, fn);
};

$.fn.mouseupScroll = function(fn, data){
    if(typeof fn == "undefined" && typeof data == "undefined"){
        $(this).trigger("mouseupScroll");
        return;
    }

    $(this).on("mouseupScroll", data, fn);
};

$(document).on("mousedown", function(e){
    if(inScrollRange(e)){
        $(e.target).trigger("mousedownScroll");
    }
});

$(document).on("mouseup", function(e){
    if(inScrollRange(e)){
        $(e.target).trigger("mouseupScroll");
    }
});

$("selector").mousedown(function(e){
    console.log("Clicked content."); //Fired when clicking scroller as well
});

$("selector").mousedownScroll(function(e){
    console.log("Clicked scroller.");
});

如何阻止其他点击"事件触发?

虽然我在问,但请尽可能地优化代码.

While I'm asking, please feel free to optimize the code as much as possible.

这里有一个 JSFiddle 需要处理.

我做这个的原因是因为我正在开发一个更大的插件.它有一个自定义上下文菜单,当我右键单击其中一个滚动条时会显示该菜单.我不想要那个.所以我想我应该创建一个事件来检查滚动点击(鼠标向上/向下),然后阻止显示上下文菜单.但是,为了做到这一点,我需要在正常点击之前进行滚动点击,并且如果可能的话,停止触发正常点击.

The reason I'm making this is because of a bigger plugin I'm developing. It's got a custom context menu that is showing up when I right click one of the scrollers. I don't want that. So I thought I should make an event that checks for scroll clicks (mouseup/downs) and then prevent the context menu from being displayed. In order to do that though, I need the scroll click to come before the normal click, and also, if possible, stop the normal clicks from firing.

我只是在这里大声思考但是也许有一种方法可以获取绑定到元素的所有函数,然后切换它们的添加顺序?我知道函数是按照添加的顺序执行的(第一个添加的第一个调用),因此,如果我可以利用该过程,也许可以在单击事件之前插入整个事件到 JQuery 的注册".

I'm just thinking out loud here but maybe there's a way to get all the functions that are bound to the element and then switch the order in which they were added? I know that functions are executed in the order they were added (1st added 1st called), so, if I could tap into that process, perhaps the whole "registering" of the event to JQuery could just be inserted before the click events.

1 只能使用 mousedown/mouseup,因为单击滚动条时不会触发单击.如果这是错误的,请提供一个工作示例/代码

1 can only use mousedown/mouseup because click doesn't trigger when clicking on a scrollbar. If this is false, please provide a working example/code

推荐答案

你可能会使用这个 hack.

You may probably use this hack.

您可以尝试劫持 mousedownmouseup 事件,并在点击带有自定义功能的滚动条时避免它们.

You could try hijacking the mousedown and mouseup events and avoiding them when click on a scrollbar with your custom powered function.

$.fn.mousedown = function(data, fn) {
    if ( fn == null ) {
        fn = data;
        data = null;
    }    
    var o = fn;
    fn = function(e){
        if(!inScrollRange(e)) {
            return o.apply(this, arguments);
        }
        return;
    };
    if ( arguments.length > 0 ) {
        return this.bind( "mousedown", data, fn );
    } 
    return this.trigger( "mousedown" );
};

mousedownScrollmouseupScroll 事件的反面.

$.fn.mousedownScroll = function(data, fn) {
    if ( fn == null ) {
        fn = data;
        data = null;
    }    
    var o = fn;
    fn = function(e){
        if(inScrollRange(e)) {
            e.type = "mousedownscroll";
            return o.apply(this, arguments);
        }
        return;
    };
    if ( arguments.length > 0 ) {
        return this.bind( "mousedown", data, fn );
    } 
    return this.trigger( "mousedown" );
};

顺便说一下,我认为滚动条宽度是操作系统设置.

By the way, I think the scrollbar width is an OS setting.

这篇关于确定用户是点击滚动条还是内容(onclick 为原生滚动条)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆