zui
Version:
一个基于 Bootstrap 深度定制开源前端实践方案,帮助你快速构建现代跨屏应用。
1,561 lines (1,341 loc) • 133 kB
JavaScript
/*!
* ZUI: Lite edition - v1.10.0 - 2021-11-04
* http://openzui.com
* GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2021 cnezsoft.com; Licensed MIT
*/
/*! Some code copy from Bootstrap v3.0.0 by @fat and @mdo. (Copyright 2013 Twitter, Inc. Licensed under http://www.apache.org/licenses/)*/
/* ========================================================================
* ZUI: jquery.extensions.js
* http://openzui.com
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function($, window, undefined) {
'use strict';
/* Check jquery */
if(typeof($) === 'undefined') throw new Error('ZUI requires jQuery');
/* ZUI shared object */
if(!$.zui) $.zui = function(obj) {
if($.isPlainObject(obj)) {
$.extend($.zui, obj);
}
};
var MOUSE_BUTTON_CODES = {
all: -1,
left: 0,
middle: 1,
right: 2
};
var lastUuidAmend = 0;
$.zui({
uuid: function(asNumber) {
var uuidNumber = (Date.now() - 1580890015292) * 10e4 + Math.floor(Math.random() * 10e3) * 10 + (lastUuidAmend++) % 10;
return asNumber ? uuidNumber : uuidNumber.toString(36);
},
callEvent: function(func, event, proxy) {
if(typeof func === 'function') {
if(proxy !== undefined) {
func = func.bind(proxy);
}
var result = func(event);
if(event) event.result = result;
return !(result !== undefined && (!result));
}
return 1;
},
strCode: function(str) {
var code = 0;
if (typeof str !== 'string') str = String(str);
if(str && str.length) {
for(var i = 0; i < str.length; ++i) {
code += (i + 1) * str.charCodeAt(i);
}
}
return code;
},
getMouseButtonCode: function(mouseButton) {
if(typeof mouseButton !== 'number') {
mouseButton = MOUSE_BUTTON_CODES[mouseButton];
}
if(mouseButton === undefined || mouseButton === null) mouseButton = -1;
return mouseButton;
},
/**
* default language name
* @type {string}
*/
defaultLang: 'en',
/**
* Get client language name
* @return {string}
*/
clientLang: function() {
var lang;
var config = window.config;
if(typeof(config) != 'undefined' && config.clientLang) {
lang = config.clientLang;
}
if(!lang) {
var hl = $('html').attr('lang');
lang = hl ? hl : (navigator.userLanguage || navigator.userLanguage || $.zui.defaultLang);
}
return lang.replace('-', '_').toLowerCase();
},
/**
* @type {object}
* @example
* {
* 'zui.pager': {
* 'zh-cn': {
* prev: '上一页',
* }
* }
* }
*/
langDataMap: {},
/**
* Add lang data for components
* @param {string} [langName]
* @param {string} [componentName]
* @param {object} data
* @example
* // Add lang data to specify language and specify component
* $.zui.addLangData('zh-cn', 'zui.pager', {
* prev: '上一页',
* next: '下一页',
* });
*
* // Add lang data to specify language and multiple components
* $.zui.addLangData('zh-cn', {
* 'zui.pager': {
* prev: '上一页',
* next: '下一页',
* },
* 'chosen': {
* }
* });
*
* // Add lang data to multiple languages and multiple components
* $.zui.addLangData({
* 'zh-cn': {
* 'zui.pager': {
* prev: '上一页',
* next: '下一页',
* },
* 'chosen': {
* }
* },
* 'zh-tw': {
* 'zui.pager': {
* prev: '上一页',
* next: '下一页',
* }
* }
* });
*/
addLangData: function(langName, componentName, data) {
var langData = {};
if (data && componentName && langName) {
langData[componentName] = {};
langData[componentName][langName] = data;
} else if (langName && componentName && !data) {
data = componentName;
$.each(data, function(comName) {
langData[comName] = {};
langData[comName][langName] = data[comName];
});
} else if (langName && !componentName && !data) {
$.each(data, function(theLangName) {
var comsData = data[theLangName];
$.each(comsData, function(comName) {
if (!langData[comName]) {
langData[comName] = {};
}
langData[comName][theLangName] = comsData[comName];
});
});
}
$.extend(true, $.zui.langDataMap, langData);
},
/**
* Get lang data
* @example
* $.zui.getLangData('zui.pager');
*
* $.zui.getLangData('zui.pager', 'zh-cn');
*
* $.zui.getLangData('zui.pager', 'zh-cn', {
* prev: '上一页',
* next: '下一页',
* });
*/
getLangData: function(componentName, langName, initialData) {
if (!arguments.length) {
return $.extend({}, $.zui.langDataMap);
}
if (arguments.length === 1) {
return $.extend({}, $.zui.langDataMap[componentName]);
}
if (arguments.length === 2) {
var comData = $.zui.langDataMap[componentName];
if (comData) {
return langName ? comData[langName] : comData;
}
return {};
}
if (arguments.length === 3) {
langName = langName || $.zui.clientLang();
var comData = $.zui.langDataMap[componentName];
var langData = comData ? comData[langName] : {};
return $.extend(true, {}, initialData[langName] || initialData.en || initialData.zh_cn, langData);
}
return null;
},
lang: function() {
if (arguments.length && $.isPlainObject(arguments[arguments.length - 1])) {
return $.zui.addLangData.apply(null, arguments);
}
return $.zui.getLangData.apply(null, arguments);
},
_scrollbarWidth: 0,
checkBodyScrollbar: function() {
if(document.body.clientWidth >= window.innerWidth) return 0;
if(!$.zui._scrollbarWidth) {
var scrollDiv = document.createElement('div');
scrollDiv.className = 'scrollbar-measure';
document.body.appendChild(scrollDiv);
$.zui._scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
document.body.removeChild(scrollDiv);
}
return $.zui._scrollbarWidth;
},
fixBodyScrollbar: function() {
if($.zui.checkBodyScrollbar()) {
var $body = $('body');
var bodyPad = parseInt(($body.css('padding-right') || 0), 10);
if($.zui._scrollbarWidth) {
$body.css({paddingRight: bodyPad + $.zui._scrollbarWidth, overflowY: 'hidden'});
}
return true;
}
},
resetBodyScrollbar: function() {
$('body').css({paddingRight: '', overflowY: ''});
},
});
$.fn.callEvent = function(name, event, model) {
var $this = $(this);
var dotIndex = name.indexOf('.zui.');
var shortName = dotIndex < 0 ? name : name.substring(0, dotIndex);
var e = $.Event(shortName, event);
if((model === undefined) && dotIndex > 0) {
model = $this.data(name.substring(dotIndex + 1));
}
if(model && model.options) {
var func = model.options[shortName];
if(typeof func === 'function') {
e.result = $.zui.callEvent(func, e, model);
}
}
$this.trigger(e);
return e;
};
$.fn.callComEvent = function(component, eventName, params) {
if (params !== undefined && !Array.isArray(params)) {
params = [params];
}
var $this = this;
var result;
$this.trigger(eventName, params);
var eventCallback = component.options[eventName];
if (eventCallback) {
result = eventCallback.apply(component, params);
}
return result;
};
}(jQuery, window, undefined));
/* ========================================================================
* ZUI: typography.js
* http://openzui.com
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function($) {
'use strict';
$.fn.fixOlPd = function(pd) {
pd = pd || 10;
return this.each(function() {
var $ol = $(this);
$ol.css('paddingLeft', Math.ceil(Math.log10($ol.children().length)) * pd + 10);
});
};
$(function() {
$('.ol-pd-fix,.article ol').fixOlPd();
});
}(jQuery));
/* ========================================================================
* Bootstrap: alert.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#alerts
* ========================================================================
* Copyright 2013 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ZUI: The file has been changed in ZUI. It will not keep update with the
* Bootsrap version in the future.
* http://openzui.com
* ======================================================================== */
+ function($) {
'use strict';
// ALERT CLASS DEFINITION
// ======================
var dismiss = '[data-dismiss="alert"]'
var zuiname = 'zui.alert';
var Alert = function(el) {
$(el).on('click', dismiss, this.close)
}
Alert.prototype.close = function(e) {
var $this = $(this)
var selector = $this.attr('data-target')
if(!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = $(selector)
if(e) e.preventDefault()
if(!$parent.length) {
$parent = $this.hasClass('alert') ? $this : $this.parent()
}
$parent.trigger(e = $.Event('close.' + zuiname))
if(e.isDefaultPrevented()) return
$parent.removeClass('in')
function removeElement() {
$parent.trigger('closed.' + zuiname).remove()
}
$.support.transition && $parent.hasClass('fade') ?
$parent
.one($.support.transition.end, removeElement)
.emulateTransitionEnd(150) :
removeElement()
}
// ALERT PLUGIN DEFINITION
// =======================
var old = $.fn.alert
$.fn.alert = function(option) {
return this.each(function() {
var $this = $(this)
var data = $this.data(zuiname)
if(!data) $this.data(zuiname, (data = new Alert(this)))
if(typeof option == 'string') data[option].call($this)
})
}
$.fn.alert.Constructor = Alert
// ALERT NO CONFLICT
// =================
$.fn.alert.noConflict = function() {
$.fn.alert = old
return this
}
// ALERT DATA-API
// ==============
$(document).on('click.' + zuiname + '.data-api', dismiss, Alert.prototype.close)
}(window.jQuery);
/* ========================================================================
* Bootstrap: transition.js v3.2.0
* http://getbootstrap.com/javascript/#transitions
*
* ZUI: The file has been changed in ZUI. It will not keep update with the
* Bootsrap version in the future.
* http://openzui.com
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+ function($) {
'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
WebkitTransition: 'webkitTransitionEnd',
MozTransition: 'transitionend',
OTransition: 'oTransitionEnd otransitionend',
transition: 'transitionend'
}
for(var name in transEndEventNames) {
if(el.style[name] !== undefined) {
return {
end: transEndEventNames[name]
}
}
}
return false // explicit for ie8 ( ._.)
}
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function(duration) {
var called = false
var $el = this
$(this).one('bsTransitionEnd', function() {
called = true
})
var callback = function() {
if(!called) $($el).trigger($.support.transition.end)
}
setTimeout(callback, duration)
return this
}
$(function() {
$.support.transition = transitionEnd()
if(!$.support.transition) return
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function(e) {
if($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
}
}
})
}(jQuery);
/* ========================================================================
* Bootstrap: collapse.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#collapse
*
* ZUI: The file has been changed in ZUI. It will not keep update with the
* Bootsrap version in the future.
* http://openzui.com
* ========================================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+ function($) {
'use strict';
var zuiname = 'zui.collapse'
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
var Collapse = function(element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
this.transitioning = null
if(this.options.parent) this.$parent = $(this.options.parent)
if(this.options.toggle) this.toggle()
}
Collapse.DEFAULTS = {
toggle: true
}
Collapse.prototype.dimension = function() {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
Collapse.prototype.show = function() {
if(this.transitioning || this.$element.hasClass('in')) return
var startEvent = $.Event('show.' + zuiname)
this.$element.trigger(startEvent)
if(startEvent.isDefaultPrevented()) return
var actives = this.$parent && this.$parent.find('.in')
if(actives && actives.length) {
var hasData = actives.data(zuiname)
if(hasData && hasData.transitioning) return
actives.collapse('hide')
hasData || actives.data(zuiname, null)
}
var dimension = this.dimension()
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
this.transitioning = 1
var complete = function() {
this.$element
.removeClass('collapsing')
.addClass('in')[dimension]('auto')
this.transitioning = 0
this.$element.trigger('shown.' + zuiname)
}
if(!$.support.transition) return complete.call(this)
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
this.$element
.one($.support.transition.end, complete.bind(this))
.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function() {
if(this.transitioning || !this.$element.hasClass('in')) return
var startEvent = $.Event('hide.' + zuiname)
this.$element.trigger(startEvent)
if(startEvent.isDefaultPrevented()) return
var dimension = this.dimension()
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
this.$element
.addClass('collapsing')
.removeClass('collapse')
.removeClass('in')
this.transitioning = 1
var complete = function() {
this.transitioning = 0
this.$element
.trigger('hidden.' + zuiname)
.removeClass('collapsing')
.addClass('collapse')
}
if(!$.support.transition) return complete.call(this)
this.$element[dimension](0)
.one($.support.transition.end, complete.bind(this))
.emulateTransitionEnd(350)
}
Collapse.prototype.toggle = function() {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
// COLLAPSE PLUGIN DEFINITION
// ==========================
var old = $.fn.collapse
$.fn.collapse = function(option) {
return this.each(function() {
var $this = $(this)
var data = $this.data(zuiname)
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
if(!data) $this.data(zuiname, (data = new Collapse(this, options)))
if(typeof option == 'string') data[option]()
})
}
$.fn.collapse.Constructor = Collapse
// COLLAPSE NO CONFLICT
// ====================
$.fn.collapse.noConflict = function() {
$.fn.collapse = old
return this
}
// COLLAPSE DATA-API
// =================
$(document).on('click.' + zuiname + '.data-api', '[data-toggle=collapse]', function(e) {
var $this = $(this),
href
var target = $this.attr('data-target') || e.preventDefault() || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
var $target = $(target)
var data = $target.data(zuiname)
var option = data ? 'toggle' : $this.data()
var parent = $this.attr('data-parent')
var $parent = parent && $(parent)
if(!data || !data.transitioning) {
if($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed')
$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
}
$target.collapse(option)
})
}(window.jQuery);
/* ========================================================================
* ZUI: device.js
* http://openzui.com
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function(window, $) {
'use strict';
var desktopLg = 1200,
desktop = 992,
tablet = 768;
var $window = $(window);
var resetCssClass = function() {
var width = $window.width();
$('html').toggleClass('screen-desktop', width >= desktop && width < desktopLg)
.toggleClass('screen-desktop-wide', width >= desktopLg)
.toggleClass('screen-tablet', width >= tablet && width < desktop)
.toggleClass('screen-phone', width < tablet)
.toggleClass('device-mobile', width < desktop)
.toggleClass('device-desktop', width >= desktop);
};
var classNames = '';
var userAgent = navigator.userAgent;
if (userAgent.match(/(iPad|iPhone|iPod)/i)) {
classNames += ' os-ios';
} else if (userAgent.match(/android/i)) {
classNames += ' os-android';
} else if (userAgent.match(/Win/i)) {
classNames += ' os-windows';
} else if (userAgent.match(/Mac/i)) {
classNames += ' os-mac';
} else if (userAgent.match(/Linux/i)) {
classNames += ' os-linux';
} else if (userAgent.match(/X11/i)) {
classNames += ' os-unix';
}
if ('ontouchstart' in document.documentElement) {
classNames += ' is-touchable';
}
$('html').addClass(classNames);
$window.resize(resetCssClass);
resetCssClass();
}(window, jQuery));
/* ========================================================================
* ZUI: browser.js
* http://openzui.com
* ========================================================================
* Copyright 2014-2020 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function ($) {
'use strict';
var browseHappyTip = {
'zh_cn': '您的浏览器版本过低,无法体验所有功能,建议升级或者更换浏览器。 <a href="https://browsehappy.com/" target="_blank" class="alert-link">了解更多...</a>',
'zh_tw': '您的瀏覽器版本過低,無法體驗所有功能,建議升級或者更换瀏覽器。<a href="https://browsehappy.com/" target="_blank" class="alert-link">了解更多...</a>',
'en': 'Your browser is too old, it has been unable to experience the colorful internet. We strongly recommend that you upgrade a better one. <a href="https://browsehappy.com/" target="_blank" class="alert-link">Learn more...</a>'
};
// The browser modal class
var Browser = function () {
var ie = false;
for (var i = 11; i > 5; i--) {
if (this.isIE(i)) {
ie = i;
break;
}
}
this.ie = ie;
this.cssHelper();
};
// Append CSS class to html tag
Browser.prototype.cssHelper = function () {
var ie = this.ie,
$html = $('html');
$html.toggleClass('ie', ie)
.removeClass('ie-6 ie-7 ie-8 ie-9 ie-10');
if (ie) {
$html.addClass('ie-' + ie)
.toggleClass('gt-ie-7 gte-ie-8 support-ie', ie >= 8)
.toggleClass('lte-ie-7 lt-ie-8 outdated-ie', ie < 8)
.toggleClass('gt-ie-8 gte-ie-9', ie >= 9)
.toggleClass('lte-ie-8 lt-ie-9', ie < 9)
.toggleClass('gt-ie-9 gte-ie-10', ie >= 10)
.toggleClass('lte-ie-9 lt-ie-10', ie < 10)
.toggleClass('gt-ie-10 gte-ie-11', ie >= 11)
.toggleClass('lte-ie-10 lt-ie-11', ie < 11);
}
};
// Show browse happy tip
Browser.prototype.tip = function (showContent) {
var $browseHappy = $('#browseHappyTip');
if (!$browseHappy.length) {
$browseHappy = $('<div id="browseHappyTip" class="alert alert-dismissable alert-danger-inverse alert-block" style="position: relative; z-index: 99999"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button><div class="container"><div class="content text-center"></div></div></div>');
$browseHappy.prependTo('body');
}
if (!showContent) {
showContent = $.zui.getLangData('zui.browser', $.zui.clientLang(), browseHappyTip);
if (typeof showContent === 'object') {
showContent = showContent.tip;
}
}
$browseHappy.find('.content').html(showContent);
};
// Detect it is IE, can given a version
Browser.prototype.isIE = function (version) {
if (version === 11) return this.isIE11();
if (version === 10) return this.isIE10();
if (!version && (this.isIE11() || this.isIE10())) return true;
var b = document.createElement('b');
b.innerHTML = '<!--[if IE ' + (version || '') + ']><i></i><![endif]-->';
return b.getElementsByTagName('i').length === 1;
};
// Detect ie 10 with hack
Browser.prototype.isIE10 = function () {
return navigator.appVersion.indexOf("MSIE 10") !== -1;
};
// Detect ie 10 with hack
Browser.prototype.isIE11 = function () {
var userAgentStr = navigator.userAgent;
return userAgentStr.indexOf("Trident") !== -1 && userAgentStr.indexOf("rv:11") !== -1;
};
$.zui({
browser: new Browser()
});
$(function () {
if (!$('body').hasClass('disabled-browser-tip')) {
if ($.zui.browser.ie && $.zui.browser.ie < 8) {
$.zui.browser.tip();
}
}
});
}(jQuery));
/* ========================================================================
* ZUI: date.js
* Date polyfills
* http://openzui.com
* ========================================================================
* Copyright 2014-2020 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function(window) {
'use strict';
/**
* Ticks of a whole day
* @type {number}
*/
var ONEDAY_TICKS = 24 * 3600 * 1000;
/**
* Create a Date instance
* @param {Date|String|Number} date Date expression
* @return {Date}
*/
var createDate = function(date) {
if (!(date instanceof Date)) {
if (typeof date === 'number' && date < 10000000000) {
date *= 1000;
}
date = new Date(date);
}
return date;
};
/**
* Get timestamp of a Date
* @param {Date|String|Number} date Date expression
* @return {number}
*/
var getTimestamp = function(date) {
return createDate(date).getTime();
};
/**
* Format date to a string
*
* @param {Date|String|Number} Date date expression
* @param {string} [format='yyyy-MM-dd hh:mm:ss'] Date format string
* @return {string}
*/
var formatDate = function(date, format) {
date = createDate(date);
if (format === undefined) {
format = 'yyyy-MM-dd hh:mm:ss';
}
var map = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds(),
'q+': Math.floor((date.getMonth() + 3) / 3),
'S+': date.getMilliseconds()
};
if(/(y+)/i.test(format)) {
format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
}
for(var k in map) {
if(new RegExp('(' + k + ')').test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? map[k] : ('00' + map[k]).substr(('' + map[k]).length));
}
}
return format;
};
/**
* Add milliseconds to the date
* @param {Date} Date date
* @param {number} milliseconds milliseconds value
* @return {Date}
*/
var addMilliseconds = function(date, milliseconds) {
date.setTime(date.getTime() + milliseconds);
return date;
};
/**
* Add milliseconds to the date
* @param {Date} date date
* @param {number} days days value
* @return {Date}
*/
var addDays = function(date, days) {
return addMilliseconds(date, days * ONEDAY_TICKS);
};
/**
* Clone date to a new instance
* @param {Date|String|Number} date date expression
*/
var cloneDate = function(date) {
return new Date(createDate(date).getTime());
};
/**
* Judge the year is in a leap year
* @param {number} year
* @return {boolean}
*/
var isLeapYear = function(year) {
return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
};
/**
* Get days number of the date
* @param {number} year
* @param {number} month
* @return {number}
*/
var getDaysInMonth = function(year, month) {
return [31, (isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};
/**
* Get days number of the date
* @param {Date} date date
* @return {number}
*/
var getDaysOfThisMonth = function(date) {
return getDaysInMonth(date.getFullYear(), date.getMonth());
};
/**
* Clear time part of the date
* @param {Date} date date
* @return {Date}
*/
var clearTime = function(date) {
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
};
/**
* Add months to the date
* @param {Date} date date
* @param {number} monthsCount
* @return {Date}
*/
var addMonths = function(date, monthsCount) {
var n = date.getDate();
date.setDate(1);
date.setMonth(date.getMonth() + monthsCount);
date.setDate(Math.min(n, getDaysOfThisMonth(date)));
return date;
};
/**
* Get last week day of the date
* @param {Date} date date
* @param {number} [day=1] 1 ~ 7
* @return {Date}
*/
var getLastWeekday = function(date, day) {
day = day || 1;
var d = new Date(date.getTime());
while(d.getDay() != day) {
d = addDays(d, -1);
}
return clearTime(d);
};
/**
* Judge the date is same day with another date
* @param {Date} date1
* @param {Date} date2
* @return {boolean}
*/
var isSameDay = function(date1, date2) {
return date1.toDateString() === date2.toDateString();
};
/**
* Judge the date is in same week with another date
* @param {Date} date1
* @param {Date} date2
* @return {boolean}
*/
var isSameWeek = function(date1, date2) {
var weekStart = getLastWeekday(date1);
var weekEnd = addDays(cloneDate(weekStart), 7);
return date2 >= weekStart && date2 < weekEnd;
};
/**
* Judge the date is in same year with another date
* @param {Date} date1
* @param {Date} date2
* @return {boolean}
*/
var isSameYear = function(date1, date2) {
return date1.getFullYear() === date2.getFullYear();
};
var exports = {
formatDate: formatDate,
createDate: createDate,
date: {
ONEDAY_TICKS: ONEDAY_TICKS,
create: createDate,
getTimestamp: getTimestamp,
format: formatDate,
addMilliseconds: addMilliseconds,
addDays: addDays,
cloneDate: cloneDate,
isLeapYear: isLeapYear,
getDaysInMonth: getDaysInMonth,
getDaysOfThisMonth: getDaysOfThisMonth,
clearTime: clearTime,
addMonths: addMonths,
getLastWeekday: getLastWeekday,
isSameDay: isSameDay,
isSameWeek: isSameWeek,
isSameYear: isSameYear,
}
};
if (window.$ && window.$.zui) {
$.zui(exports);
} else {
window.dateHelper = exports.date;
}
if (!window.noDatePrototypeHelper) {
/**
* Ticks of a whole day
* @type {number}
*/
Date.ONEDAY_TICKS = ONEDAY_TICKS;
/**
* Format date to a string
*
* @param string format
* @return string
*/
if(!Date.prototype.format) {
Date.prototype.format = function(format) {
return formatDate(this, format);
};
}
/**
* Add milliseconds to the date
* @param {number} value
*/
if(!Date.prototype.addMilliseconds) {
Date.prototype.addMilliseconds = function(value) {
return addMilliseconds(this, value);
};
}
/**
* Add days to the date
* @param {number} days
*/
if(!Date.prototype.addDays) {
Date.prototype.addDays = function(days) {
return addDays(this, days);
};
}
/**
* Clone a new date instane from the date
* @return {Date}
*/
if(!Date.prototype.clone) {
Date.prototype.clone = function() {
return cloneDate(this);
};
}
/**
* Judge the year is in a leap year
* @param {integer} year
* @return {Boolean}
*/
if(!Date.isLeapYear) {
Date.isLeapYear = function(year) {
return isLeapYear(year);
};
}
if(!Date.getDaysInMonth) {
/**
* Get days number of the date
* @param {integer} year
* @param {integer} month
* @return {integer}
*/
Date.getDaysInMonth = function(year, month) {
return getDaysInMonth(year, month);
};
}
/**
* Judge the date is in a leap year
* @return {Boolean}
*/
if(!Date.prototype.isLeapYear) {
Date.prototype.isLeapYear = function() {
return isLeapYear(this.getFullYear());
};
}
/**
* Clear time part of the date
* @return {date}
*/
if(!Date.prototype.clearTime) {
Date.prototype.clearTime = function() {
return clearTime(this);
};
}
/**
* Get days of this month of the date
* @return {integer}
*/
if(!Date.prototype.getDaysInMonth) {
Date.prototype.getDaysInMonth = function() {
return getDaysOfThisMonth(this);
};
}
/**
* Add months to the date
* @param {number} monthsCount
*/
if(!Date.prototype.addMonths) {
Date.prototype.addMonths = function(monthsCount) {
return addMonths(this, monthsCount);
};
}
/**
* Get last week day of the date
* @param {integer} day
* @return {date}
*/
if(!Date.prototype.getLastWeekday) {
Date.prototype.getLastWeekday = function(day) {
return getLastWeekday(this, day);
};
}
/**
* Judge the date is same day as another date
* @param {Date} date
* @return {Boolean}
*/
if(!Date.prototype.isSameDay) {
Date.prototype.isSameDay = function(date) {
return isSameDay(date, this);
};
}
/**
* Judge the date is in same week as another date
* @param {Date} date
* @return {Boolean}
*/
if(!Date.prototype.isSameWeek) {
Date.prototype.isSameWeek = function(date) {
return isSameWeek(date, this);
};
}
/**
* Judge the date is in same year as another date
* @param {Date} date
* @return {Boolean}
*/
if(!Date.prototype.isSameYear) {
Date.prototype.isSameYear = function(date) {
return isSameYear(this, date);
};
}
/**
* Create an date instance with string, timestamp or date instance
* @param {Date|String|Number} date
* @return {Date}
*/
if (!Date.create) {
Date.create = function(date) {
return createDate(date);
};
}
if (!Date.timestamp) {
Date.timestamp = function(date) {
return getTimestamp(date);
};
}
}
}(window));
/* ========================================================================
* ZUI: string.js
* String Polyfill.
* http://openzui.com
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function() {
'use strict';
/**
* Format string with argument list or object
* @param {String} str
* @param {object | arguments} args
* @return {String}
*/
var formatString = function(str, args) {
if(arguments.length > 1) {
var reg;
if(arguments.length == 2 && typeof(args) == "object") {
for(var key in args) {
if(args[key] !== undefined) {
reg = new RegExp("({" + key + "})", "g");
str = str.replace(reg, args[key]);
}
}
} else {
for(var i = 1; i < arguments.length; i++) {
if(arguments[i] !== undefined) {
reg = new RegExp("({[" + (i - 1) + "]})", "g");
str = str.replace(reg, arguments[i]);
}
}
}
}
return str;
};
/**
* Judge the string is a integer number
*
* @param {String} str
* @access public
* @return {Boolean}
*/
var isNum = function(str) {
if(str !== null) {
var r, re;
re = /\d*/i;
r = str.match(re);
return(r == str) ? true : false;
}
return false;
};
var exports = {
formatString: formatString,
string: {
format: formatString,
isNum: isNum,
}
};
if (window.$ && window.$.zui) {
$.zui(exports);
} else {
window.stringHelper = exports.string;
}
if (!window.noStringPrototypeHelper) {
/**
* Format string with argument list or object
* @param {object | arguments} args
* @return {String}
*/
if(!String.prototype.format) {
String.prototype.format = function() {
var args = [].slice.call(arguments);
args.unshift(this);
return formatString.apply(this, args);
};
}
/**
* Judge the string is a integer number
*
* @access public
* @return bool
*/
if(!String.prototype.isNum) {
String.prototype.isNum = function() {
return isNum(this);
};
}
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
if (!String.prototype.endsWith) {
String.prototype.endsWith = function(search, this_len) {
if (this_len === undefined || this_len > this.length) {
this_len = this.length;
}
return this.substring(this_len - search.length, this_len) === search;
};
}
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
if (!String.prototype.startsWith) {
Object.defineProperty(String.prototype, 'startsWith', {
value: function(search, pos) {
pos = !pos || pos < 0 ? 0 : +pos;
return this.substring(pos, pos + search.length) === search;
}
});
}
if(!String.prototype.includes) {
String.prototype.includes = function() {
return String.prototype.indexOf.apply(this, arguments) !== -1;
};
}
}
})();
/* ========================================================================
* Resize: resize.js [Version: 1.1]
* http://benalman.com/projects/jquery-resize-plugin/
*
* ZUI: The file has been changed in ZUI. It will not keep update with the
* official version in the future.
* http://openzui.com
* ========================================================================
* opyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
* ======================================================================== */
/*!
* jQuery resize event - v1.1
* http://benalman.com/projects/jquery-resize-plugin/
* Copyright (c) 2010 "Cowboy" Ben Alman
* MIT & GPL http://benalman.com/about/license/
*/
// Script: jQuery resize event
//
// *Version: 1.1, Last updated: 3/14/2010*
//
// Project Home - http://benalman.com/projects/jquery-resize-plugin/
// GitHub - http://github.com/cowboy/jquery-resize/
// Source - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.js
// (Minified) - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.min.js (1.0kb)
//
// About: License
//
// Copyright (c) 2010 "Cowboy" Ben Alman,
// Dual licensed under the MIT and GPL licenses.
// http://benalman.com/about/license/
//
// About: Examples
//
// This working example, complete with fully commented code, illustrates a few
// ways in which this plugin can be used.
//
// resize event - http://benalman.com/code/projects/jquery-resize/examples/resize/
//
// About: Support and Testing
//
// Information about what version or versions of jQuery this plugin has been
// tested with, what browsers it has been tested in, and where the unit tests
// reside (so you can test it yourself).
//
// jQuery Versions - 1.3.2, 1.4.1, 1.4.2
// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome, Opera 9.6-10.1.
// Unit Tests - http://benalman.com/code/projects/jquery-resize/unit/
//
// About: Release History
//
// 1.1 - (3/14/2010) Fixed a minor bug that was causing the event to trigger
// immediately after bind in some circumstances. Also changed $.fn.data
// to $.data to improve performance.
// 1.0 - (2/10/2010) Initial release
(function($, window, undefined) {
'$:nomunge'; // Used by YUI compressor.
// A jQuery object containing all non-window elements to which the resize
// event is bound.
var elems = $([]),
// Extend $.resize if it already exists, otherwise create it.
jq_resize = $.resize = $.extend($.resize, {}),
timeout_id,
// Reused strings.
str_setTimeout = 'setTimeout',
str_resize = 'resize',
str_data = str_resize + '-special-event',
str_delay = 'delay',
str_throttle = 'throttleWindow';
// Property: jQuery.resize.delay
//
// The numeric interval (in milliseconds) at which the resize event polling
// loop executes. Defaults to 250.
jq_resize[str_delay] = 250;
// Property: jQuery.resize.throttleWindow
//
// Throttle the native window object resize event to fire no more than once
// every <jQuery.resize.delay> milliseconds. Defaults to true.
//
// Because the window object has its own resize event, it doesn't need to be
// provided by this plugin, and its execution can be left entirely up to the
// browser. However, since certain browsers fire the resize event continuously
// while others do not, enabling this will throttle the window resize event,
// making event behavior consistent across all elements in all browsers.
//
// While setting this property to false will disable window object resize
// event throttling, please note that this property must be changed before any
// window object resize event callbacks are bound.
jq_resize[str_throttle] = true;
// Event: resize event
//
// Fired when an element's width or height changes. Because browsers only
// provide this event for the window element, for other elements a polling
// loop is initialized, running every <jQuery.resize.delay> milliseconds
// to see if elements' dimensions have changed. You may bind with either
// .resize( fn ) or .bind( "resize", fn ), and unbind with .unbind( "resize" ).
//
// Usage:
//
// > jQuery('selector').bind( 'resize', function(e) {
// > // element's width or height has changed!
// > ...
// > });
//
// Additional Notes:
//
// * The polling loop is not created until at least one callback is actually
// bound to the 'resize' event, and this single polling loop is shared
// across all elements.
//
// Double firing issue in jQuery 1.3.2:
//
// While this plugin works in jQuery 1.3.2, if an element's event callbacks
// are manually triggered via .trigger( 'resize' ) or .resize() those
// callbacks may double-fire, due to limitations in the jQuery 1.3.2 special
// events system. This is not an issue when using jQuery 1.4+.
//
// > // While this works in jQuery 1.4+
// > $(elem).css({ width: new_w, height: new_h }).resize();
// >
// > // In jQuery 1.3.2, you need to do this:
// > var elem = $(elem);
// > elem.css({ width: new_w, height: new_h });
// > elem.data( 'resize-special-event', { width: elem.width(), height: elem.height() } );
// > elem.resize();
$.event.special[str_resize] = {
// Called only when the first 'resize' event callback is bound per element.
setup: function() {
// Since window has its own native 'resize' event, return false so that
// jQuery will bind the event using DOM methods. Since only 'window'
// objects have a .setTimeout method, this should be a sufficient test.
// Unless, of course, we're throttling the 'resize' event for window.
if(!jq_resize[str_throttle] && this[str_setTimeout]) {
return false;
}
var elem = $(this);
// Add this element to the list of internal elements to monitor.
elems = elems.add(elem);
// Initialize data store on the element.
$.data(this, str_data, {
w: elem.width(),
h: elem.height()
});
// If this is the first element added, start the polling loop.
if(elems.length === 1) {
loopy();
}
},
// Called only when the last 'resize' event callback is unbound per element.
teardown: function() {
// Since window has its own native 'resize' event, return false so that
// jQuery will unbind the event using DOM methods. Since only 'window'
// objects have a .setTimeout method, this should be a sufficient test.
// Unless, of course, we're throttling the 'resize' event for window.
if(!jq_resize[str_throttle] && this[str_setTimeout]) {
return false;
}
var elem = $(this);
// Remove this element from the list of internal elements to monitor.
elems = elems.not(elem);
// Remove any data stored on the element.
elem.removeData(str_data);
// If this is the last element removed, stop the polling loop.
if(!elems.length) {
clearTimeout(timeout_id);
}
},
// Called every time a 'resize' event callback is bound per element (new in
// jQuery 1.4).
add: function(handleObj) {
// Since window has its own native 'resize' event, return false so that
// jQuery doesn't modify the event object. Unless, of course, we're
// throttling the 'resize' event for window.
if(!jq_resize[str_throttle] && this[str_setTimeout]) {
return false;
}
var old_handler;
// The new_handler function is executed every time the event is triggered.
// This is used to update the internal element data store with the width
// and height when the event is triggered manually, to avoid double-firing
// of the event callback. See the "Double firing issue in jQuery