bootstrap源码学习与示例:bootstrap-button

梁丘俊人
2023-12-01

今天开始说非常简单的bootstrap-button组件。

button设计得非常smart,只有一个调用接口,你可以在$().button(str)中传入不同的字符串,来切换它的文本,其中有三个是框架占用的——toggle, reset, loading。

button的文本切换是通过data-xxx-text自定义属性控制。$().button("xxx"),就是取data-aaa-text的值作为新文本。如果要还原最初状态,使用$().button("reset")。loading参数会在这基础上添加disabled类名与disabled属性,目的是不让人家修改。

button的类型是通过data-toggle自定义属性决定,目前有三种。普通的单个按钮,checked类型的按钮组,radio类型的按钮组,分别对应button, buttons-checked, buttons-radio。

要使用bootstrap的样式,必须加btn类名。皮肤在通用样式名前加个btn-前缀,即.btn-primary, .btn-warning, .btn-danger, .btn-success, .btn-info, .btn-inverse

除了切换文本需要你动手外,切换状态的点击事件组件已经为你做好了,你只要引入它就能用了。

!function ($) {

    "use strict"; // jshint ;_;

    /* BUTTON PUBLIC CLASS DEFINITION
  * ============================== */
    var Button = function (element, options) {
        this.$element = $(element)
        this.options = $.extend({}, $.fn.button.defaults, options)
    }

    Button.prototype.setState = function (state) {
        var d = 'disabled'
        , $el = this.$element
        , data = $el.data()
        , val = $el.is('input') ? 'val' : 'html'//如果是button标签,使用html方法

        state = state + 'Text'
        //如果是reset,则变成resetText保留起来,换言之reset对框架而言是个保留字
        data.resetText || $el.data('resetText', $el[val]())
        //切换文本
        $el[val](data[state] || this.options[state])
        //如果是loading,那么它就添加一个disabled类名与disabled属性,换言之reset对框架而言是个保留字
        setTimeout(function () {
            state == 'loadingText' ?
            $el.addClass(d).attr(d, d) :
            $el.removeClass(d).removeAttr(d)
        }, 0)
    }
    //这个用于按钮组,通过$().button('toggle')调用
    Button.prototype.toggle = function () {
        var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
        //radio具有排他性,只有一个按钮组只有一个按钮存在激活状态
        $parent && $parent
        .find('.active')
        .removeClass('active')
      
        this.$element.toggleClass('active')
    }


    var old = $.fn.button

    /* BUTTON PLUGIN DEFINITION
  * ======================== */
    $.fn.button = function (option) {
        return this.each(function () {
            var $this = $(this)
            , data = $this.data('button')
            , options = typeof option == 'object' && option
            //重复利用之前的实例
            if (!data) $this.data('button', (data = new Button(this, options)))
            if (option == 'toggle') data.toggle()
            else if (option) data.setState(option)
        })
    }

    $.fn.button.defaults = {
        loadingText: 'loading...'
    }

    $.fn.button.Constructor = Button

    /* BUTTON NO CONFLICT
  * ================== */
    $.fn.button.noConflict = function () {
        $.fn.button = old
        return this
    }

    /* BUTTON DATA-API
  * =============== */
 //为存在data-toggle属性,并且其值以button开头的按钮绑定点击事件
    $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
        var $btn = $(e.target)
        if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
        $btn.button('toggle')
    })

}(window.jQuery);
<!DOCTYPE html> <html> <head> <title>bootstrap学习 by 司徒正美</title> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <link rel="stylesheet" href="http://files.cnblogs.com/rubylouvre/bootstrap.css"/> <script src="http://files.cnblogs.com/rubylouvre/jquery1.83.js" > </script> <script src="http://files.cnblogs.com/rubylouvre/bootstrap-transition.js"></script> <script src="http://files.cnblogs.com/rubylouvre/bootstrap-button.js"></script> <script> $(function(){ var btn = $("#example1") btn.click(function(){ btn.button('loading'); setTimeout(function(){ btn.button("reset") },1200) }) new function(){ var btn = $("#example2") btn.click(function(){ btn.button('complete'); setTimeout(function(){ btn.button("reset") },1200) }) } new function(){ var btn = $("#example3") btn.click(function(){ btn.button('error'); setTimeout(function(){ btn.button("reset") },1200) }) } new function(){ var btn = $("#example4") btn.click(function(){ btn.button('error'); setTimeout(function(){ btn.button("first") },600) setTimeout(function(){ btn.button("second") },1600) setTimeout(function(){ btn.button("third") },2400) setTimeout(function(){ btn.button("reset") },3400) }) } }) </script> </head> <body> <button type="button" id="example1" class="btn btn-primary" data-loading-text="加载中...">第一个按钮</button> <button type="button" id="example2" class="btn btn-info" data-complete-text="完成了..">换一个文本提示属性</button> <button type="button" id="example3" class="btn btn-error" data-error-text="出错了..">换另一个文本提示属性</button> <button type="button" id="example4" class="btn btn-success" data-first-text="状态1.." data-second-text="状态2.." data-third-text="状态3..">同时有多个文本提示属性</button> <p>点击切换示例,添加一个active类名</p> <div> <p>data-toggle="button"</p> <button type="button" id="example5" class="btn btn-primary" data-toggle="button">这是单个按钮切换状态</button> </div> <p>data-toggle="buttons-checkbox"</p> <div class="btn-group" data-toggle="buttons-checkbox"> <button type="button" class="btn btn-primary">Left</button> <button type="button" class="btn btn-primary">Middle</button> <button type="button" class="btn btn-primary">Right</button> </div> <p>data-toggle="buttons-radio"</p> <div class="btn-group" data-toggle="buttons-radio"> <button type="button" class="btn btn-primary">Left</button> <button type="button" class="btn btn-primary">Middle</button> <button type="button" class="btn btn-primary">Right</button> </div> </body> </html>

运行代码

以下是它对应的less,生成的CSS大概是它的五倍以上。


//
// Buttons
// --------------------------------------------------


// Base styles
// --------------------------------------------------

// Core
.btn {
  display: inline-block;
  .ie7-inline-block();
  padding: 4px 12px;
  margin-bottom: 0; // For input.btn
  font-size: @baseFontSize;
  line-height: @baseLineHeight;
  text-align: center;
  vertical-align: middle;
  cursor: pointer;
  .buttonBackground(@btnBackground, @btnBackgroundHighlight, @grayDark, 0 1px 1px rgba(255,255,255,.75));
  border: 1px solid @btnBorder;
  *border: 0; // Remove the border to prevent IE7's black border on input:focus
  border-bottom-color: darken(@btnBorder, 10%);
  .border-radius(@baseBorderRadius);
  .ie7-restore-left-whitespace(); // Give IE7 some love
  .box-shadow(~"inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)");

  // Hover state
  &:hover {
    color: @grayDark;
    text-decoration: none;
    background-position: 0 -15px;

    // transition is only when going to hover, otherwise the background
    // behind the gradient (there for IE<=9 fallback) gets mismatched
    .transition(background-position .1s linear);
  }

  // Focus state for keyboard and accessibility
  &:focus {
    .tab-focus();
  }

  // Active state
  &.active,
  &:active {
    background-image: none;
    outline: 0;
    .box-shadow(~"inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)");
  }

  // Disabled state
  &.disabled,
  &[disabled] {
    cursor: default;
    background-image: none;
    .opacity(65);
    .box-shadow(none);
  }

}



// Button Sizes
// --------------------------------------------------

// Large
.btn-large {
  padding: @paddingLarge;
  font-size: @fontSizeLarge;
  .border-radius(@borderRadiusLarge);
}
.btn-large [class^="icon-"],
.btn-large [class*=" icon-"] {
  margin-top: 4px;
}

// Small
.btn-small {
  padding: @paddingSmall;
  font-size: @fontSizeSmall;
  .border-radius(@borderRadiusSmall);
}
.btn-small [class^="icon-"],
.btn-small [class*=" icon-"] {
  margin-top: 0;
}
.btn-mini [class^="icon-"],
.btn-mini [class*=" icon-"] {
  margin-top: -1px;
}

// Mini
.btn-mini {
  padding: @paddingMini;
  font-size: @fontSizeMini;
  .border-radius(@borderRadiusSmall);
}


// Block button
// -------------------------

.btn-block {
  display: block;
  width: 100%;
  padding-left: 0;
  padding-right: 0;
  .box-sizing(border-box);
}

// Vertically space out multiple block buttons
.btn-block + .btn-block {
  margin-top: 5px;
}

// Specificity overrides
input[type="submit"],
input[type="reset"],
input[type="button"] {
  &.btn-block {
    width: 100%;
  }
}



// Alternate buttons
// --------------------------------------------------

// Provide *some* extra contrast for those who can get it
.btn-primary.active,
.btn-warning.active,
.btn-danger.active,
.btn-success.active,
.btn-info.active,
.btn-inverse.active {
  color: rgba(255,255,255,.75);
}

// Set the backgrounds
// -------------------------
.btn {
  // reset here as of 2.0.3 due to Recess property order
  border-color: #c5c5c5;
  border-color: rgba(0,0,0,.15) rgba(0,0,0,.15) rgba(0,0,0,.25);
}
.btn-primary {
  .buttonBackground(@btnPrimaryBackground, @btnPrimaryBackgroundHighlight);
}
// Warning appears are orange
.btn-warning {
  .buttonBackground(@btnWarningBackground, @btnWarningBackgroundHighlight);
}
// Danger and error appear as red
.btn-danger {
  .buttonBackground(@btnDangerBackground, @btnDangerBackgroundHighlight);
}
// Success appears as green
.btn-success {
  .buttonBackground(@btnSuccessBackground, @btnSuccessBackgroundHighlight);
}
// Info appears as a neutral blue
.btn-info {
  .buttonBackground(@btnInfoBackground, @btnInfoBackgroundHighlight);
}
// Inverse appears as dark gray
.btn-inverse {
  .buttonBackground(@btnInverseBackground, @btnInverseBackgroundHighlight);
}


// Cross-browser Jank
// --------------------------------------------------

button.btn,
input[type="submit"].btn {

  // Firefox 3.6 only I believe
  &::-moz-focus-inner {
    padding: 0;
    border: 0;
  }

  // IE7 has some default padding on button controls
  *padding-top: 3px;
  *padding-bottom: 3px;

  &.btn-large {
    *padding-top: 7px;
    *padding-bottom: 7px;
  }
  &.btn-small {
    *padding-top: 3px;
    *padding-bottom: 3px;
  }
  &.btn-mini {
    *padding-top: 1px;
    *padding-bottom: 1px;
  }
}


// Link buttons
// --------------------------------------------------

// Make a button look and behave like a link
.btn-link,
.btn-link:active,
.btn-link[disabled] {
  background-color: transparent;
  background-image: none;
  .box-shadow(none);
}
.btn-link {
  border-color: transparent;
  cursor: pointer;
  color: @linkColor;
  .border-radius(0);
}
.btn-link:hover {
  color: @linkColorHover;
  text-decoration: underline;
  background-color: transparent;
}
.btn-link[disabled]:hover {
  color: @grayDark;
  text-decoration: none;
}

 类似资料: