Bootstrap中不乏很多优秀的小插件来让界面更加漂亮。比如之前做过笔记的bootstrap-fileinput,select2,datetimepicker等都是属于这一系列的。这些相对而言比较大一点。其他还有一些比较轻比较小的插件,也很好,特此开篇来记录一下。

  由于是基于bootstrap的插件,所以基本上所有插件都是需要bootstrap和jquery相关文件的。也就是说下面的说明中我们默认页面上已经有了:

  1. <link href="/static/css/bootstrap.min.css" rel="stylesheet" />
  2.  
  3. <script src="/static/js/jquery.min.js"></script>
  4. <script src="/static/js/bootstrap.min.js"></script>

■  ladda-bootstrap

  转自【http://www.cnblogs.com/landeanfen/p/5603790.html#_label3】

  按钮通常是发起ajax请求或提交表单数据的第一入口,有时候点击按钮发送请求之后反应会比较慢,如果用户等不及了再按一下按钮就导致重复请求了。这个就很僵硬了。

  这个插件可以让我们点击按钮之后让按钮出现转菊花,并且禁用。虽说自己实现逻辑也不复杂,不过这个很好看。

  这个插件在github上的地址是:【https://github.com/msurguy/ladda-bootstrap】,使用这个插件需要引入的静态文件有:

  1. <link href="/static/ladda-bootstrap/dist/ladda-themeless.min.css" rel="stylesheet" />
  2.  
  3. <script src="/static/ladda-bootstrap/dist/spin.min.js"></script>
  4. <script src="/static/ladda-bootstrap/dist/ladda.min.js"></script>

  然后HTML是一个简单的按钮,但是需要加入一些class和新的属性:

  1. <button type="button" class="btn btn-primary ladda-button" data-style="expand-right" id="testbtn"><span class="ladda-label">测试</span></button>

  然后是js初始化这个按钮:

  1. $(document).ready(function(){
  2. $('#testbtn').click(function(event){
  3. var l = Ladda.create(this);
  4. l.start(); //启动动画,禁用按钮
  5. l.setProgress(0-1); //设置进度条
  6. /* 做这个按钮该做的操作 */
  7. l.stop(); //结束动画,启用按钮
  8. });
  9. });

  首先需要注意的是,Ladda.create方法的参数不是一个jquery对象而是一个DOM对象(所以我们用this而不是$(this)),这一点在click外面写时尤其重要。比如我和一个bootstrap-table结合起来,点击按钮时触发bootstrap-table的refresh事件:

  1. $('#table').bootstrapTable({
  2. /*其他参数*/
  3. onLoadSuccess: function(data){
  4. var l = Ladda.create($('#testbtn')[0]);
  5. l.stop();
  6. }
  7. });
  8.  
  9. $('#testbtn').click(function(event){
  10. var l = Ladda.create(this);
  11. l.start();
  12. l.setProgress(0-1);
  13. $('#table').bootstrapTable('refresh'); //触发refresh事件
  14. });

  然后再来看button的data-style属性。这个属性指出了按钮的动画以何种形式出现。expand-right是按钮先扩展然后在文字右边出现一个转菊花。除了这个还有以下这些data-style可以选择:

  expand-left , expand-up , expand-down

  zoom-in , zoom-out  文字先放大/缩小淡出,然后菊花淡入

  slide-up/down/left/right  文字向指定方向划出,然后菊花淡入

  此外,button也有一些属性可以进一步定制这个组件的样式,比如

  data-spinner-color  可以指定转菊花时菊花的颜色,值是类似于'#6600ff'这种

  

  最后再说下,setProgress是个什么东西。这个组件其实默认会给按钮上加上一个进度条,反映在界面上就是文字退出按钮的时间的快慢。作为实用的话这个方法肯定是要在某个回调函数中调用的。参数设置0到1间的某个实数来体现进度条。

■  bootstrap-switch

  这个插件可以帮我们方便地实现像IOS那样风格的开关按钮。开关这个东西,本质上是一个checkbox(分成开和关两种状态,多个开关之间互相不关联)。

  源码下载:【https://github.com/Bttstrp/bootstrap-switch】

  官方文档:【http://bootstrapswitch.com/options.html】

  使用:

  需要引用的文件:

  1. <link href="/static/bootstrap-switch/dist/css/bootstrap3/bootstrap-switch.min.css" rel="stylesheet" />
  2.  
  3. <script src="/static/bootstrap-switch/dist/js/bootstrap-switch.min.js"></script>

  HTML:

  1. <input type="checkbox" id="testswitch" checked />

  JS:

  1. $(document).ready(function(){
  2. $('#testswtich').bootstrapSwtich({
  3. size: 'mini'
  4. });
  5. });

  这是基本用法,就可以渲染出一个开关了。开关的取值和一般的checkbox一致,只需要$('#testswitch').prop('checked')或者is(':checked')来获取true和false

  事件的话和普通checkbox不同,无法通过change方法绑定事件处理函数。而是要在初始化时定义好处理函数比如有这些事件:
  onSwitchChange  最主要的事件,定义开关切换状态时触发的事件的处理函数,绑定的函数有两个参数,分别是事件对象event和data(该switch做完变化后的状态,true和false)

  onInit  初始化时发生的事件

  绑定事件的具体方式是$('#test').bootstrapSwitch('onSwitchChange',function(event,data){...})

  另外这些是初始化时的参数:

  size  指定组件大小,从小到大有mini,small,normal,large等

  onColor,offColor  指定开关状态时开关的颜色,可选值有success,warning,primary,info,danger,default

  onText,offText  指定开关状态下显示的文字,默认是ON和OFF

  state  设置默认状态下是开是关

  inverse  默认情况下开在按钮左边关在右边,设置inverse参数为true时倒过来

  handleWidth  设置开关宽度,单位为px,可设置成'auto'

  

  在此额外提一下(也是一个比较通用的知识点)如果不想在初始化时设置这些参数,可以在初始化方法外面进行全局设定的重写,方法是:

  1. $.fn.bootstrapSwitch.defaults.size = 'large';
  2. $.fn.bootstrapSwitch.defaults.onColor = 'sucess';

■  步骤条ystep

  步骤条是开发流程、多步骤表单时常用的一种组件。ystep这个组件是由一位叫杨园的前辈(https://github.com/iyangyuan/ystep)开发的,轻量级的步骤条组件。然后我还结合了这篇文章对插件做了一些定制化的内容。

  首先引入文件:

  1. <link href="{% static 'ystep-master/css/ystep.css' %}" rel="stylesheet" />
  2. <script src="{% static 'js/skill.js' %}"></script>

  然后HTML上写一个div:

  1. <div id="teststep"></div>

  然后是JS来初始化:

  1. $(document).ready(function(){
  2. $('#teststep').loadStep({
  3. //size: 'small',
  4. size: 'large',
  5. color: 'blue',
  6. steps: [{
  7. title: '第一步',
  8. content: '打开冰箱门'
  9. },{
  10. title: '第二步',
  11. content: '把大象塞进冰箱'
  12. },{
  13. title: '第三步',
  14. content: '把冰箱门带上'
  15. },{
  16. title: '第四步',
  17. content: '完成'
  18. }
  19. ]
  20. }).setStep(0);
  21. });

  size指出了步骤条大小,只有large和small两个选项。color是颜色风格,有blue和green两种。steps是步骤条主题,title是步骤名称,content是鼠标悬浮在步骤名附近时给出的关于步骤详细内容的提示信息。

  先来说说方法,setStep(n)可以将当前步骤条调整到第n步(是0开始的),getStep()获取当前第几步,nextStep和prevStep是前后调整。

  ●  自己的一些小修改

  结合上面给出的第二篇文章,ystep这个组件还存在一些小缺点。其实最困扰我的还是大小问题。虽然提供了large这个选项,但是整个步骤条还是一个比较短的状态,我想让它变长,最好是达到100%容器的宽度。于是我在ystep.js中做出了如下修改:

  1. /*在540行附近的large参数的函数,如果愿意改small或者新增一个自定义的参数也是可以的*/
  2. large: function($html){
  3. var stepCount = $html.find("li").length-1,
  4. /* beg 将原来写死的px值换成百分比 */
  5. containerWidth = "100%";
  6. progressWidth = "100%";
  7. progressbarWidth = ((stepCount/(stepCount+1))*100)+"%";
  8. /* end */
  9. $html.css({
  10. width: containerWidth
  11. });
  12. $html.find(".ystep-progress").css({
  13. width: progressWidth
  14. });
  15. $html.find(".ystep-progress-bar").css({
  16. width: progressbarWidth //原来progress和progress-bar长度一样,现在应该让progress-bar比progress略短一些,具体短多少看上面公式
  17. });
  18. $html.addClass("ystep-lg");
  19. }

以及

  1. /* 在600行附近新增调整每个步骤margin-right的值的逻辑 */
  2. //调整步骤margin以对齐
  3. var containerWidth = $n.width();
  4. var fullStepCount = $baseHtml.find('li').length;
  5. var modify = ( containerWidth - fullStepCount * 100 ) / fullStepCount;
  6. $n.find('li').css('margin-right',modify+'px');

  通过这样渲染出来的步骤条,它就是一个长度可以填满.ystep-container这个div相当一部分的步骤条了。不能做到填满到100%是因为progress的进度逻辑和宽度逻辑是不相符的,如果progressbarWidth和progressWidth一样保持100%,那么调用一次nextStep(或者其他方法)后进度条不会刚好走到步骤条节点上而是有所出入。如果要改进度逻辑,那么就要修改各个方法了,有点麻烦,所以走了简单的路改宽度逻辑。

  如此修改之后得到的步骤条还是有些不好的地方,就是会往左边偏一点。想要去除这个可以看情况把#teststep这个div加上一个col-lg-offset-x的class,尽量把.ystep-container这个div调整到画面中间。

■  遮罩效果

  在发起ajax之后等场景下,可能需要页面出现一个所谓的遮罩效果,防止用户在这段时间内做出多余的操作。遮罩的基本思路就是在页面上添加一个覆盖所有元素(从CSS的角度上来看z-index较大)的div,并添加一些提示信息和进出效果,提示信息可以分为简单的文字提示,也可以有转菊花等比较好看的提示,转菊花又可以分成图片实现(直接插入一张gif图)和css/js实现。

  虽然整体而言,自己实现遮罩起来也不困难,但是也有一些现成的组件可以使用。比如这位大神提到的一些:【http://www.cnblogs.com/landeanfen/p/5461849.html#_label2】

  1. 简单的单层遮罩

  组件很简单,就是一个js文件:

  1. /*******************************************
  2. *
  3. * Plug-in:友好的页面加载效果
  4. * Author:sqinyang (sqinyang@sina.com)
  5. * Time:2015/04/20
  6. * Explanation:随着HTML5的流行,页面效果越来越炫,同时也需要加载大量的插件及素材,万恶的网速,特别对于挂在国外服务器的网站,一打开一堆素材缓缓加载,位置错乱不齐,故编写此方法,方便大家使用
  7. *
  8. *********************************************/
  9.  
  10. jQuery.bootstrapLoading = {
  11. start: function (options) {
  12. var defaults = {
  13. opacity: 1,
  14. //loading页面透明度
  15. backgroundColor: "#fff",
  16. //loading页面背景色
  17. borderColor: "#bbb",
  18. //提示边框颜色
  19. borderWidth: 1,
  20. //提示边框宽度
  21. borderStyle: "solid",
  22. //提示边框样式
  23. loadingTips: "Loading, please wait...",
  24. //提示文本
  25. TipsColor: "#666",
  26. //提示颜色
  27. delayTime: 1000,
  28. //页面加载完成后,加载页面渐出速度
  29. zindex: 999,
  30. //loading页面层次
  31. sleep: 0
  32. //设置挂起,等于0时则无需挂起
  33.  
  34. }
  35. var options = $.extend(defaults, options);
  36.  
  37. //获取页面宽高
  38. var _PageHeight = document.documentElement.clientHeight,
  39. _PageWidth = document.documentElement.clientWidth;
  40.  
  41. //在页面未加载完毕之前显示的loading Html自定义内容
  42. 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>';
  43.  
  44. //呈现loading效果
  45. $("body").append(_LoadingHtml);
  46.  
  47. //获取loading提示框宽高
  48. var _LoadingTipsH = document.getElementById("loadingTips").clientHeight,
  49. _LoadingTipsW = document.getElementById("loadingTips").clientWidth;
  50.  
  51. //计算距离,让loading提示框保持在屏幕上下左右居中
  52. var _LoadingTop = _PageHeight > _LoadingTipsH ? (_PageHeight - _LoadingTipsH) / 2 : 0,
  53. _LoadingLeft = _PageWidth > _LoadingTipsW ? (_PageWidth - _LoadingTipsW) / 2 : 0;
  54.  
  55. $("#loadingTips").css({
  56. "left": _LoadingLeft + "px",
  57. "top": _LoadingTop + "px"
  58. });
  59.  
  60. //监听页面加载状态
  61. document.onreadystatechange = PageLoaded;
  62.  
  63. //当页面加载完成后执行
  64. function PageLoaded() {
  65. if (document.readyState == "complete") {
  66. var loadingMask = $('#loadingPage');
  67.  
  68. setTimeout(function () {
  69. loadingMask.animate({
  70. "opacity": 0
  71. },
  72. options.delayTime,
  73. function () {
  74. $(this).hide();
  75.  
  76. });
  77.  
  78. },
  79. options.sleep);
  80.  
  81. }
  82. }
  83. },
  84. end: function () {
  85. $("#loadingPage").remove();
  86. }
  87. }

  然后在我们自己的页面可以这样调用(当然,默认已经导入了bootstrap的js和css以及jquery):

  1. $('#test').click(function(event){
  2. event.preventDefault();
  3.  
  4. // 显示遮罩
  5. $.bootstrapLoading.start({
  6. //一些初始化参数,可以参考组件代码中的default中的字段
  7. loadingTips: '正在加载中...',
  8. backgroundColor: '#EEE8CD',
  9. opacity: 0.8
  10. });
  11. //做一些耗时操作如ajax请求等,如果是ajax那么关闭遮罩的方法end可以在complete参数指定的函数中调用
  12.  
  13. // 关闭遮罩
  14. $.bootstrapLoading.end();
  15. });

  2. spin.js

  这个组件有通过css+js实现的转菊花效果。用到的组件文件主要有

  spin.js【根据参考文中给出的提示进行了修改】:

  1. /**
  2. * Copyright (c) 2011-2014 Felix Gnass
  3. * Licensed under the MIT license
  4. * http://spin.js.org/
  5. *
  6. * Example:
  7. var opts = {
  8. lines: 12, // The number of lines to draw
  9. length: 7, // The length of each line
  10. width: 5, // The line thickness
  11. radius: 10, // The radius of the inner circle
  12. scale: 1.0, // Scales overall size of the spinner
  13. corners: 1, // Roundness (0..1)
  14. color: '#000', // #rgb or #rrggbb
  15. opacity: 1/4, // Opacity of the lines
  16. rotate: 0, // Rotation offset
  17. direction: 1, // 1: clockwise, -1: counterclockwise
  18. speed: 1, // Rounds per second
  19. trail: 100, // Afterglow percentage
  20. fps: 20, // Frames per second when using setTimeout()
  21. zIndex: 2e9, // Use a high z-index by default
  22. className: 'spinner', // CSS class to assign to the element
  23. top: '50%', // center vertically
  24. left: '50%', // center horizontally
  25. shadow: false, // Whether to render a shadow
  26. hwaccel: false, // Whether to use hardware acceleration (might be buggy)
  27. position: 'absolute' // Element positioning
  28. };
  29. var target = document.getElementById('foo');
  30. var spinner = new Spinner(opts).spin(target);
  31. */
  32. ;(function(root, factory) {
  33. if (typeof module == 'object' && module.exports) module.exports = factory(); // CommonJS
  34. else if (typeof define == 'function' && define.amd) define(factory); // AMD module
  35. else root.Spinner = factory(); // Browser global
  36. }
  37. (this, function() {
  38. 'use strict';
  39.  
  40. var prefixes = ['webkit', 'Moz', 'ms', 'O']; // Vendor prefixes
  41. var animations = {}; // Animation rules keyed by their name
  42. var useCssAnimations; // Whether to use CSS animations or setTimeout
  43. var sheet; // A stylesheet to hold the @keyframe or VML rules
  44.  
  45. /**
  46. * Utility function to create elements. If no tag name is given,
  47. * a DIV is created. Optionally properties can be passed.
  48. */
  49. function createEl(tag, prop) {
  50. var el = document.createElement(tag || 'div');
  51. var n;
  52.  
  53. for (n in prop) el[n] = prop[n];
  54. return el;
  55. }
  56.  
  57. /**
  58. * Appends children and returns the parent.
  59. */
  60. function ins(parent /* child1, child2, ...*/) {
  61. for (var i = 1, n = arguments.length; i < n; i++) {
  62. parent.appendChild(arguments[i]);
  63. }
  64.  
  65. return parent;
  66. }
  67.  
  68. /**
  69. * Creates an opacity keyframe animation rule and returns its name.
  70. * Since most mobile Webkits have timing issues with animation-delay,
  71. * we create separate rules for each line/segment.
  72. */
  73. function addAnimation(alpha, trail, i, lines) {
  74. var name = ['opacity', trail, ~~(alpha * 100), i, lines].join('-');
  75. var start = 0.01 + i/lines * 100;
  76. var z = Math.max(1 - (1-alpha) / trail * (100-start), alpha);
  77. var prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase();
  78. var pre = prefix && '-' + prefix + '-' || '';
  79.  
  80. if (!animations[name]) {
  81. sheet.insertRule(
  82. '@' + pre + 'keyframes ' + name + '{' +
  83. '0%{opacity:' + z + '}' +
  84. start + '%{opacity:' + alpha + '}' +
  85. (start+0.01) + '%{opacity:1}' +
  86. (start+trail) % 100 + '%{opacity:' + alpha + '}' +
  87. '100%{opacity:' + z + '}' +
  88. '}', sheet.cssRules.length);
  89.  
  90. animations[name] = 1;
  91. }
  92.  
  93. return name;
  94. }
  95.  
  96. /**
  97. * Tries various vendor prefixes and returns the first supported property.
  98. */
  99. function vendor(el, prop) {
  100. var s = el.style;
  101. var pp;
  102. var i;
  103.  
  104. prop = prop.charAt(0).toUpperCase() + prop.slice(1);
  105. if (s[prop] !== undefined) return prop;
  106. for (i = 0; i < prefixes.length; i++) {
  107. pp = prefixes[i]+prop;
  108. if (s[pp] !== undefined) return pp;
  109. }
  110. }
  111.  
  112. /**
  113. * Sets multiple style properties at once.
  114. */
  115. function css(el, prop) {
  116. for (var n in prop) {
  117. el.style[vendor(el, n) || n] = prop[n];
  118. }
  119.  
  120. return el;
  121. }
  122.  
  123. /**
  124. * Fills in default values.
  125. */
  126. function merge(obj) {
  127. for (var i = 1; i < arguments.length; i++) {
  128. var def = arguments[i];
  129. for (var n in def) {
  130. if (obj[n] === undefined) obj[n] = def[n];
  131. }
  132. }
  133. return obj;
  134. }
  135.  
  136. /**
  137. * Returns the line color from the given string or array.
  138. */
  139. function getColor(color, idx) {
  140. return typeof color == 'string' ? color : color[idx % color.length];
  141. }
  142.  
  143. // Built-in defaults
  144.  
  145. var defaults = {
  146. lines: 12, // The number of lines to draw
  147. length: 7, // The length of each line
  148. width: 5, // The line thickness
  149. radius: 10, // The radius of the inner circle
  150. scale: 1.0, // Scales overall size of the spinner
  151. corners: 1, // Roundness (0..1)
  152. color: '#000', // #rgb or #rrggbb
  153. opacity: 1/4, // Opacity of the lines
  154. rotate: 0, // Rotation offset
  155. direction: 1, // 1: clockwise, -1: counterclockwise
  156. speed: 1, // Rounds per second
  157. trail: 100, // Afterglow percentage
  158. fps: 20, // Frames per second when using setTimeout()
  159. zIndex: 2e9, // Use a high z-index by default
  160. className: 'spinner', // CSS class to assign to the element
  161. top: '50%', // center vertically
  162. left: '50%', // center horizontally
  163. shadow: false, // Whether to render a shadow
  164. hwaccel: false, // Whether to use hardware acceleration
  165. position: 'absolute' // Element positioning
  166. };
  167.  
  168. /** The constructor */
  169. function Spinner(o) {
  170. this.opts = merge(o || {}, Spinner.defaults, defaults);
  171. }
  172.  
  173. // Global defaults that override the built-ins:
  174. Spinner.defaults = {};
  175.  
  176. merge(Spinner.prototype, {
  177. /**
  178. * Adds the spinner to the given target element. If this instance is already
  179. * spinning, it is automatically removed from its previous target b calling
  180. * stop() internally.
  181. */
  182. spin: function(target) {
  183. this.stop();
  184.  
  185. var self = this;
  186. var o = self.opts;
  187. var el = self.el = createEl(null, {className: o.className});
  188.  
  189. css(el, {
  190. position: o.position,
  191. width: 0,
  192. zIndex: o.zIndex,
  193. left: o.left,
  194. top: o.top
  195. });
  196.  
  197. if (target) {
  198. target.insertBefore(el, target.firstChild || null);
  199. target.className = "fade";
  200. }
  201.  
  202. el.setAttribute('role', 'progressbar');
  203. self.lines(el, self.opts);
  204.  
  205. if (!useCssAnimations) {
  206. // No CSS animation support, use setTimeout() instead
  207. var i = 0;
  208. var start = (o.lines - 1) * (1 - o.direction) / 2;
  209. var alpha;
  210. var fps = o.fps;
  211. var f = fps / o.speed;
  212. var ostep = (1 - o.opacity) / (f * o.trail / 100);
  213. var astep = f / o.lines;
  214.  
  215. (function anim() {
  216. i++;
  217. for (var j = 0; j < o.lines; j++) {
  218. alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity);
  219.  
  220. self.opacity(el, j * o.direction + start, alpha, o);
  221. }
  222. self.timeout = self.el && setTimeout(anim, ~~(1000 / fps));
  223. })();
  224. }
  225.  
  226. return self;
  227. },
  228.  
  229. /**
  230. * Stops and removes the Spinner.
  231. */
  232. stop: function() {
  233. var el = this.el;
  234. if (el) {
  235. clearTimeout(this.timeout);
  236. if (el.parentNode) {
  237. var reg = new RegExp('(\\s|^)fade(\\s|$)');
  238. el.parentNode.className = el.parentNode.className.replace(reg, ' ');
  239. el.parentNode.removeChild(el);
  240. }
  241. this.el = undefined;
  242. }
  243. return this;
  244. },
  245.  
  246. /**
  247. * Internal method that draws the individual lines. Will be overwritten
  248. * in VML fallback mode below.
  249. */
  250. lines: function(el, o) {
  251. var i = 0;
  252. var start = (o.lines - 1) * (1 - o.direction) / 2;
  253. var seg;
  254.  
  255. function fill(color, shadow) {
  256. return css(createEl(), {
  257. position: 'absolute',
  258. width: o.scale * (o.length + o.width) + 'px',
  259. height: o.scale * o.width + 'px',
  260. background: color,
  261. boxShadow: shadow,
  262. transformOrigin: 'left',
  263. transform: 'rotate(' + ~~(360/o.lines*i + o.rotate) + 'deg) translate(' + o.scale*o.radius + 'px' + ',0)',
  264. borderRadius: (o.corners * o.scale * o.width >> 1) + 'px'
  265. });
  266. }
  267.  
  268. for (; i < o.lines; i++) {
  269. seg = css(createEl(), {
  270. position: 'absolute',
  271. top: 1 + ~(o.scale * o.width / 2) + 'px',
  272. transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
  273. opacity: o.opacity,
  274. animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1 / o.speed + 's linear infinite'
  275. });
  276.  
  277. if (o.shadow) ins(seg, css(fill('#000', '0 0 4px #000'), {top: '2px'}));
  278. ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)')));
  279. }
  280. return el;
  281. },
  282.  
  283. /**
  284. * Internal method that adjusts the opacity of a single line.
  285. * Will be overwritten in VML fallback mode below.
  286. */
  287. opacity: function(el, i, val) {
  288. if (i < el.childNodes.length) el.childNodes[i].style.opacity = val;
  289. }
  290.  
  291. });
  292.  
  293. function initVML() {
  294.  
  295. /* Utility function to create a VML tag */
  296. function vml(tag, attr) {
  297. return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr);
  298. }
  299.  
  300. // No CSS transforms but VML support, add a CSS rule for VML elements:
  301. sheet.addRule('.spin-vml', 'behavior:url(#default#VML)');
  302.  
  303. Spinner.prototype.lines = function(el, o) {
  304. var r = o.scale * (o.length + o.width);
  305. var s = o.scale * 2 * r;
  306.  
  307. function grp() {
  308. return css(
  309. vml('group', {
  310. coordsize: s + ' ' + s,
  311. coordorigin: -r + ' ' + -r
  312. }),
  313. { width: s, height: s }
  314. );
  315. }
  316.  
  317. var margin = -(o.width + o.length) * o.scale * 2 + 'px';
  318. var g = css(grp(), {position: 'absolute', top: margin, left: margin});
  319. var i;
  320.  
  321. function seg(i, dx, filter) {
  322. ins(
  323. g,
  324. ins(
  325. css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
  326. ins(
  327. css(
  328. vml('roundrect', {arcsize: o.corners}),
  329. {
  330. width: r,
  331. height: o.scale * o.width,
  332. left: o.scale * o.radius,
  333. top: -o.scale * o.width >> 1,
  334. filter: filter
  335. }
  336. ),
  337. vml('fill', {color: getColor(o.color, i), opacity: o.opacity}),
  338. vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
  339. )
  340. )
  341. );
  342. }
  343.  
  344. if (o.shadow)
  345. for (i = 1; i <= o.lines; i++) {
  346. seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)');
  347. }
  348.  
  349. for (i = 1; i <= o.lines; i++) seg(i);
  350. return ins(el, g);
  351. };
  352.  
  353. Spinner.prototype.opacity = function(el, i, val, o) {
  354. var c = el.firstChild;
  355. o = o.shadow && o.lines || 0;
  356. if (c && i + o < c.childNodes.length) {
  357. c = c.childNodes[i + o]; c = c && c.firstChild; c = c && c.firstChild;
  358. if (c) c.opacity = val;
  359. }
  360. };
  361. }
  362.  
  363. if (typeof document !== 'undefined') {
  364. sheet = (function() {
  365. var el = createEl('style', {type : 'text/css'});
  366. ins(document.getElementsByTagName('head')[0], el);
  367. return el.sheet || el.styleSheet;
  368. }());
  369.  
  370. var probe = css(createEl('group'), {behavior: 'url(#default#VML)'});
  371.  
  372. if (!vendor(probe, 'transform') && probe.adj) initVML();
  373. else useCssAnimations = vendor(probe, 'animation');
  374. }
  375.  
  376. return Spinner;
  377.  
  378. }));

  原生的组件不带有遮罩,只有转菊花。为了加上遮罩我们还要写一个小css,命名为spin.css:

  1. .fade {
  2. position: fixed;
  3. top:;
  4. right:;
  5. bottom:;
  6. left:;
  7. z-index:;
  8. opacity: 0.8;
  9. background-color: #CDCDCD;
  10. }

  然后就是调用了,当然别忘了在调用界面引入上面两个js和css文件。由于spin.js不需要jquery,而采用javascript原生的方式调用方法,所以有些特殊。为了更清楚地说明,下面将完整写出一整个调用页面的情况:

  1. {% extends 'orig/my_base.html' %}
  2.  
  3. {% load static %}
  4.  
  5. {% block styles %}
  6. {{ block.super }}
  7. <link href="{% static 'spinjs/spin.css' %}" rel="stylesheet" />
  8. {% endblock %}
  9.  
  10. {% block front_scripts %}
  11. {{ block.super }}
  12. <script src="{% static 'spinjs/spin.js' %}"></script>
  13. <script src="{% static 'test.js' %}"></script>
  14. {% endblock %}
  15.  
  16. {% block page_content %}
  17. <button type="button" class="btn btn-default" id="req">发起ajax请求</button>
  18. <!-- spin.js的遮罩需要手动在页面上写上一个div,如下 -->
  19. <div id="mask"></div>
  20. {% endblock %}

  然后再来看下在test.js中是如何具体调用遮罩发生方法的:

  1. $(document).ready(function(event){
  2. // 点击按钮发起请求,同时带起遮罩
  3. $('#req').click(function(event){
  4. event.preventDefault();
  5. var spinner; // 进入ajax前声明spinner变量以使得变量得以在ajax参数中传递
  6. $.ajax({
  7. url: '/test/spinload',
  8. type: 'get',
  9. dataType: 'json',
  10. data: {},
  11. // 遮罩的启用在beforeSend中进行
  12. beforeSend: function(){
  13. var target = $('#mask')[0]; // 注意,取的是[0],或者用js的document.getElementById('mask')也行
  14. spinner = new Spinner({
  15. lines: 12,
  16. length: 2,
  17. width: 5,
  18. radius: 10,
  19. shadow: true,
  20. opacity: 0.1
  21. //更多的初始化参数可以参考spin.js里面的defaults
  22. }).spin(target); // 这里就算是显示遮罩了
  23. },
  24. success: function(data){
  25. console.log(data);
  26. },
  27. complete: function(){
  28. target.spin(); // 隐去遮罩
  29. }
  30. })
  31. })
  32.  
  33. })

  

  3. fakeLoader

  fakeLoader同样需要bootstrap和jquery的支持。这个组件严格来说并不是一个遮罩,而是一个提升体验的组件。比如在网页还在加载中或者其他一些不太好看的时候,可以放出fakeLoader,但是fakeLoader只能显示固定秒数,不能和上面那几个插件一样加入某个动作的钩子。

  引入方法很简单,就是在有bootstrap和jquery的情况下把下载【https://github.com/joaopereirawd/fakeLoader.js/tree/master/demo】来的css和js分别引用进去即可。和上面的spinjs类似的,需要在页面上<body>中添加一个<div>,然后用这个标识的div调用fakeLoader的一些方法即可。

  调用时用:

  1. $('#mask').fakeLoader({
  2. timeToHide: 3000 // fakeLoader隐藏的秒数。由于无钩子控制,需要合理设置不能太大也不能太小
  3. spinner: 'spinner4' // 有7-8种spinner,不同的“菊花”样式,可以网上查下哪个好看
  4. });

  正如上面所说,fakeLoader无法加入钩子,这主要是因为他没有留出(动作结束时)隐藏fakeLoader的接口。虽然我们可以通过这样的方式来进行手动的隐藏:

  1. $('#mask').fakeLoader({
  2. timeToHide: 60000, // 设置一个很长的时间,保证动作完成前fakeLoader一直在
  3. spinner: 'spinner4'
  4. });
  5.  
  6. // 一些动作过后
  7.  
  8. $('#mask').fakeLoader({
  9. timeToHide: 1, // 隐藏fakeLoader
  10. spinner: 'spinner4' // 设置和出现的spinner一样,否则可能会出现出入
  11. })

  虽然这样可以实现一次,但是如果再来一次相同的动作的话可能会导致fakeLoader无法再次出现,也就是说一次性的。。有符合场景的情况的话不妨可以用用。

【Bootstrap】优秀小插件收集的更多相关文章

  1. 近期十大优秀jQuery插件推荐

    当有限的开发知识限制了设计进展,你无法为自己插上创新的翅膀时,jQuery可以扩展你的视野.本文将推荐从jQuery网站的Plugin频道中推选出的近期十款优秀jQuery插件. 1.jQuery U ...

  2. 第二百四十八节,Bootstrap轮播插件

    Bootstrap轮播插件 学习要点: 1.轮播插件 本节课我们主要学习一下 Bootstrap 中的轮播插件. 一.轮播 轮播插件就是将几张同等大小的大图,按照顺序依次播放. 基本实例. 第一步,给 ...

  3. 第二百四十三节,Bootstrap模态框插件

    Bootstrap模态框插件 学习要点: 1.基本使用 2.用法说明 本节课我们主要学习一下 Bootstrap 中的模态框插件,这是一款交互式网站非常常见的 弹窗功能插件. 一.基本使用 使用模态框 ...

  4. bootstrap学习——javascript插件篇

    飞近期做的一个小项目须要用到一个模态框和一个图片浏览插件,并把二者结合,刚好bootstrap有相应插件,下面是学习应用流程: 1.    引入js文件: 能够单个引入相应插件文件,或一次所有引入.飞 ...

  5. Web前端开发人员实用Chrome插件收集

    越来越多的前端开发人员喜欢在Chrome里开发调试代码,Chrome有许多优秀的插件可以帮助前端开发人员极大的提高工作效率.尤其Chrome本身是可以登录的,登录后你所有的插件都会自动同步到每一个登录 ...

  6. Visual Studio Code 和Visual Studio插件收集(持续更新)

    Visual Studio Code 插件收集 Chinese (Simplified) Language Pack 默认刚安装的VSC是原味英文的,如果你用不习惯,非常简单,官方出品的简体中文语言包 ...

  7. 开源Unity小插件CheatConsole

    我们在开发游戏的过程中,通常都需要一些快捷的方式来进行一些非常规的测试,这些功能一般被称作控制台或者GM指令,比如虚幻竞技场中,可以使用~键呼出控制台,输入一些指令即可进行快捷设置,比如设置分辨率,全 ...

  8. 浮动【电梯】或【回到顶部】小插件:iElevator.js

    iElevator.js 是一个jquery小插件,使用简单,兼容IE6,支持UMD和3种配置方式,比锚点更灵活. Default Options _defaults = { floors: null ...

  9. aBowman >>可以运用到自己博客上的小插件

    大家进入我的博客会发现页面右边有一只小狗这部分.这个就是我用在上面的 一个小插件.插件网址是:http://abowman.com/google-modules/,这上面有很多的小插件,可以直接运用到 ...

随机推荐

  1. python替换脚本

    任何场合都用的到的全文替换 #!/usr/bin/python import sys if len(sys.argv) < 5: print 'usage: python %s from to ...

  2. 新手福音︱正则表达式小工具RegExr

    由于之前在做NLP的内容,势必会接触正则表达式,但是呢,又觉得这个学不明白- 于是,这个工具还是蛮不错的,相当于在线正则速查+验证小工具,对于我这样的新手值得去玩玩. github:https://g ...

  3. 常用u-boot命令详解(全) 2

    (8) USB 操作指令 指令 功能 usb reset 初始化USB控制器 usb stop [f] 关闭USB控制器 usb tree 已连接的USB设备树 usb info [dev] 显示US ...

  4. java.text.ParseException: Unparseable date: "2015-06-09 hh:56:19"

    1.错误描述 [DEBUG:]2015-06-09 16:56:19,520 [-------------------transcation start!--------------] java.te ...

  5. Scheme change not implemented

    1.错误描述 2.错误原因 由于在改变Java代码中的方法或运行代码出现,导致Tomcat编译的代码不能替换工作空间的代码,即不能及时同步,出现错误 3.解决办法 (1)关闭Tomcat,clean一 ...

  6. java中equals和==以及toString

    我们通常在控制台输出时使用System.out.print(),print只能直接输出基本类型和字符串,对于其他的类型直接输出将会输出@开头的引用,因此若需要输出对应的内容则需要使用toSring方法 ...

  7. Java中集合List,Map和Set的区别

    Java中集合List,Map和Set的区别 1.List和Set的父接口是Collection,而Map不是 2.List中的元素是有序的,可以重复的 3.Map是Key-Value映射关系,且Ke ...

  8. VxWorks操作系统shell命令与调试方法总结

    VxWorks下的调试手段 主要介绍在Tornado集成开发环境下的调试方法,和利用支撑定位问题的步骤.思路. 1         Tornado的调试工具 嵌入式实时操作系统VxWorks和集成开发 ...

  9. SecurityError:Error:#2148

    1.错误描述 SecurityError:Error:#2148:SWF文件http://localhost:8888/UploadDownload/Flash/ReadLocalFile.swf/[ ...

  10. 微信开发中access_token,js_ticket,时间戳,签名生成工具

    Access_token生成工具 工具地址:https://mp.weixin.qq.com/debug 这个工具主要用来验证和生成微信公众号access_token,主要有正确的app_id和app ...