lu2
Version:
Simple and flexible UI component library based on native HTML and JavaScript
452 lines (395 loc) • 12.9 kB
JavaScript
/**
* @Dialog.js
* @author xunxuzhang
* @version
* Created: 15-06-18
* 17-03-13 按钮events可以直接是function类型
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.Dialog = factory();
}
}(this, function (require) {
// require
if (typeof require == 'function') {
require('common/ui/Loading');
} else if (!$().loading) {
if (window.console) {
console.error('need Loading.js');
}
return {};
}
/**
* 弹框组件
* IE9+基于HTML5 <dialog>元素创建
* 本透明遮罩层和弹框在一个元素内
* @example
* var myDialog = new Dialog();
* $(button).click(function() {
myDialog.show();
});
*/
// 类名前缀
var prefixGlobal = 'ui-', prefixDialog = 'ui-dialog-', joiner = '-';
// 关闭SVG
var svg = window.addEventListener? '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><path d="M116.152,99.999l36.482-36.486c2.881-2.881,2.881-7.54,0-10.42 l-5.215-5.215c-2.871-2.881-7.539-2.881-10.42,0l-36.484,36.484L64.031,47.877c-2.881-2.881-7.549-2.881-10.43,0l-5.205,5.215 c-2.881,2.881-2.881,7.54,0,10.42l36.482,36.486l-36.482,36.482c-2.881,2.881-2.881,7.549,0,10.43l5.205,5.215 c2.881,2.871,7.549,2.871,10.43,0l36.484-36.488L137,152.126c2.881,2.871,7.549,2.871,10.42,0l5.215-5.215 c2.881-2.881,2.881-7.549,0-10.43L116.152,99.999z"/></svg>': '';
// Is it webkit
var isWebkit = 'WebkitAppearance' in document.documentElement.style || typeof document.webkitHidden != "undefined";
var Dialog = function(options) {
var defaults = {
title: '',
// 不同类别的内容类型
content: '',
// 弹框的宽度
width: 'auto',
// 不同类别的默认按钮
buttons: [],
// 弹框显示、隐藏、移除的回调
onShow: $.noop,
onHide: $.noop,
onRemove: $.noop
};
// 最终参数
var params = $.extend({}, defaults, options || {});
var el = {};
this.el = el;
// 存储一些参数
this.width = this.width;
this.callback = {
show: params.onShow,
hide: params.onHide,
remove: params.onRemove
};
// 各个元素创建
// 容器-含半透明遮罩背景
el.container = window.addEventListener?
$('<dialog class="'+ prefixDialog +'container"></dialog>'):
$('<div class="'+ prefixDialog +'container"></div>');
if (history.pushState) {
el.container.get(0).addEventListener(isWebkit? 'webkitAnimationEnd': 'animationend', function(event) {
if (event.target.tagName.toLowerCase() == 'dialog') {
this.classList.remove(prefixDialog + 'animation');
}
});
}
// 弹框主体
el.dialog = $('<div class="'+ prefixGlobal +'dialog"></div>').css('width', params.width);
// 标题
el.title = $('<div class="'+ prefixDialog +'title"></div>').html(params.title);
// 关闭按钮
el.close = $('<a href="javascript:" class="'+ prefixDialog +'close"></a>').html(svg).click($.proxy( function(event) {
this[this.closeMode]();
event.preventDefault();
}, this));
// 主体
var content = params.content;
// content可以是函数
if ($.isFunction(content)) {
content = content();
}
if (!content.size) {
this.closeMode = 'remove';
} else {
this.closeMode = 'hide';
}
el.body = $('<div class="'+ prefixDialog +'body"></div>')[content.size? 'append': 'html'](content);
// 底部
el.footer = $('<div class="'+ prefixDialog +'footer"></div>');
// 按钮
this.button(params.buttons);
// 组装
el.container.append(el.dialog.append(el.close).append(el.title).append(el.body).append(el.footer));
// IE7 额外辅助元素
if (!document.querySelector) {
el.container.append('<i class="'+ prefixDialog +'after"></i>');
}
// zIndex动态计算
// 所有dialog的前面
var dialog = $('.' + prefixDialog +'container');
if (dialog.size()) {
// 页面前置
dialog.eq(0).before(el.container.css({
// 动态计算zIndex值
zIndex: dialog.eq(0).css('z-index') * 1 + 1
}));
} else {
// 页面后入
(params.container || $(document.body)).append(el.container);
}
this.display = false;
if (params.content) {
this.show();
}
return this;
};
Dialog.prototype.button = function(data) {
var el = this.el, dialog = this;
el.footer.empty();
$.each(data, function(i, btn) {
// 避免btn为null等值报错
btn = btn || {};
// 按钮的默认参数
var type = i? (btn.type || ''): (btn.type || 'primary'),
value = i? (btn.value || '取消'): (btn.value || '确定');
// 事件处理,如果直接function类型,则认为是点击方法
var events = btn.events || {
click: function() {
dialog[dialog.closeMode]();
}
};
if ($.isFunction(events)) {
events = {
click: events
};
}
// 按钮的类名值
var cl = prefixGlobal +'button';
if (type) cl = cl + ' ' + cl + joiner + type;
if (!btn['for']) {
el.footer.append(el['button' + i] =
$('<a href="javascript:;" class="'+ cl +'">'+ value + '</a>').bind(events)
);
} else {
el.footer.append(el['button' + i] =
$('<label for="'+ btn['for'] +'" class="'+ cl +'">'+ value + '</label>').bind(events)
);
}
});
return this;
},
Dialog.prototype.loading = function() {
var el = this.el, dialog = this;
if (el) {
el.container.attr('class', [prefixDialog +'container', prefixDialog + 'loading'].join(' '));
el.body.loading();
this.show();
}
return this;
};
Dialog.prototype.unloading = function(time) {
var el = this.el, dialog = this;
if (el) {
el.container.removeClass(prefixDialog + 'loading');
el.body.unloading(time);
}
return this;
};
Dialog.prototype.open = function(html, options) {
var el = this.el, dialog = this;
// 默认参数
var defaults = {
title: '',
buttons: []
};
// 最终参数
var params = $.extend({}, defaults, options || {});
// 替换当前弹框的内容,包括按钮等
if (el && html) {
el.container.attr('class', [prefixDialog +'container'].join(' '));
el.title.html(params.title);
el.body.html(html);
this.button(params.buttons).show();
}
return this;
};
Dialog.prototype.alert = function(html, options) {
var el = this.el, dialog = this;
// alert框的默认参数
var defaults = {
title: '',
type: 'remind', // 类型, 'remind', 'success', 'warning', 或者任意 'custom'
buttons: [{}]
};
// 最终参数
var params = $.extend({}, defaults, options || {});
if (!params.buttons[0].type && params.type != 'remind') {
params.buttons[0].type = params.type;
}
// 替换当前弹框的内容,包括按钮等
if (el && html) {
el.container.attr('class', [prefixDialog +'container', prefixDialog + 'alert'].join(' '));
el.dialog.width('auto');
el.title.html(params.title);
// 如果是纯文本
if (/<[\w\W]+>/.test(html) == false) {
html = '<h6>' + html + '</h6>';
}
el.body.html('<div class="'+ prefixDialog + params.type +'">' + html + '</div>');
this.button(params.buttons).show();
if (el.button0) {
el.button0.focus();
}
}
return this;
};
Dialog.prototype.confirm = function(html, options) {
var el = this.el, dialog = this;
// confirm框的默认参数
var defaults = {
title: '',
type: 'warning',
buttons: [{
type: 'warning'
}, { /* 取消按钮使用默认配置 */}]
};
// 最终参数
var params = $.extend({}, defaults, options || {});
// warning类型的按钮可缺省
if (params.buttons.length && !params.buttons[0].type) {
params.buttons[0].type = 'warning';
}
// 替换当前弹框的内容,包括按钮等
if (el && html) {
el.container.attr('class', [prefixDialog +'container', prefixDialog + 'confirm'].join(' '));
el.dialog.width('auto');
el.title.html(params.title);
// 如果是纯文本
if (/<[\w\W]+>/.test(html) == false) {
html = '<h6>' + html + '</h6>';
}
el.body.html('<div class="'+ prefixDialog + params.type +'">' + html + '</div>');
this.button(params.buttons).show();
if (el.button0) {
el.button0.focus();
}
}
return this;
};
Dialog.prototype.ajax = function(ajaxOptions, options) {
var dialog = this, timer = new Date().getTime();
// ajax请求的一些默认参数
// 类似timeout等参数这里缺省了
// url直接注释了,就是jQuery的Ajax参数
var ajaxDefaults = {
// url: '', // 必须参数,请求地址
dataType: 'JSON',
timeout: 30000,
error: function(xhr, status) {
var msgSorry = '<h6>尊敬的用户,很抱歉您刚才的操作没有成功!</h6>', msgReason = '';
if (status == 'timeout') {
msgReason = '<p>主要是由于请求时间过长,数据没能成功加载,这一般是由于网速过慢导致,您可以稍后重试!</p>';
} else if (status == 'parsererror') {
msgReason = '<p>原因是请求的数据含有不规范的内容。一般出现这样的问题是开发人员没有考虑周全,欢迎向我们反馈此问题!</p>';
} else {
msgReason = '<p>一般是网络出现了异常,如断网;或是网络临时阻塞,您可以稍后重试!如依然反复出现此问题,欢迎向我们反馈!</p>';
}
dialog.alert(msgSorry + msgReason, {
type: 'warning'
}).unloading();
}
};
var ajaxParams = $.extend({}, ajaxDefaults, ajaxOptions || {});
// ajax的url地址是必须参数
if (!ajaxParams.url) return this;
// 下面是弹框的一些默认参数
var defaults = {
title: '',
content: function(data) {
// 如果ajax的类型是'JSON', 此方法用来返回格式化的HTML数据
// 如果是HTML, 默认返回HTML
if (typeof data == 'string') {
return data;
} else {
return '<i style="display:none">看见我说明没使用\'options.content\'做JSON解析</i>';
}
},
buttons: []
};
var params = $.extend({}, defaults, options || {});
// ajax走起
// ajax success回调走合并
var success = ajaxParams.success;
ajaxParams.success = function(data) {
dialog.open(params.content(data), params);
// 移除菊花态
// 如果时间戳小于100毫秒
// 弹框直接打开,无动画
if (new Date().getTime() - timer < 100) {
dialog.unloading(0);
} else {
dialog.unloading();
}
// 这是用户设置的成功回调
if ($.isFunction(success)) {
success.apply(this, arguments);
}
};
// 开始执行Ajax请求
// 稍等……
// 请求之前,我们还需要做一件事件
// 开菊花
dialog.loading();
// ajax走起
// 下面的定时器测试用
setTimeout(function() {
$.ajax(ajaxParams);
}, 250);
return this;
};
Dialog.prototype.scroll = function() {
var containers = $('.' + prefixDialog + 'container'), isDisplayed = false;
containers.each(function() {
if ($(this).css('display') == 'block') {
isDisplayed = true;
}
});
// 因为去掉了滚动条,所以宽度需要偏移,保证页面内容没有晃动
if (isDisplayed) {
var widthScrollbar = 17;
if (this.display != true && typeof window.innerWidth == 'number') {
widthScrollbar = window.innerWidth - document.documentElement.clientWidth;
}
document.documentElement.style.overflow = 'hidden';
if (this.display != true) {
$(document.body).css('border-right', widthScrollbar + 'px solid transparent');
}
} else {
document.documentElement.style.overflow = '';
$(document.body).css('border-right', '');
}
return this;
};
Dialog.prototype.show = function() {
var container = this.el.container;
if (container) {
// 面板显示
container.css('display', 'block');
if (this.display != true) {
container.addClass(prefixDialog + 'animation')
}
this.scroll();
this.display = true;
if ($.isFunction(this.callback.show)) {
this.callback.show.call(this, container);
}
}
return this;
};
Dialog.prototype.hide = function() {
var container = this.el.container;
if (container) {
container.hide();
this.scroll();
this.display = false;
if ($.isFunction(this.callback.hide)) {
this.callback.hide.call(this, container);
}
}
return this;
};
Dialog.prototype.remove = function(time) {
var container = this.el.container;
if (container) {
container.remove();
this.scroll();
this.display = false;
if ($.isFunction(this.callback.remove)) {
this.callback.remove.call(this, container);
}
}
return this;
};
return Dialog;
}));