Bootstrap 4 中 Alerts 实现
Alert 的使用说明
http://v4-alpha.getbootstrap.com/components/alerts/
JavaScript behavior
Triggers
Enable dismissal of an alert via JavaScript:
$(".alert").alert()
Or with data
attributes on a button within the alert, as demonstrated above:
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
Note that closing an alert will remove it from the DOM.
Methods
Method | Description |
---|---|
$().alert() |
Makes an alert listen for click events on descendant elements which have the data-dismiss="alert" attribute. (Not necessary when using the data-api’s auto-initialization.) |
$().alert('close') |
Closes an alert by removing it from the DOM. If the .fade and .in classes are present on the element, the alert will fade out before it is removed. |
$(".alert").alert('close')
Events
Bootstrap’s alert plugin exposes a few events for hooking into alert functionality.
Event | Description |
---|---|
close.bs.alert |
This event fires immediately when the close instance method is called. |
closed.bs.alert |
This event is fired when the alert has been closed (will wait for CSS transitions to complete). |
$('#myAlert').on('closed.bs.alert', function () {
// do something…
})
获取 bootstrap 4
源代码分析
外层函数分析
从代码的最外层来看,实际上是一个立即执行的函数,jQuery 就是我们熟悉的 jQuery 库。
+function ($) { } (jQuery);
对于在 function 之前使用 + 的用法,这里有详细的说明:function与感叹号
加上 Alert 之后,我们函数内部会成为嵌套的立即执行函数。
+function ($) { var Alert = (function ($) { })(jQuery); } (jQuery);
有点问题,编码风格不一致,这次里面使用了常见的括号方式来处理立即执行函数。
几个辅助函数
创建类的函数 _createClass.
在 JavaScript 中,如何才能定义一个类呢?
类的作用在于同类的对象可以共享处理方法和数据,因此,在类中,必须有一个方式来共享所有同类对象所共享的成员,在 JavaSript 中,基本的方式是通过 function 的原型 prototype 来实现的。定义在 function 的 prototype 对象上的成员,可以被通过这个函数 new 出来的对象所共享。
所以,通常一个类是一个函数,我们把希望共享的成员定义在它的原型对象上。
同时,还可以定义静态的成员,不需要通过对象实例来放问,可以直接通过类型来访问,这些静态成员可以直接定义在这个 function 对象上,没错,function 也是一个对象。
这样的话,在创建一个类的时候,我们需要为这个函数定义实例成员和静态成员,这就是 _createClass 这个函数的职责。
先看简化版本,这个函数不是直接定义出来的,是调用一个匿名函数返回的。这又是一个立即执行函数。
var _createClass = (function () { return function () { };
})();
在它的内部定义了一个私有的函数,这个函数在外部不可调用。我们再扩展一下。这样看的更加清楚一些。
var _createClass = (function () { // 内部的私有函数,外部不可调用.
function defineProperties(target, props) {
}
} // 返回的函数,外部可以调用
return function (Constructor, protoProps, staticProps) {
defineProperties(Constructor.prototype, protoProps);
return Constructor;
}; })();
内部的这个 defineProperties 做什么呢?就是为目标对象定义属性。属性需要实现一些规范: Object.prototype, 下面的代码就是实现规范的要求.
Object.prototype 属性的属性特性: |
|
---|---|
writable | false |
enumerable | false |
configurable | false |
// define prpperties on object.
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ('value' in descriptor)
descriptor.writable = true; //https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Object.defineProperty(target, descriptor.key, descriptor);
}
}
所以, 创建类型就是传递两个分别描述实例成员和静态成员的数组了.
_createClass 的全部代码如下:
var _createClass = (function () { // define prpperties on object.
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ('value' in descriptor)
descriptor.writable = true; // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Object.defineProperty(target, descriptor.key, descriptor);
}
} // Constructor: target function
// protoProps: prototype of function
// staticProps: static properties
return function (Constructor, protoProps, staticProps) {
if (protoProps)
defineProperties(Constructor.prototype, protoProps);
if (staticProps)
defineProperties(Constructor, staticProps);
return Constructor;
};
})();
Alert 定义
里面的 Alert 是一个变量,这个变量是一个内部函数 Alert 返回的. 而这个内部函数就是我们的 Alert 类定义. 可以看到在这个函数定义之后, 就被添加了我们类的成员.
var Alert = (function ($) {
function Alert(element) {
_classCallCheck(this, Alert); this._element = element;
} _createClass(Alert, [{......}]); return Alert;
})();
再看剩下处理内容.
在 document 上注册了一个名为 "click.bs.alert.data-api" 的事件处理程序, 在 jQuery 中吧on 函数的定义如下:
.on( events [, selector ] [, data ], handler )
see also: http://api.jquery.com/on/
第一个参数是事件名称,有可选的选择器,还有事件处理程序.
$(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
最后, 是适配到 jQuery 的原型中, 以便直接通过 jQuery 对象实例进行处理. 其中的工作NAME 这里就是 alert 了.
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/ $.fn[NAME] = Alert._jQueryInterface;
$.fn[NAME].Constructor = Alert;
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT;
return Alert._jQueryInterface;
}; return Alert;
这里的工作_jQueryInterface 就是一个函数.
function _jQueryInterface(config) {
return this.each(function () {
var $element = $(this);
var data = $element.data(DATA_KEY); if (!data) {
data = new Alert(this);
$element.data(DATA_KEY, data);
} if (config === 'close') {
data[config](this);
}
});
}
注册事件处理函数
// Event.CLICK_DATA_API: click.bs.alert.data-api
// Selector.DISMISS: [data-dismiss="alert"]
// register a event handler
$(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
注意,这里的事件名称并不是通常的 click, 而是 click.bs.alert.data-api,这里涉及到 jQuery 的事件命名空间问题,可以到这里参考 jQuery 的文档:http://api.jquery.com/on/#event-names
作用就是我们可以在取消某些事件处理注册的时候,不会影响其它已经注册的事件处理程序。
目标选择器则为:[data-dismiss="alert"] ,这正是 bootstrap 所要求的按钮必须拥有的属性。
全部的 Alert 代码.
/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.2): alert.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/ var Alert = (function ($) { /**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/ var NAME = 'alert';
var VERSION = '4.0.0-alpha';
var DATA_KEY = 'bs.alert';
var EVENT_KEY = '.' + DATA_KEY;
var DATA_API_KEY = '.data-api';
var JQUERY_NO_CONFLICT = $.fn[NAME];
var TRANSITION_DURATION = 150; var Selector = {
DISMISS: '[data-dismiss="alert"]'
}; var Event = {
CLOSE: 'close' + EVENT_KEY,
CLOSED: 'closed' + EVENT_KEY,
CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
}; var ClassName = {
ALERT: 'alert',
FADE: 'fade',
IN: 'in'
}; /**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/ var Alert = (function () { // class define
function Alert(element) {
_classCallCheck(this, Alert); this._element = element;
} /**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/ // getters _createClass(Alert, [{
key: 'close', // public value: function close(element) {
element = element || this._element; var rootElement = this._getRootElement(element);
var customEvent = this._triggerCloseEvent(rootElement); if (customEvent.isDefaultPrevented()) {
return;
} this._removeElement(rootElement);
}
}, {
key: 'dispose',
value: function dispose() {
$.removeData(this._element, DATA_KEY);
this._element = null;
} // private }, {
key: '_getRootElement',
value: function _getRootElement(element) {
var selector = Util.getSelectorFromElement(element);
var parent = false; if (selector) {
parent = $(selector)[0];
} if (!parent) {
parent = $(element).closest('.' + ClassName.ALERT)[0];
} return parent;
}
}, {
key: '_triggerCloseEvent',
value: function _triggerCloseEvent(element) {
var closeEvent = $.Event(Event.CLOSE); $(element).trigger(closeEvent);
return closeEvent;
}
}, {
key: '_removeElement',
value: function _removeElement(element) {
$(element).removeClass(ClassName.IN); if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {
this._destroyElement(element);
return;
} $(element).one(Util.TRANSITION_END, $.proxy(this._destroyElement, this, element)).emulateTransitionEnd(TRANSITION_DURATION);
}
}, {
key: '_destroyElement',
value: function _destroyElement(element) {
$(element).detach().trigger(Event.CLOSED).remove();
} // static }], [{
key: '_jQueryInterface',
value: function _jQueryInterface(config) {
return this.each(function () {
var $element = $(this);
var data = $element.data(DATA_KEY); if (!data) {
data = new Alert(this);
$element.data(DATA_KEY, data);
} if (config === 'close') {
data[config](this);
}
});
}
}, {
key: '_handleDismiss',
value: function _handleDismiss(alertInstance) {
return function (event) {
if (event) {
event.preventDefault();
} alertInstance.close(this);
};
}
}, {
key: 'VERSION',
get: function get() {
return VERSION;
}
}]); return Alert;
})(); $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); /**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/ $.fn[NAME] = Alert._jQueryInterface;
$.fn[NAME].Constructor = Alert;
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT;
return Alert._jQueryInterface;
}; return Alert;
})(jQuery); } (jQuery);
使用的样式
.alert {
padding: 15px;
margin-bottom: 1rem;
border: 1px solid transparent;
border-radius: .25rem;
} .alert > p,
.alert > ul {
margin-bottom:;
} .alert > p + p {
margin-top: 5px;
} .alert-heading {
color: inherit;
} .alert-link {
font-weight: bold;
} .alert-dismissible {
padding-right: 35px;
} .alert-dismissible .close {
position: relative;
top: -2px;
right: -21px;
color: inherit;
} .alert-success {
color: #3c763d;
background-color: #dff0d8;
border-color: #d0e9c6;
} .alert-success hr {
border-top-color: #c1e2b3;
} .alert-success .alert-link {
color: #2b542c;
} .alert-info {
color: #31708f;
background-color: #d9edf7;
border-color: #bcdff1;
} .alert-info hr {
border-top-color: #a6d5ec;
} .alert-info .alert-link {
color: #245269;
} .alert-warning {
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faf2cc;
} .alert-warning hr {
border-top-color: #f7ecb5;
} .alert-warning .alert-link {
color: #66512c;
} .alert-danger {
color: #a94442;
background-color: #f2dede;
border-color: #ebcccc;
} .alert-danger hr {
border-top-color: #e4b9b9;
} .alert-danger .alert-link {
color: #843534;
}
待续......
Bootstrap 4 中 Alerts 实现的更多相关文章
- bootstrap Table 中给某一特定值设置table选中
bootstrap Table 中给某一特定值设置table选中 需求: 如图所示:左边地图人员选定,右边表格相应选中. 功能代码: //表格和图标联动 function changeTableSel ...
- Bootstrap.css 中请求googleapis.com/css?family 备忘录
问题描述: Web中引入bootstrap.css中头部有访问Google服务器的请求 @import url("//fonts.googleapis.com/css?family=Open ...
- 在Bootstrap开发框架中使用Grid++报表
之前在随笔<在Winform开发中使用Grid++报表>介绍了在Winform环境中使用Grid++报表控件,本篇随笔介绍在Bootstrap开发框架中使用Grid++报表,也就是Web环 ...
- 在Bootstrap开发框架中使用dataTable直接录入表格行数据(2)--- 控件数据源绑定
在前面随笔<在Bootstrap开发框架中使用dataTable直接录入表格行数据>中介绍了在Web页面中使用Jquery DataTable插件进行对数据直接录入操作,这种处理能够给用户 ...
- 在Bootstrap开发框架中使用dataTable直接录入表格行数据
在Winform开发的时候,我们很多时候可以利用表格控件来直接录入数据,不过在Web上较少看到,其实也可以利用dataTable对象处理直接录入表格行数据,这个可以提高数据的录入方便,特别是在一些简单 ...
- 在Bootstrap开发框架中使用bootstrapTable表格插件和jstree树形列表插件时候,对树列表条件和查询条件的处理
在我Boostrap框架中,很多地方需要使用bootstrapTable表格插件和jstree树形列表插件来共同构建一个比较常见的查询界面,bootstrapTable表格插件主要用来实现数据的分页和 ...
- 使用BootStrap框架中的轮播插件
在使用bootstrap框架中的轮播插件时,效果做出来后,无法通过点击小圆行的按钮来选择特定的图片. 后面发现是最开始的<div>标签中少写了一个id.一开始<div>标签是这 ...
- 在Bootstrap框架中,form-control的效果
在Bootstrap框架中,通过定制了一个类名`form-control`,也就是说,如果这几个元素使用了类名“form-control”,将会实现一些设计上的定制效果. 1.宽度变成了100% 2. ...
- bootstrap -- meta中的viewport指令
在查看bootstrap教程中,碰到 <meta name="viewport" content="width=device-width, initial-scal ...
随机推荐
- BaiduMap Search List
using AnfleCrawler.Common; using HtmlClient; using System; using System.Collections.Generic; using S ...
- iOS6的旋屏控制技巧
在iOS5.1 和 之前的版本中, 我们通常利用 shouldAutorotateToInterfaceOrientation: 来单独控制某个UIViewController的旋屏方向支持,比如: ...
- Java与数据库之间时间的处理
Java与数据库之间时间的处理 在数据库中建表: DROP TABLE IF EXISTS `times`; CREATE TABLE `times` ( `id` int(11) NOT NULL ...
- 2016 - 1- 23 iOS中xml解析 (!!!!!!!有坑要解决!!!!!!)
一: iOS中xml解析的几种方式简介 1.官方原生 NSXMLParser :SAX方式解析,使用起来比较简单 2.第三方框架 libxml2 :纯C 同时支持DOM与SAX GDataXML: D ...
- OpenCV是什么?
OpenCV其实就是一对C和C++语言的源代码文件,这些源代码文件中实现了许多常用的计算机视觉算法.例如C借口函数cvCanny()实现了Canny边缘提取算法.可以直接将这些源代码添加到我们自己的项 ...
- C#中using关键字的作用及用法
using的用途和使用技巧. 1. 引用命名空间 2. 为命名空间或类型创建别名 3. 使用using语句 1. 引用命名空间,这样可以在程序中引用命名空间的类型而不必指定详细的命名空间. a ...
- M3: 发送邮件附件(2)
本小节介绍如何通过邮件将生成的贺卡发送给朋友.使用到了EmailMessageAPI, 需要引入的命名空间为Windows.ApplicationModel.Email. 请确保完成了以前的章节. 在 ...
- 根据地图上的两个点各自的x,y坐标,计算出2点之间的直线距离。显示为公里、米
/** * calc_map_distance() , 根据地图上的两个点各自的x,y坐标,计算出2点之间的直线距离 * @param array $point_1 第1个点的x,y坐标 array( ...
- LintCode Validate Binary Search Tree
Validate Binary Search Tree Given a binary tree, determine if it is a valid binary search tree (BST) ...
- 初识Winform , 还好没喜欢上控制台
虽然没听的太懂, 不过还是写点东西吧. 我呢, 就跟着这本书写了个学生管理系统 前面刚会了SQLserver, 所以这个学生管理系统需要连上数据库, 毕竟学了不用天诛地灭 既然需要连接数据库, 就要用 ...