简体   繁体   English

jQuery插件只适用于最后一个选择器

[英]jQuery plugin only working on last selector

In my quest for learning more Javascript I'm trying to create a jQuery plugin that creates my own custom scrollbars. 在我寻求学习更多Javascript我正在尝试创建一个jQuery插件,创建我自己的自定义滚动条。 It is working fine for one scrollbar at a time but if I try to do two of them only the last one works. 它一次适用于一个滚动条但如果我尝试做其中两个只有最后一个工作。

JSFiddle: http://jsfiddle.net/JoelCool/K4mW7/1/ JSFiddle: http//jsfiddle.net/JoelCool/K4mW7/1/

I've noticed the variable "scrolling" is not true on the first scrollbar in the HandleMouseMove() function so it seems like it might be a scoping thing? 我注意到在HandleMouseMove()函数的第一个滚动条上变量“滚动”不正确所以看起来它可能是一个范围的东西?

HTML Scrollbar Test .scroller-bar { background-color:#ccc;border:1px solid black;float:left;position:relative;cursor:pointer; HTML Scrollbar Test .scroller-bar {background-color:#ccc; border:1px solid black; float:left; position:relative; cursor:pointer; } .noSelect { user-select:none; } .noSelect {user-select:none; -o-user-select:none; -o-用户选择:无; -moz-user-select:none; -moz-用户选择:无; -khtml-user-select:none; -khtml-用户选择:无; -webkit-user-select:none; -webkit-用户选择:无; } }

<div id="container" style="width:600px;height:300px;background-color:#ccc;overflow:hidden;position:relative;">
    <div id="content" style="background-color:blue;width:800px;height:283px;position:relative;left:0;">
        12345678901234567890123456789012345678901234567890
    </div>
    <div style="top:0;left:0;height:300px;width:100px;background-color:yellow;z-index:100;position:absolute;"></div>
    <div id="scroll-track-h" style="position:absolute;bottom:0;right:0;height:17px;width:500px;background-color:cyan;"></div>
    <div id="scroll-track-v" style="position:absolute;top:0;right:0;height:283px;width:17px;background-color:orange;"></div>
</div>
<br /><br />

<script src="jquery-2.1.0.min.js"></script>
<script src="scroller.js"></script>
<script>
    $('#scroll-track-v').scroller();
    $('#scroll-track-h').scroller();
    //$('#scroll-track-v, #scroll-track-h').scroller();
</script>

Javascript 使用Javascript

(function( $ ) {
    $.fn.scroller = function( options ) {

    options = $.extend( $.fn.scroller.defaults, options );

    // Plugin code
    return this.each(function () {
        var $elem = $(this),
            scrolling = false,
            mouseStartPos = 0,
            barPos = 0,
            xy = $elem.width() > $elem.height() ? 'x' : 'y',    // x = horizontal, y = vertical
            trackLength = xy == 'x' ? $elem.width() : $elem.height(),
            barLength = (trackLength * options.barPct / 100) - 2,   // should make it figure out the border width
            travelLength = trackLength - barLength - 2;
        console.log($elem);
        var $bar = $('<div class="scroller-bar"></div>')
                    .width( xy == 'x' ? barLength : $elem.innerWidth() - 2)
                    .height( xy == 'x' ? $elem.innerHeight() - 2 : barLength);
        $elem.append($bar);

        $elem.on('mousedown', function (evt) {
            scrolling = true;
            $("body").addClass("noSelect"); // turn off text selection while scrolling
            mouseStartPos = xy == 'x' ? evt.pageX : evt.pageY;
            barPos = xy == 'x' ? $bar.position().left : $bar.position().top;
            $(document).on('mousemove', function (evt) { HandleMouseMove(evt); });
        });

        $(document).on('mouseup', function (evt) {
            if (scrolling) {
                $("body").removeClass("noSelect");
                $(document).off('mousemove');
                mouseStartPos = 0;
                scrolling = false;
            }
        });

        HandleMouseMove = function (evt) {
            console.log(scrolling);
            if (scrolling) {
                var mouseMovedBy = xy == 'x' ? evt.pageX - mouseStartPos : evt.pageY - mouseStartPos,
                    newBarPos = barPos + mouseMovedBy;
                if (newBarPos < 0) { newBarPos = 0; }
                if (newBarPos > travelLength) { newBarPos = travelLength; }
                $bar.css(xy == 'x' ? 'left' : 'top', newBarPos);
                var pct = newBarPos / travelLength;
            }
        }
    });
}

// Set up the default options.
$.fn.scroller.defaults = {
    barPct : 25,
    onScroll : null
};
})( jQuery );

$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();

I'm calling it on the vertical bar first and then the horizontal and only the horizontal works. 我先在垂直条上调用它,然后是水平调用,只调整横向调整。 If I switch them then only the vertical works. 如果我切换它们,那么只有垂直工作。

Can anyone give me a clue? 任何人都可以给我一个线索吗? Am I doing it completely wrong? 我完全错了吗?

Your function HandleMouseMove() was not binded to the Element. 你的函数HandleMouseMove()没有绑定到Element。 It was getting mixed values for the 'scrolling' Boolean value. 它正在获得'scrolling'布尔值的混合值。

I just added $elem. 我刚加了$ elem。 before the function name. 在函数名之前。 and made it as $elem.HandleMouseMove(event); 并将其设为$ elem.HandleMouseMove(event);

Check the code 检查代码

(function( $ ) {
$.fn.scroller = function( options ) {

    options = $.extend( $.fn.scroller.defaults, options );

    // Plugin code
    return this.each(function () {
        var $elem = $(this),
            scrolling = false,
            mouseStartPos = 0,
            barPos = 0,
            xy = $elem.width() > $elem.height() ? 'x' : 'y',    // x = horizontal, y = vertical
            trackLength = xy == 'x' ? $elem.width() : $elem.height(),
            barLength = (trackLength * options.barPct / 100) - 2,   // should make it figure out the border width
            travelLength = trackLength - barLength - 2;
        console.log($elem);
        var $bar = $('<div class="scroller-bar"></div>')
                    .width( xy == 'x' ? barLength : $elem.innerWidth() - 2)
                    .height( xy == 'x' ? $elem.innerHeight() - 2 : barLength);
        $elem.append($bar);

        $elem.on('mousedown', function (evt) {
            scrolling = true;
            $("body").addClass("noSelect"); // turn off text selection while scrolling
            mouseStartPos = xy == 'x' ? evt.pageX : evt.pageY;
            barPos = xy == 'x' ? $bar.position().left : $bar.position().top;
            $(document).on('mousemove', function (evt) { $elem.HandleMouseMove(evt); });
        });

        $(document).on('mouseup', function (evt) {
            if (scrolling) {
                $("body").removeClass("noSelect");
                $(document).off('mousemove');
                mouseStartPos = 0;
                scrolling = false;
            }
        });

        $elem.HandleMouseMove = function (evt) {
            console.log(scrolling);
            if (scrolling) {
                var mouseMovedBy = xy == 'x' ? evt.pageX - mouseStartPos : evt.pageY - mouseStartPos,
                    newBarPos = barPos + mouseMovedBy;
                if (newBarPos < 0) { newBarPos = 0; }
                if (newBarPos > travelLength) { newBarPos = travelLength; }
                $bar.css(xy == 'x' ? 'left' : 'top', newBarPos);
                var pct = newBarPos / travelLength;
            }
        }
    });
}

// Set up the default options.
$.fn.scroller.defaults = {
    barPct : 25,
    onScroll : null
};

 })( jQuery );

    $('#scroll-track-v').scroller();
    $('#scroll-track-h').scroller();

Check the Updated jsfiddle http://jsfiddle.net/shinde87sagar/K4mW7/3/ 检查更新的jsfiddle http://jsfiddle.net/shinde87sagar/K4mW7/3/

I've updated your code to work using data objects. 我已经更新了您的代码以使用数据对象。 When you have multiple DOM elements being worked on in a plugin, you should explicitly state which objects you're referring to. 如果在插件中处理多个DOM元素,则应明确说明要引用的对象。 Keeping them global as you did makes it impossible for the mousemove and mouseup events to know which element to refer to. 保持它们的全局性使得mousemovemouseup事件无法知道要引用哪个元素。 This way is cleaner and you only have to worry about the scope inside each event handler. 这种方式更清晰,您只需要担心每个事件处理程序中的范围。

edit: this doesn't move the content pane yet, but this should give you an idea how to proceed correctly. 编辑:这还没有移动内容窗格,但这应该让你知道如何正确地进行。

http://jsfiddle.net/ozzy_og_kush/K4mW7/2/ http://jsfiddle.net/ozzy_og_kush/K4mW7/2/

$.fn.scroller = function( options ) {

    options = $.extend( $.fn.scroller.defaults, options );

    // Plugin code
    return this.each(function () {
        var $elem = $(this);            
        var xy = ($elem.width() > $elem.height() ? 'x' : 'y');
        var trackLength = (xy == 'x' ? $elem.width() : $elem.height());
        var barLength = (trackLength * options.barPct / 100) - 2;
        $elem.data({ 
            'scrolling' : false,
            'xy' : xy,
            'barPos' : 0,
            'mouseStartPos' : 0,
            'trackLength' : trackLength,
            'barLength' : barLength,
            'travelLength' : trackLength - barLength - 2
        });
        console.log($elem);
        var $bar = $('<div class="scroller-bar"></div>')
            .width($elem.data('xy') == 'x' ?
                       $elem.data('barLength') : 
                       $elem.innerWidth() - 2
            )
            .height($elem.data('xy') == 'x' ? 
                        $elem.innerHeight() - 2 : 
                        $elem.data('barLength')
            );
        $elem.append($bar).data('bar', $bar);

        $elem.on('mousedown', { elem : $elem }, function(evt) {
            evt.data.elem.data('scrolling', true);
            $thisBar = evt.data.elem.data('bar');
            $("body").addClass("noSelect"); 
            evt.data.elem.data('mouseStartPos', (
                evt.data.elem.data('xy') == 'x' ?
                    evt.pageX : 
                    evt.pageY
            ));
            evt.data.elem.data('barPos', (
                evt.data.elem.data('xy') == 'x' ?
                    $thisBar.position().left :
                    $thisBar.position().top
            ));
            $(document).on(
                'mousemove',
                { elem : evt.data.elem }, 
                HandleMouseMove
            );
        });

        $(document).on('mouseup', { elem : $elem }, function(evt) {
            if (evt.data.elem.data('scrolling') === true) {
                $("body").removeClass("noSelect");
                $(document).off('mousemove');
                mouseStartPos = 0;
                evt.data.elem.data('scrolling', false);
            }
        });

        HandleMouseMove = function(evt) {
            console.log(evt.data.elem.data('scrolling'));
            if (evt.data.elem.data('scrolling') === true) {
                var mouseMovedBy = (
                    evt.data.elem.data('xy') == 'x' ?
                        evt.pageX - evt.data.elem.data('mouseStartPos') :
                        evt.pageY - evt.data.elem.data('mouseStartPos')
                ),
                    newBarPos = evt.data.elem.data('barPos') + mouseMovedBy;
                if (newBarPos < 0) { newBarPos = 0; }
                if (newBarPos > evt.data.elem.data('travelLength')) {
                    newBarPos = evt.data.elem.data('travelLength'); 
                }
                evt.data.elem.data('bar').css(
                    (
                        evt.data.elem.data('xy') == 'x' ?
                            'left' : 
                            'top'
                    ),
                    newBarPos + "px"
                );
                //var pct = newBarPos / evt.data.elem.data('travelLength');
            }
        }
    });
}

// Set up the default options.
$.fn.scroller.defaults = {
    barPct : 25,
    onScroll : null
};

$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM