1. 程式人生 > >JS元件系列——Bootstrap元件福利篇:幾款好用的元件推薦

JS元件系列——Bootstrap元件福利篇:幾款好用的元件推薦

前言:之前分享過很多bootstrap常用元件,包括表格表單驗證檔案上傳複選下拉框彈出框等。這段時間,博主又收藏了一些好用的元件(有些在專案中已經用起來了),經過兩天的時間,已經整理出了一部分,本著“好東西要與人分享”的原則,今天還是來點福利,將博主收藏的東西分享出來,供需要的園友參考。元件大部分都是些開源元件,也有部分是博主自己在網上找到然後改寫出來的效果,可能不盡如人意,有興趣的且看看吧。

一、時間元件

 bootstrap風格的時間元件非常多,你可以在github上面隨便搜尋“datepicker”關鍵字,可以找到很多的時間元件。博主原來也用過其中的兩個,發現都會有一些大大小小的問題。經過一番篩選,找到一個效果不錯、能適用各種場景的時間元件,下面就來一睹它的風采吧。

1、效果展示

初始效果

元件中文化和日期格式自定義:只顯示日期

顯示日期和時間(手機、平板類裝置可能體驗會更好)

2、原始碼說明

初初看了下元件效果,還是給出 原始碼地址

3、程式碼示例

 首先引用需要的檔案

    <link href="~/Content/bootstrap/css/bootstrap.css" rel="stylesheet" />
    <link href="~/Content/bootstrap-datetimepicker-master/build/css/bootstrap-datetimepicker.css" rel="stylesheet"
/> <script src="~/Content/jquery-1.9.1.js"></script> <script src="~/Content/bootstrap/js/bootstrap.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment-with-locales.js"></script> <script src="~/Content/bootstrap-datetimepicker-master/build/js/bootstrap-datetimepicker.min.js"
></script>

JQuery和bootstrap是必須的。除此之外,還得引用 moment-with-locales.js 這個檔案,當然,你也可以不用這種cdn的方式,完全可以下載這個js檔案到你的本地,然後新增本地引用。

(1)初始效果

    <label class="control-label col-xs-3">日期:</label>
    <div class='input-group date' id='datetimepicker1'>
        <input type='text' class="form-control" />
        <span class="input-group-addon">
            <span class="glyphicon glyphicon-calendar"></span>
        </span>
    </div>
    <script type="text/javascript">
    $(function () {
        $('#datetimepicker1').datetimepicker();
    });
    </script>

這樣就能出現如上圖一效果。

(2)中文化和日期格式化

html部分不變。js初始化的時候增加引數即可。

    <script type="text/javascript">
    $(function () {
        $('#datetimepicker1').datetimepicker({
            format: 'YYYY-MM-DD',//日期格式化,只顯示日期
            locale: 'zh-CN'      //中文化
        });
    });
    </script>

(3)顯示時間

    <label class="control-label col-xs-3">時間:</label>
    <div class='input-group date' id='datetimepicker2'>
        <input type='text' class="form-control" />
        <span class="input-group-addon">
            <span class="glyphicon glyphicon-calendar"></span>
        </span>
    </div>
    <script type="text/javascript">
    $(function () {
        $('#datetimepicker2').datetimepicker({
            format: 'YYYY-MM-DD HH:mm:ss',
            locale: 'zh-CN'
        });
    });
    </script>

 (4)最大日期、最小日期

        $('#datetimepicker1').datetimepicker({
            format: 'YYYY-MM-DD',//日期格式化,只顯示日期
            locale: 'zh-CN',      //中文化
            maxDate: '2017-01-01',//最大日期
            minDate: '2010-01-01' //最小日期
        });

(5)啟用刪除按鈕

showClear: true

(6)View Mode屬性。設定瀏覽器選中模式

viewMode: 'years'

(7)其他

更多強大的功能可以參看API,這裡就不一一列舉。裡面有大量的屬性、事件、方法來滿足你各種特殊的需求。

二、自增器元件

關於bootstrap自增器,可能並非每一個專案裡面都需要用到。有一些特殊場景,比如:某一個文字框需要資料數字、陣列的大小需要微調等一些情況。說了半天,可能有園友都不知道它長啥樣,上點圖吧。

1、效果展示

其實效果很簡單,但它可以自動設定最大值、最小值、自增值還是挺方便的,並且可以自動做數字校驗。最最方便的是它不需要使用JavaScript去做初始化,只需要在html裡面初始化即可。

2、原始碼說明

3、程式碼示例

首先需要引用的檔案如下:

    <link href="~/Content/bootstrap/css/bootstrap.css" rel="stylesheet" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
    <link href="~/Content/jquery.spinner-master/dist/css/bootstrap-spinner.css" rel="stylesheet" />

    <script src="~/Content/jquery-1.9.1.js"></script>
    <script src="~/Content/bootstrap/js/bootstrap.js"></script>
    <script src="~/Content/jquery.spinner-master/dist/js/jquery.spinner.js"></script>

font-aweaome.min.css檔案是一個cdn引用的檔案,你也可以它引用到你的本地。

(1)初始化

<div class="input-group spinner" data-trigger="spinner">
    <input type="text" class="form-control text-center" value="1" data-rule="quantity">
    <span class="input-group-addon">
        <a href="javascript:;" class="spin-up" data-spin="up"><i class="fa fa-caret-up"></i></a>
        <a href="javascript:;" class="spin-down" data-spin="down"><i class="fa fa-caret-down"></i></a>
    </span>
</div>

就這麼一段簡單的html就能看到如上圖的效果,有沒有很easy~~

(2)自增型別

檢視元件的原始碼,可以看到在它裡面為我們定義了多種自增型別:

 

可以定義data-rule屬性為這些型別,比如:

 data-rule="month" 可以控制自增元件的規則是按照月的規則來進行。

(3)設定最大值、最小值、自增值

除了上面的幾種特定型別,元件還支援自定義最大值、最小值、自增值

<div class="input-group spinner" data-trigger="spinner">
    <input type="text" class="form-control text-center" value="1" data-min="-10" data-max="10" data-step="2" data-rule="quantity">
    <span class="input-group-addon">
        <a href="javascript:;" class="spin-up" data-spin="up"><i class="fa fa-caret-up"></i></a>
        <a href="javascript:;" class="spin-down" data-spin="down"><i class="fa fa-caret-down"></i></a>
    </span>
</div>
  • data-min="-10":最小值
  • data-max="10":最大值
  • data-step="2":自增值

 這個很好理解,不做過多說明。效果:

(4)事件捕捉

元件提供了兩個事件changed、changing,分別對應數值變化中和變化後的事件回撥。

$('#id').spinner('changed', function(e, newVal, oldVal) {

});

$('[data-trigger="spinner"]').spinner('changing', function(e, newVal, oldVal) {

});

三、載入效果

前幾天,有群友在問bootstrap的載入效果用什麼元件。其實百度搜索一下,也能找到很多的結果。在此,博主根據自己的使用經歷分享下幾個載入的小元件,希望大家用得著。主要分為實用型和炫酷型兩種。實用型效果一般,但能適用各種瀏覽器;炫酷型使用最新的css3和html5寫出來的,效果很炫,但基本上低版本的IE(10以下)都不能相容。

一、實用型

1、PerfectLoading元件

這個元件是博主在網上找到的一個js,但下載下來之後發現一些大大小小的問題,於是,博主改寫了下,命名為bootstrap-loading元件。它的原理就是在元件啟動的時候彈出一個覆蓋層,然後元件關閉時,將覆蓋層的dom移除,載入效果使用了一張gif的圖片。

PerfectLoad.js檔案內容:

/*******************************************
 * 
 * Plug-in:友好的頁面載入效果
 * Author:sqinyang ([email protected])
 * Time:2015/04/20
 * Explanation:隨著HTML5的流行,頁面效果越來越炫,同時也需要載入大量的外掛及素材,萬惡的網速,特別對於掛在國外伺服器的網站,一開啟一堆素材緩緩載入,位置錯亂不齊,故編寫此方法,方便大家使用
 *
*********************************************/

jQuery.bootstrapLoading = {
    start: function (options) {
        var defaults = {
            opacity: 1,
            //loading頁面透明度
            backgroundColor: "#fff",
            //loading頁面背景色
            borderColor: "#bbb",
            //提示邊框顏色
            borderWidth: 1,
            //提示邊框寬度
            borderStyle: "solid",
            //提示邊框樣式
            loadingTips: "Loading, please wait...",
            //提示文字
            TipsColor: "#666",
            //提示顏色
            delayTime: 1000,
            //頁面載入完成後,載入頁面漸出速度
            zindex: 999,
            //loading頁面層次
            sleep: 0
            //設定掛起,等於0時則無需掛起

        }
        var options = $.extend(defaults, options);

        //獲取頁面寬高
        var _PageHeight = document.documentElement.clientHeight,
        _PageWidth = document.documentElement.clientWidth;

        //在頁面未載入完畢之前顯示的loading Html自定義內容
        var _LoadingHtml = '<div id="loadingPage" style="position:fixed;left:0;top:0;_position: absolute;width:100%;height:' + _PageHeight + 'px;background:' + options.backgroundColor + ';opacity:' + options.opacity + ';filter:alpha(opacity=' + options.opacity * 100 + ');z-index:' + options.zindex + ';"><div id="loadingTips" style="position: absolute; cursor1: wait; width: auto;border-color:' + options.borderColor + ';border-style:' + options.borderStyle + ';border-width:' + options.borderWidth + 'px; height:80px; line-height:80px; padding-left:80px; padding-right: 5px;border-radius:10px;  background: ' + options.backgroundColor + ' url(/Content/bootstrap-loading/images/loading.gif) no-repeat 5px center; color:' + options.TipsColor + ';font-size:20px;">' + options.loadingTips + '</div></div>';

        //呈現loading效果
        $("body").append(_LoadingHtml);

        //獲取loading提示框寬高
        var _LoadingTipsH = document.getElementById("loadingTips").clientHeight,
        _LoadingTipsW = document.getElementById("loadingTips").clientWidth;

        //計算距離,讓loading提示框保持在螢幕上下左右居中
        var _LoadingTop = _PageHeight > _LoadingTipsH ? (_PageHeight - _LoadingTipsH) / 2 : 0,
        _LoadingLeft = _PageWidth > _LoadingTipsW ? (_PageWidth - _LoadingTipsW) / 2 : 0;

        $("#loadingTips").css({
            "left": _LoadingLeft + "px",
            "top": _LoadingTop + "px"
        });

        //監聽頁面載入狀態
        document.onreadystatechange = PageLoaded;

        //當頁面載入完成後執行
        function PageLoaded() {
            if (document.readyState == "complete") {
                var loadingMask = $('#loadingPage');

                setTimeout(function () {
                    loadingMask.animate({
                        "opacity": 0
                    },
                    options.delayTime,
                    function () {
                        $(this).hide();

                    });

                },
                options.sleep);

            }
        }
    },
    end: function () {
        $("#loadingPage").remove();
    }
}

這個js基本上是網上down下來的,只是在此基礎上博主加了一個end的方法。

來看看元件如何使用,下面是測試程式碼:

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>loading</title>

    <link href="~/Content/bootstrap/css/bootstrap.css" rel="stylesheet" />

    <script src="~/Content/jquery-1.9.1.js"></script>
    <script src="~/Content/bootstrap/js/bootstrap.js"></script>
    <script src="~/Content/bootstrap-loading/PerfectLoad.js"></script>
    <script type="text/javascript">
        $(function () {
            $("#btn_submit").on("click", function () {
                $.bootstrapLoading.start({ loadingTips: "正在處理資料,請稍候..." });
                $.ajax({
                    type: 'get',
                    url: '/Home/TestLoading',
                    data: {},
                    success: function (data, statu) {
                        debugger;
                    },
                    complete: function () {
                        $.bootstrapLoading.end();
                    }
                });
            })
            
        });
    </script>
</head>
<body>
    <div class="panel-body" style="padding:0px">
        <div class="panel panel-default" style="height:450px;">
            <div class="panel-heading">查詢條件</div>
            <div class="panel-body">
                <form id="formSearch" class="form-horizontal">
                    <div class="form-group">
                        <div class="col-xs-4">
                            <button type="button" id="btn_submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>載入測試</button>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
</body>
</html>

使用說明:元件不需要任何的html程式碼,只需要在執行loading的時候呼叫元件的start方法即可。 start()方法啟動彈出層,並可設定defaults 變數裡面的所有引數。當loading結束後再呼叫元件的end方法,自動將彈出層移除。來看看效果:

如果對效果不滿意,可自己設定defaults裡面的引數,註釋寫得很詳細,在此就不一一列舉了。

2、菊花載入元件spin.js

使用圖片顯示載入效果有它天生的弊端,所以現在很多的載入元件都使用css+js去實現動畫效果。spin.js就是其中一個例子,spin.js是一個開源元件,開源地址

下載原始碼後,初始化發現元件不帶遮罩的效果,只能這樣:

找了半天它的引數,硬是沒找到,亦或是哪裡有“機關”沒發現。沒辦法,博主只能自己加上遮罩的效果了。於是新建了一個css樣式檔案暫且命名為spin.css,裡面只有一個樣式:

.fade {
  position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 9999;
    opacity: 1;
     background-color: grey;
}

然後將spin.js改寫了兩個地方,改寫後的內容如下:

/**
 * Copyright (c) 2011-2014 Felix Gnass
 * Licensed under the MIT license
 * http://spin.js.org/
 *
 * Example:
    var opts = {
      lines: 12,            // The number of lines to draw
      length: 7,            // The length of each line
      width: 5,             // The line thickness
      radius: 10,           // The radius of the inner circle
      scale: 1.0,           // Scales overall size of the spinner
      corners: 1,           // Roundness (0..1)
      color: '#000',        // #rgb or #rrggbb
      opacity: 1/4,         // Opacity of the lines
      rotate: 0,            // Rotation offset
      direction: 1,         // 1: clockwise, -1: counterclockwise
      speed: 1,             // Rounds per second
      trail: 100,           // Afterglow percentage
      fps: 20,              // Frames per second when using setTimeout()
      zIndex: 2e9,          // Use a high z-index by default
      className: 'spinner', // CSS class to assign to the element
      top: '50%',           // center vertically
      left: '50%',          // center horizontally
      shadow: false,        // Whether to render a shadow
      hwaccel: false,       // Whether to use hardware acceleration (might be buggy)
      position: 'absolute'  // Element positioning
    };
    var target = document.getElementById('foo');
    var spinner = new Spinner(opts).spin(target);
 */
;(function(root, factory) {
  if (typeof module == 'object' && module.exports) module.exports = factory(); // CommonJS
  else if (typeof define == 'function' && define.amd) define(factory); // AMD module
  else root.Spinner = factory(); // Browser global
}
(this, function() {
  'use strict';

  var prefixes = ['webkit', 'Moz', 'ms', 'O']; // Vendor prefixes
  var animations = {}; // Animation rules keyed by their name
  var useCssAnimations; // Whether to use CSS animations or setTimeout
  var sheet; // A stylesheet to hold the @keyframe or VML rules

  /**
   * Utility function to create elements. If no tag name is given,
   * a DIV is created. Optionally properties can be passed.
   */
  function createEl(tag, prop) {
    var el = document.createElement(tag || 'div');
    var n;

    for (n in prop) el[n] = prop[n];
    return el;
  }

  /**
   * Appends children and returns the parent.
   */
  function ins(parent /* child1, child2, ...*/) {
    for (var i = 1, n = arguments.length; i < n; i++) {
      parent.appendChild(arguments[i]);
    }

    return parent;
  }

  /**
   * Creates an opacity keyframe animation rule and returns its name.
   * Since most mobile Webkits have timing issues with animation-delay,
   * we create separate rules for each line/segment.
   */
  function addAnimation(alpha, trail, i, lines) {
    var name = ['opacity', trail, ~~(alpha * 100), i, lines].join('-');
    var start = 0.01 + i/lines * 100;
    var z = Math.max(1 - (1-alpha) / trail * (100-start), alpha);
    var prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase();
    var pre = prefix && '-' + prefix + '-' || '';

    if (!animations[name]) {
      sheet.insertRule(
        '@' + pre + 'keyframes ' + name + '{' +
        '0%{opacity:' + z + '}' +
        start + '%{opacity:' + alpha + '}' +
        (start+0.01) + '%{opacity:1}' +
        (start+trail) % 100 + '%{opacity:' + alpha + '}' +
        '100%{opacity:' + z + '}' +
        '}', sheet.cssRules.length);

      animations[name] = 1;
    }

    return name;
  }

  /**
   * Tries various vendor prefixes and returns the first supported property.
   */
  function vendor(el, prop) {
    var s = el.style;
    var pp;
    var i;

    prop = prop.charAt(0).toUpperCase() + prop.slice(1);
    if (s[prop] !== undefined) return prop;
    for (i = 0; i < prefixes.length; i++) {
      pp = prefixes[i]+prop;
      if (s[pp] !== undefined) return pp;
    }
  }

  /**
   * Sets multiple style properties at once.
   */
  function css(el, prop) {
    for (var n in prop) {
      el.style[vendor(el, n) || n] = prop[n];
    }

    return el;
  }

  /**
   * Fills in default values.
   */
  function merge(obj) {
    for (var i = 1; i < arguments.length; i++) {
      var def = arguments[i];
      for (var n in def) {
        if (obj[n] === undefined) obj[n] = def[n];
      }
    }
    return obj;
  }

  /**
   * Returns the line color from the given string or array.
   */
  function getColor(color, idx) {
    return typeof color == 'string' ? color : color[idx % color.length];
  }

  // Built-in defaults

  var defaults = {
    lines: 12,            // The number of lines to draw
    length: 7,            // The length of each line
    width: 5,             // The line thickness
    radius: 10,           // The radius of the inner circle
    scale: 1.0,           // Scales overall size of the spinner
    corners: 1,           // Roundness (0..1)
    color: '#000',        // #rgb or #rrggbb
    opacity: 1/4,         // Opacity of the lines
    rotate: 0,            // Rotation offset
    direction: 1,         // 1: clockwise, -1: counterclockwise
    speed: 1,             // Rounds per second
    trail: 100,           // Afterglow percentage
    fps: 20,              // Frames per second when using setTimeout()
    zIndex: 2e9,          // Use a high z-index by default
    className: 'spinner', // CSS class to assign to the element
    top: '50%',           // center vertically
    left: '50%',          // center horizontally
    shadow: false,        // Whether to render a shadow
    hwaccel: false,       // Whether to use hardware acceleration
    position: 'absolute'  // Element positioning
  };

  /** The constructor */
  function Spinner(o) {
    this.opts = merge(o || {}, Spinner.defaults, defaults);
  }

  // Global defaults that override the built-ins:
  Spinner.defaults = {};

  merge(Spinner.prototype, {
    /**
     * Adds the spinner to the given target element. If this instance is already
     * spinning, it is automatically removed from its previous target b calling
     * stop() internally.
     */
    spin: function(target) {
      this.stop();

      var self = this;
      var o = self.opts;
      var el = self.el = createEl(null, {className: o.className});

      css(el, {
        position: o.position,
        width: 0,
        zIndex: o.zIndex,
        left: o.left,
        top: o.top
      });

      if (target) {
          target.insertBefore(el, target.firstChild || null);
          target.className = "fade";
      }

      el.setAttribute('role', 'progressbar');
      self.lines(el, self.opts);

      if (!useCssAnimations) {
        // No CSS animation support, use setTimeout() instead
        var i = 0;
        var start = (o.lines - 1) * (1 - o.direction) / 2;
        var alpha;
        var fps = o.fps;
        var f = fps / o.speed;
        var ostep = (1 - o.opacity) / (f * o.trail / 100);
        var astep = f / o.lines;

        (function anim() {
          i++;
          for (var j = 0; j < o.lines; j++) {
            alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity);

            self.opacity(el, j * o.direction + start, alpha, o);
          }
          self.timeout = self.el && setTimeout(anim, ~~(1000 / fps));
        })();
      }
      
      return self;
    },

    /**
     * Stops and removes the Spinner.
     */
    stop: function() {
      var el = this.el;
      if (el) {
        clearTimeout(this.timeout);
        if (el.parentNode) {
            var reg = new RegExp('(\\s|^)fade(\\s|$)');
            el.parentNode.className = el.parentNode.className.replace(reg, ' ');
            el.parentNode.removeChild(el);
        }
        this.el = undefined;
      }
      return this;
    },

    /**
     * Internal method that draws the individual lines. Will be overwritten
     * in VML fallback mode below.
     */
    lines: function(el, o) {
      var i = 0;
      var start = (o.lines - 1) * (1 - o.direction) / 2;