同一页面上的多个jQuery插件实例无效

时间:2014-10-16 14:19:29

标签: javascript jquery jquery-plugins

我在这个网站上搜索过但没找到我需要的东西 我的问题是我为旋转木马创建了一个jquery插件,它在1个实例上正常工作,但是如果我创建了多个实例,它只能在最后一个工作。

例如:     $( '#一个')smartCarousel(); //它不工作
    $( '#两个')smartCarousel()。 //它的工作

以下是插件代码:

;(function($){

// default options
var defaults = {
    slide : 1,
    autoPlay : false,
    autoPlayTime : 3000,
    speed : 400,
    next : false,
    prev : false,
    reverse : false,
    show : 4
}

// function
function sc(el, o){
    this.config = $.extend({}, defaults, o);
    this.el = el;
    this.init();
    return this;
}

// set init configurations
sc.prototype.init = function(){

    $this = this;
    // get children
    $this.children = $this.el.children();

    // wrape element, add basic css properties
    $this.el.wrap('<div class="smartCarouselWrapper clearfix"></div>')
        .css({
            position: 'absolute',
        }).parent().css({
            height: $this.el.outerHeight(true), // Height is setting on line 57
            width: '100%',
            overflow: 'hidden',
            position: 'relative'
        });

    // Show element by config
    // Calculate width by deviding wraper width
    // Set width of items
    $elw = $this.el.parent().width()/$this.config.show;
    $this.children.each(function(index, el) {
        $(this).width($elw);
    });

    w = $elw*$this.config.slide; // init width

    // get width, hadle diffrent width
    $this.children.each(function(index, el) {
        w += $(this).outerWidth(true);
    });

    // set lement width
    $this.el.width(w);

    // Set height for wrapper 
    $this.el.parent().height($this.el.outerHeight(true));

    // check if next handle assigned
    if ($this.config.next != false ) {
        $(this.config.next).click(function(e) {
            e.preventDefault()
            $this.next();
        });
    };

    // check if prev handle assigned
    if ($this.config.prev != false ) {
        $(this.config.prev).click(function(e) {
            e.preventDefault()
            $this.prev();
        });
    };

    $this.ready();
} // end of inti

sc.prototype.autoPlay = function(){
    // if reverse enabled
    if (this.config.reverse != false) { this.prev(); } else { this.next(); };
}

// do stuffs when ready
sc.prototype.ready = function(){
    if(this.config.autoPlay != false){
        this.timeOut = setTimeout('$this.autoPlay()', this.config.autoPlayTime);
    }
}

sc.prototype.next = function(){
    $this = this;

    clearTimeout($this.timeOut);


    l = 0; // left
    i = 0; // index

    // Add width to l from each element, limiting through slide
    $this.children.each(function(index, el) {
        if (i < $this.config.slide) {
            l -= $(this).outerWidth(true);
            //Clone first item after last for smooth animation
            $this.el.append($this.children.eq(i).clone());
            $this.children = $this.el.children();
        };
        i++;
    });

    // animat to show next items and appent prev items to end
    $this.el.stop().animate({
        left: l},
        $this.config.speed, function() {

            i = 0; // index
            $this.children.each(function(index, el) {
                if (i < $this.config.slide) {
                    $this.children.last().remove();
                    $this.children = $this.el.children();
                };
                i++;
            });

            i = 0;
            $this.children.each(function(index, el) {
                if (i < $this.config.slide) {
                    $(this).appendTo($this.el);
                    $this.el.css('left', parseInt($this.el.css('left'))+$(this).outerWidth(true));
                };
                i++;
            });
            $this.children = $this.el.children();
            $this.ready();
    });
} // end of next

sc.prototype.prev = function(){

    $this = this;

    clearTimeout($this.timeOut);

    l = 0; // left
    i = 0; // index

    //move last item to first through slide
    $this.children.each(function(index, el) {
        if (i < $this.config.slide) {

            //Clone first item after last for smooth animation
            $this.el.prepend($this.children.eq(($this.children.length-1)-i).clone());
            l -= $this.children.eq(($this.children.length-1)-i).outerWidth(true);
            $this.el.css('left', l);
            console.log(1);
        };
        i++;

    });
    console.log(l);
    $this.children = $this.el.children();
    // animate back to 0
    $this.el.stop().animate({left: 0}, $this.config.speed, function(){ 

        i = 0;
        $this.children.each(function(index, el) {
            if (i <= $this.config.slide) {
                $this.children.eq($this.children.length-i).remove();
            };
            i++;
        });

        $this.children = $this.el.children();
        $this.ready(); 
    });
} // end of prev

// plugin
if (typeof $.smartCarousel != 'function') {  
    $.fn.smartCarousel = function(o){
        if (this.length > 0) {
            new sc(this.first(), o);
        };
        return this;
    }
}else{
    console.log('Function already declared.');
    return this;
}

}(jQuery))

这里是html:

<ul class="smart-carousel-list clearfix" id="one"> <li><!-- Image here --> <h3>Premium Quality DATES</h3> </li> <li><!-- Image here --> <h3>Variety of Export Quality RICE</h3> </li> <li><!-- Image here --> <h3>Sports Goods</h3> </li> <li><!-- Image here --> <h3>Surgical Items</h3> </li> <li><!-- Image here --> <h3>Bad Sheets</h3> </li> <li><!-- Image here --> <h3>Towals</h3> </li> <li><!-- Image here --> <h3>Fruits & Vegetable</h3> </li> </ul>

这是CSS:

`

.smart-carousel{
    width: 100%;
    position: relative;
}
.smart-carousel-list{
    list-style: none;
    margin: 0;
    padding: 0;
}
.smart-carousel-list li {
    float: left;
    -webkit-box-sizing: border-box !important; /* Safari/Chrome, other WebKit */
    -moz-box-sizing: border-box !important;    /* Firefox, other Gecko */
    box-sizing: border-box !important;         /* Opera/IE 8+ */
}
.smart-carousel-nav{
    position: absolute;
    top: 0;
    z-index: 1000;
    opacity: 0;
    transition: opacity 0.4s;
    width: 100%;
}
.smart-carousel:hover .smart-carousel-nav{
    opacity: 1;
}
.smart-carousel-nav a{
    display: block;
    width: 29px;
    height: 28px;
    text-indent: -999999px;
    outline: none;
}
.smart-carousel-nav a.sc_next{
    background-image: url('next.png');
    margin-right: 10px;
    float: right;
}
.smart-carousel-nav a.sc_prev{
    background-image: url('prev.png');
    margin-left: 10px;
    float: left;
}


/**
 * STYLE FOR TYPE : Images;
 */

.smart-carousel.type-images .smart-carousel-list li img{
    max-width: 100%;
    display: block;
    margin: 0 auto;
}

/**
 * STYLE FOR TYPE : Products;
 */
.smart-carousel.type-products .smart-carousel-list li{
    border: solid 1px #efefef;
}
.smart-carousel.type-products .smart-carousel-list li img{
    max-width: 100%;
    display: block;
    margin: 0 auto;
}
.smart-carousel.type-products .smart-carousel-list li h3{
    width: 100%;
    font-size: 18px;
    margin: 0;
    padding: 0;
}
.smart-carousel.type-products .smart-carousel-list li h3 a{
    display: block;
    padding: 10px;
    font-weight: bold;
}
.smart-carousel.type-products .smart-carousel-list li h3 a span{
    float: right;
    font-weight: normal;
}

/**
 * STYLE FOR TYPE : Posts;
 */
.smart-carousel.type-posts .smart-carousel-list li{
    /*border: solid 1px #efefef;*/
}
.smart-carousel.type-posts .smart-carousel-list li img{
    max-width: 100%;
    display: block;
    margin: 0 auto;
}
.smart-carousel.type-posts .smart-carousel-list li h3{
    width: 100%;
    font-size: 18px;
    margin: 0;
    padding: 0;
}
.smart-carousel.type-posts .smart-carousel-list li h3 a{
    display: block;
    padding: 10px;
    font-weight: bold;
    text-align: center;
}
.smart-carousel.type-posts .smart-carousel-list li h3 a span{
    float: right;
    font-weight: normal;
}

`

2 个答案:

答案 0 :(得分:1)

您的插件一次只能连接到一个jQuery元素。你可以像这样改进:

// plugin
if (typeof $.smartCarousel != 'function') {
    $.fn.smartCarousel = function (o) {
        this.each(function(){
            // Connect to each jQuery element
            new sc($(this), o);
        });
        return this;
    }
} else {
    console.log('Function already declared.');
    return this;
}

至于其他问题,您可以在整个地方共享一个全局$this。我在你需要的地方添加了所有缺少的var $,并在计时器中正确引用它(通过匿名函数包装器,以便我可以引用本地$this):

JSFiddle:http://jsfiddle.net/TrueBlueAussie/b7u4635x/4/

;
(function ($) {

    // default options
    var defaults = {
        slide: 1,
        autoPlay: true,
        autoPlayTime: 1000,
        speed: 400,
        next: false,
        prev: false,
        reverse: false,
        show: 4
    }

    // function
        function sc(el, o) {
            this.config = $.extend({}, defaults, o);
            this.el = el;
            this.init();
            return this;
        }

        // set init configurations
        sc.prototype.init = function () {

            var $this = this;
            // get children
            $this.children = $this.el.children();

            // wrape element, add basic css properties
            $this.el.wrap('<div class="smartCarouselWrapper clearfix"></div>')
                .css({
                position: 'absolute',
            }).parent().css({
                height: $this.el.outerHeight(true), // Height is setting on line 57
                width: '100%',
                overflow: 'hidden',
                position: 'relative'
            });

            // Show element by config
            // Calculate width by deviding wraper width
            // Set width of items
            var $elw = $this.el.parent().width() / $this.config.show;
            $this.children.each(function (index, el) {
                $(this).width($elw);
            });

            var w = $elw * $this.config.slide; // init width

            // get width, hadle diffrent width
            $this.children.each(function (index, el) {
                w += $(this).outerWidth(true);
            });

            // set lement width
            $this.el.width(w);

            // Set height for wrapper 
            $this.el.parent().height($this.el.outerHeight(true));

            // check if next handle assigned
            if ($this.config.next != false) {
                $(this.config.next).click(function (e) {
                    e.preventDefault()
                    $this.next();
                });
            };

            // check if prev handle assigned
            if ($this.config.prev != false) {
                $(this.config.prev).click(function (e) {
                    e.preventDefault()
                    $this.prev();
                });
            };

            $this.ready();
        } // end of inti

        sc.prototype.autoPlay = function () {
            var $this = this;
            // if reverse enabled
            if ($this.config.reverse != false) {
                $this.prev();
            } else {
                $this.next();
            };
        }

        // do stuffs when ready
        sc.prototype.ready = function () {
            var $this = this;
            if ($this.config.autoPlay != false) {
                $this.timeOut = setTimeout(function(){$this.autoPlay();}, $this.config.autoPlayTime);
            }
        }

    sc.prototype.next = function () {
        var $this = this;

        clearTimeout($this.timeOut);


        var l = 0; // left
        var i = 0; // index

        // Add width to l from each element, limiting through slide
        $this.children.each(function (index, el) {
            if (i < $this.config.slide) {
                l -= $(this).outerWidth(true);
                //Clone first item after last for smooth animation
                $this.el.append($this.children.eq(i).clone());
                $this.children = $this.el.children();
            };
            i++;
        });

        // animat to show next items and appent prev items to end
        $this.el.stop().animate({
            left: l
        },
        $this.config.speed, function () {

            i = 0; // index
            $this.children.each(function (index, el) {
                if (i < $this.config.slide) {
                    $this.children.last().remove();
                    $this.children = $this.el.children();
                };
                i++;
            });

            i = 0;
            $this.children.each(function (index, el) {
                if (i < $this.config.slide) {
                    $(this).appendTo($this.el);
                    $this.el.css('left', parseInt($this.el.css('left')) + $(this).outerWidth(true));
                };
                i++;
            });
            $this.children = $this.el.children();
            $this.ready();
        });
    } // end of next

    sc.prototype.prev = function () {

        var $this = this;

        clearTimeout($this.timeOut);

        var l = 0; // left
        var i = 0; // index

        //move last item to first through slide
        $this.children.each(function (index, el) {
            if (i < $this.config.slide) {

                //Clone first item after last for smooth animation
                $this.el.prepend($this.children.eq(($this.children.length - 1) - i).clone());
                l -= $this.children.eq(($this.children.length - 1) - i).outerWidth(true);
                $this.el.css('left', l);
                console.log(1);
            };
            i++;

        });
        console.log(l);
        $this.children = $this.el.children();
        // animate back to 0
        $this.el.stop().animate({
            left: 0
        }, $this.config.speed, function () {

            i = 0;
            $this.children.each(function (index, el) {
                if (i <= $this.config.slide) {
                    $this.children.eq($this.children.length - i).remove();
                };
                i++;
            });

            $this.children = $this.el.children();
            $this.ready();
        });
    } // end of prev

    // plugin
    if (typeof $.smartCarousel != 'function') {
        $.fn.smartCarousel = function (o) {
            this.each(function () {
                new sc($(this), o);
            });
            return this;
        }
    } else {
        console.log('Function already declared.');
        return this;
    }

}(jQuery));

//$('.smart-carousel-list').smartCarousel();

$('#one').smartCarousel();
$('#two').smartCarousel();

答案 1 :(得分:0)

插件中有一个全局变量,因此插件无法使用多个元素,因为每次调用插件都会覆盖前一个实例的$this以定位新元素。

您只需在缺少的每个位置添加var

var $this = this;

这当然会破坏您尝试使用全局$this的任何其他地方(例如setTimeout('$this.autoplay()',200),因此您需要重新编写该部分代码以不执行自动播放()那样。