长城期货
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3978 lines
129 KiB

/*!
* 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 1.3.2"
// comments above for more information.
function new_handler(e, w, h) {
var elem = $(this),
data = $.data(this, str_data) || {};
// If called from the polling loop, w and h will be passed in as
// arguments. If called manually, via .trigger( 'resize' ) or .resize(),
// those values will need to be computed.
data.w = w !== undefined ? w : elem.width();
data.h = h !== undefined ? h : elem.height();
old_handler.apply(this, arguments);
};
// This may seem a little complicated, but it normalizes the special event
// .add method between jQuery 1.4/1.4.1 and 1.4.2+
if(typeof handleObj === 'function') {
// 1.4, 1.4.1
old_handler = handleObj;
return new_handler;
} else {
// 1.4.2+
old_handler = handleObj.handler;
handleObj.handler = new_handler;
}
}
};
function loopy() {
// Start the polling loop, asynchronously.
timeout_id = window[str_setTimeout](function() {
// Iterate over all elements to which the 'resize' event is bound.
elems.each(function() {
var elem = $(this),
width = elem.width(),
height = elem.height(),
data = $.data(this, str_data);
// If element size has changed since the last time, update the element
// data store and trigger the 'resize' event.
if(width !== data.w || height !== data.h) {
elem.trigger(str_resize, [data.w = width, data.h = height]);
}
});
// Loop.
loopy();
}, jq_resize[str_delay]);
};
})(jQuery, this);
/* ========================================================================
* ZUI: storeb.js
* http://openzui.com
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function(window, $) {
'use strict';
var lsName = 'localStorage';
var storage,
dataset,
pageName = 'page_' + window.location.pathname + window.location.search;
/* The Store object */
var Store = function() {
this.silence = true;
try {
if((lsName in window) && window[lsName] && window[lsName].setItem) {
this.enable = true;
storage = window[lsName];
}
} catch(e){}
if(!this.enable) {
dataset = {};
storage = {
getLength: function() {
var length = 0;
$.each(dataset, function() {
length++;
});
return length;
},
key: function(index) {
var key, i = 0;
$.each(dataset, function(k) {
if(i === index) {
key = k;
return false;
}
i++;
});
return key;
},
removeItem: function(key) {
delete dataset[key];
},
getItem: function(key) {
return dataset[key];
},
setItem: function(key, val) {
dataset[key] = val;
},
clear: function() {
dataset = {};
}
};
}
this.storage = storage;
this.page = this.get(pageName, {});
};
/* Save page data */
Store.prototype.pageSave = function() {
if($.isEmptyObject(this.page)) {
this.remove(pageName);
} else {
var forDeletes = [],
i;
for(i in this.page) {
var val = this.page[i];
if(val === null)
forDeletes.push(i);
}
for(i = forDeletes.length - 1; i >= 0; i--) {
delete this.page[forDeletes[i]];
}
this.set(pageName, this.page);
}
};
/* Remove page data item */
Store.prototype.pageRemove = function(key) {
if(typeof this.page[key] != 'undefined') {
this.page[key] = null;
this.pageSave();
}
};
/* Clear page data */
Store.prototype.pageClear = function() {
this.page = {};
this.pageSave();
};
/* Get page data */
Store.prototype.pageGet = function(key, defaultValue) {
var val = this.page[key];
return(defaultValue !== undefined && (val === null || val === undefined)) ? defaultValue : val;
};
/* Set page data */
Store.prototype.pageSet = function(objOrKey, val) {
if($.isPlainObject(objOrKey)) {
$.extend(true, this.page, objOrKey);
} else {
this.page[this.serialize(objOrKey)] = val;
}
this.pageSave();
};
/* Check enable status */
Store.prototype.check = function() {
if(!this.enable) {
if(!this.silence) throw new Error('Browser not support localStorage or enable status been set true.');
}
return this.enable;
};
/* Get length */
Store.prototype.length = function() {
if(this.check()) {
return storage.getLength ? storage.getLength() : storage.length;
}
return 0;
};
/* Remove item with browser localStorage native method */
Store.prototype.removeItem = function(key) {
storage.removeItem(key);
return this;
};
/* Remove item with browser localStorage native method, same as removeItem */
Store.prototype.remove = function(key) {
return this.removeItem(key);
};
/* Get item value with browser localStorage native method, and without deserialize */
Store.prototype.getItem = function(key) {
return storage.getItem(key);
};
/* Get item value and deserialize it, if value is null and defaultValue been given then return defaultValue */
Store.prototype.get = function(key, defaultValue) {
var val = this.deserialize(this.getItem(key));
if(typeof val === 'undefined' || val === null) {
if(typeof defaultValue !== 'undefined') {
return defaultValue;
}
}
return val;
};
/* Get item key by index and deserialize it */
Store.prototype.key = function(index) {
return storage.key(index);
};
/* Set item value with browser localStorage native method, and without serialize filter */
Store.prototype.setItem = function(key, val) {
storage.setItem(key, val);
return this;
};
/* Set item value, serialize it if the given value is not an string */
Store.prototype.set = function(key, val) {
if(val === undefined) return this.remove(key);
this.setItem(key, this.serialize(val));
return this;
};
/* Clear all items with browser localStorage native method */
Store.prototype.clear = function() {
storage.clear();
return this;
};
/* Iterate all items with callback */
Store.prototype.forEach = function(callback) {
var length = this.length();
for(var i = length - 1; i >= 0; i--) {
var key = storage.key(i);
callback(key, this.get(key));
}
return this;
};
/* Get all items and set value in an object. */
Store.prototype.getAll = function() {
var all = {};
this.forEach(function(key, val) {
all[key] = val;
});
return all;
};
/* Serialize value with JSON.stringify */
Store.prototype.serialize = function(value) {
if(typeof value === 'string') return value;
return JSON.stringify(value);
};
/* Deserialize value, with JSON.parse if the given value is not a string */
Store.prototype.deserialize = function(value) {
if(typeof value !== 'string') return undefined;
try {
return JSON.parse(value);
} catch(e) {
return value || undefined;
}
};
$.zui({
store: new Store()
});
}(window, jQuery));
/* ========================================================================
* Bootstrap: tab.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#tabs
*
* 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';
// TAB CLASS DEFINITION
// ====================
var zuiname = 'zui.tab'
var Tab = function(element) {
this.element = $(element)
}
Tab.prototype.show = function() {
var $this = this.element
var $ul = $this.closest('ul:not(.dropdown-menu)')
var selector = $this.attr('data-target') || $this.attr('data-tab')
if(!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
if($this.parent('li').hasClass('active')) return
var previous = $ul.find('.active:last a')[0]
var e = $.Event('show.' + zuiname, {
relatedTarget: previous
})
$this.trigger(e)
if(e.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.parent('li'), $ul)
this.activate($target, $target.parent(), function() {
$this.trigger({
type: 'shown.' + zuiname,
relatedTarget: previous
})
})
}
Tab.prototype.activate = function(element, container, callback) {
var $active = container.find('> .active')
var transition = callback && $.support.transition && $active.hasClass('fade')
function next() {
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
.removeClass('active')
element.addClass('active')
if(transition) {
element[0].offsetWidth // reflow for transition
element.addClass('in')
} else {
element.removeClass('fade')
}
if(element.parent('.dropdown-menu')) {
element.closest('li.dropdown').addClass('active')
}
callback && callback()
}
transition ?
$active
.one($.support.transition.end, next)
.emulateTransitionEnd(150) :
next()
$active.removeClass('in')
}
// TAB PLUGIN DEFINITION
// =====================
var old = $.fn.tab
$.fn.tab = function(option) {
return this.each(function() {
var $this = $(this)
var data = $this.data(zuiname)
if(!data) $this.data(zuiname, (data = new Tab(this)))
if(typeof option == 'string') data[option]()
})
}
$.fn.tab.Constructor = Tab
// TAB NO CONFLICT
// ===============
$.fn.tab.noConflict = function() {
$.fn.tab = old
return this
}
// TAB DATA-API
// ============
$(document).on('click.zui.tab.data-api', '[data-toggle="tab"], [data-tab]', function(e) {
e.preventDefault()
$(this).tab('show')
})
}(window.jQuery);
/* ========================================================================
* Bootstrap: modal.js v3.2.0
* http://getbootstrap.com/javascript/#modals
*
* 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)
* ========================================================================
* Updates in ZUI:
* 1. changed event namespace to *.zui.modal
* 2. added position option to ajust poisition of modal
* 3. added event 'escaping.zui.modal' with an param 'esc' to judge the esc
* key down
* 4. get moveable options value from '.modal-moveable' on '.modal-dialog'
* 5. add setMoveable method to make modal dialog moveable
* 6. add options.onSetScrollbar
* ======================================================================== */
+ function($, undefined) {
'use strict';
// MODAL CLASS DEFINITION
// ======================
var zuiname = 'zui.modal'
var Modal = function(element, options) {
var that = this;
that.options = options
that.$body = $(document.body)
that.$element = $(element)
that.$backdrop =
that.isShown = null
that.scrollbarWidth = 0
if(options.moveable === undefined) {
that.options.moveable = that.$element.hasClass('modal-moveable');
}
if(options.remote) {
that.$element
.find('.modal-content')
.load(options.remote, function() {
that.$element.trigger('loaded.' + zuiname)
})
}
if (options.scrollInside) {
$(window).on('resize.' + zuiname, function() {
if (that.isShown) {
that.adjustPosition(undefined, 100);
}
});
}
}
Modal.VERSION = '3.2.0'
Modal.TRANSITION_DURATION = 300
Modal.BACKDROP_TRANSITION_DURATION = 150
Modal.DEFAULTS = {
backdrop: true,
keyboard: true,
show: true,
// rememberPos: false,
// moveable: false,
position: 'fit', // 'center' or '40px' or '10%',
// scrollInside: false,
// headerHeight: 'auto',
};
var setDialogPos = function($dialog, pos) {
var $window = $(window);
pos.left = Math.max(0, Math.min(pos.left, $window.width() - $dialog.outerWidth()));
pos.top = Math.max(0, Math.min(pos.top, $window.height() - $dialog.outerHeight()));
$dialog.css(pos);
};
Modal.prototype.toggle = function(_relatedTarget, position) {
return this.isShown ? this.hide() : this.show(_relatedTarget, position)
}
Modal.prototype.adjustPosition = function(position, delay) {
var that = this;
clearTimeout(that.reposTask);
if (delay) {
that.reposTask = setTimeout(that.adjustPosition.bind(that, position, 0), delay);
return;
}
var options = that.options;
if(position === undefined) position = options.position;
if(position === undefined || position === null) return;
if (typeof position === 'function') {
position = position(that);
}
var $dialog = that.$element.find('.modal-dialog');
var winHeight = $(window).height();
var bodyCss = {maxHeight: 'initial', overflow: 'visible'};
var $body = $dialog.find('.modal-body').css(bodyCss);
if (options.scrollInside && $body.length) {
var headerHeight = options.headerHeight;
var footerHeight = options.footerHeight;
var $header = $dialog.find('.modal-header');
var $footer = $dialog.find('.modal-footer');
if (typeof headerHeight !== 'number') {
if ($header.length) {
headerHeight = $header.outerHeight();
} else if (typeof headerHeight === 'function') {
headerHeight = headerHeight($header);
} else {
headerHeight = 0;
}
}
if (typeof footerHeight !== 'number') {
if ($footer.length) {
footerHeight = $footer.outerHeight();
} else if (typeof footerHeight === 'function') {
footerHeight = footerHeight($footer);
} else {
footerHeight = 0;
}
}
bodyCss.maxHeight = winHeight - headerHeight - footerHeight;
bodyCss.overflow = $body[0].scrollHeight > bodyCss.maxHeight ? 'auto' : 'visible';
$body.css(bodyCss);
}
var half = Math.max(0, (winHeight - $dialog.outerHeight()) / 2);
if (position === 'fit') {
position = {top: half > 50 ? Math.floor(half * 2 / 3) : half};
} else if (position === 'center') {
position = {top: half};
} else if (!$.isPlainObject(position)) {
position = {top: position};
}
if($dialog.hasClass('modal-moveable')) {
var pos = null;
var rememberPos = options.rememberPos;
if(rememberPos) {
if(rememberPos === true) {
pos = that.$element.data('modal-pos');
} else if($.zui.store) {
pos = $.zui.store.pageGet(zuiname + '.rememberPos.' + rememberPos);
}
}
position = $.extend(position, {left: Math.max(0, ($(window).width() - $dialog.outerWidth()) / 2)}, pos);
if (options.moveable === 'inside') {
setDialogPos($dialog, position);
} else {
$dialog.css(position);
}
} else {
$dialog.css(position);
}
}
Modal.prototype.setMoveable = function() {
if(!$.fn.draggable) console.error('Moveable modal requires draggable.js.');
var that = this;
var options = that.options;
var $dialog = that.$element.find('.modal-dialog').removeClass('modal-dragged');
$dialog.toggleClass('modal-moveable', !!options.moveable);
if(!that.$element.data('modal-moveable-setup')) {
$dialog.draggable({
container: that.$element,
handle: '.modal-header',
before: function() {
var marginTop = $dialog.css('margin-top');
if (marginTop && marginTop !== '0px') {
$dialog.css('top', marginTop).css('margin-top', '').addClass('modal-dragged');
}
},
finish: function(e) {
var rememberPos = options.rememberPos;
if(rememberPos) {
that.$element.data('modal-pos', e.pos);
if($.zui.store && rememberPos !== true) {
$.zui.store.pageSet(zuiname + '.rememberPos.' + rememberPos, e.pos);
}
}
},
move: options.moveable === 'inside' ? function (dragPos) {
setDialogPos($dialog, dragPos);
} : true
});
}
}
Modal.prototype.show = function(_relatedTarget, position) {
var that = this
var e = $.Event('show.' + zuiname, {
relatedTarget: _relatedTarget
})
that.$element.trigger(e)
that.$element.toggleClass('modal-scroll-inside', !!that.options.scrollInside);
if(that.isShown || e.isDefaultPrevented()) return
that.isShown = true
if(that.options.moveable) that.setMoveable();
if (that.options.backdrop !== false) {
that.setScrollbar();
that.$body.addClass('modal-open')
}
that.escape()
that.$element.on('click.dismiss.' + zuiname, '[data-dismiss="modal"]',function(e) {
that.hide();
e.stopPropagation();
})
that.backdrop(function() {
var transition = $.support.transition && that.$element.hasClass('fade')
if(!that.$element.parent().length) {
that.$element.appendTo(that.$body) // don't move modals dom position
}
that.$element
.show()
.scrollTop(0)
if(transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.adjustPosition(position);
that.enforceFocus()
var e = $.Event('shown.' + zuiname, {
relatedTarget: _relatedTarget
})
transition ?
that.$element.find('.modal-dialog') // wait for modal to slide in
.one('bsTransitionEnd', function() {
that.$element.trigger('focus').trigger(e)
})
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
})
}
Modal.prototype.hide = function(e) {
if(e && e.preventDefault) e.preventDefault()
var that = this;
e = $.Event('hide.' + zuiname)
that.$element.trigger(e)
if(!that.isShown || e.isDefaultPrevented()) return
that.isShown = false
if (that.options.backdrop !== false) {
that.$body.removeClass('modal-open')
that.resetScrollbar()
}
that.escape()
$(document).off('focusin.' + zuiname)
that.$element
.removeClass('in')
.attr('aria-hidden', true)
.off('click.dismiss.' + zuiname)
$.support.transition && that.$element.hasClass('fade') ?
that.$element
.one('bsTransitionEnd', that.hideModal.bind(that))
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.hideModal()
}
Modal.prototype.enforceFocus = function() {
$(document)
.off('focusin.' + zuiname) // guard against infinite focus loop
.on('focusin.' + zuiname, (function(e) {
if(this.$element[0] !== e.target && !this.$element.has(e.target).length) {
this.$element.trigger('focus')
}
}).bind(this))
}
Modal.prototype.escape = function() {
if(this.isShown && this.options.keyboard) {
$(document).on('keydown.dismiss.' + zuiname, (function(e) {
if(e.which == 27) {
var et = $.Event('escaping.' + zuiname)
var result = this.$element.triggerHandler(et, 'esc')
if(result != undefined && (!result)) return
this.hide()
}
}).bind(this))
} else if(!this.isShown) {
$(document).off('keydown.dismiss.' + zuiname)
}
}
Modal.prototype.hideModal = function() {
var that = this
this.$element.hide()
this.backdrop(function() {
that.$element.trigger('hidden.' + zuiname)
})
}
Modal.prototype.removeBackdrop = function() {
this.$backdrop && this.$backdrop.remove()
this.$backdrop = null
}
Modal.prototype.backdrop = function(callback) {
var that = this
var animate = this.$element.hasClass('fade') ? 'fade' : ''
if(this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(this.$body)
this.$element.on('mousedown.dismiss.' + zuiname, (function(e) {
if(e.target !== e.currentTarget) return
this.options.backdrop == 'static' ? this.$element[0].focus.call(this.$element[0]) : this.hide.call(this)
}).bind(this))
if(doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
if(!callback) return
doAnimate ?
this.$backdrop
.one('bsTransitionEnd', callback)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callback()
} else if(!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
var callbackRemove = function() {
that.removeBackdrop()
callback && callback()
}
$.support.transition && this.$element.hasClass('fade') ?
this.$backdrop
.one('bsTransitionEnd', callbackRemove)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callbackRemove()
} else if(callback) {
callback()
}
}
Modal.prototype.setScrollbar = function() {
if($.zui.fixBodyScrollbar()) {
if (this.options.onSetScrollbar) {
this.options.onSetScrollbar();
}
}
}
Modal.prototype.resetScrollbar = function() {
$.zui.resetBodyScrollbar();
if (this.options.onSetScrollbar) {
this.options.onSetScrollbar('');
}
}
Modal.prototype.measureScrollbar = function() { // thx walsh
var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure'
this.$body.append(scrollDiv)
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
this.$body[0].removeChild(scrollDiv)
return scrollbarWidth
}
// MODAL PLUGIN DEFINITION
// =======================
function Plugin(option, _relatedTarget, position) {
return this.each(function() {
var $this = $(this)
var data = $this.data(zuiname)
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
if(!data) $this.data(zuiname, (data = new Modal(this, options)))
if(typeof option == 'string') data[option](_relatedTarget, position)
else if(options.show) data.show(_relatedTarget, position)
})
}
var old = $.fn.modal
$.fn.modal = Plugin
$.fn.modal.Constructor = Modal
// MODAL NO CONFLICT
// =================
$.fn.modal.noConflict = function() {
$.fn.modal = old
return this
}
// MODAL DATA-API
// ==============
$(document).on('click.' + zuiname + '.data-api', '[data-toggle="modal"]', function(e) {
var $this = $(this)
var href = $this.attr('href')
var $target = null
try {
// strip for ie7
$target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, '')));
} catch(ex) {
return
}
if(!$target.length) return;
var option = $target.data(zuiname) ? 'toggle' : $.extend({
remote: !/#/.test(href) && href
}, $target.data(), $this.data())
if($this.is('a')) e.preventDefault()
$target.one('show.' + zuiname, function(showEvent) {
// only register focus restorer if modal will actually get shown
if(showEvent.isDefaultPrevented()) return
$target.one('hidden.' + zuiname, function() {
$this.is(':visible') && $this.trigger('focus')
})
})
Plugin.call($target, option, this, $this.data('position'))
})
}(jQuery, undefined);
/* ========================================================================
* ZUI: modal.trigger.js [1.2.0+]
* http://openzui.com
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function($, window, undefined) {
'use strict';
if(!$.fn.modal) throw new Error('Modal trigger requires modal.js');
var NAME = 'zui.modaltrigger',
STR_AJAX = 'ajax',
ZUI_MODAL = '.zui.modal',
STR_STRING = 'string';
// MODAL TRIGGER CLASS DEFINITION
// ======================
var ModalTrigger = function(options, $trigger) {
options = $.extend({}, ModalTrigger.DEFAULTS, $.ModalTriggerDefaults, $trigger ? $trigger.data() : null, options);
this.isShown;
this.$trigger = $trigger;
this.options = options;
this.id = $.zui.uuid();
if (options.show) {
this.show();
}
};
ModalTrigger.DEFAULTS = {
type: 'custom',
// width: null, // number, css definition
// size: null, // 'md', 'sm', 'lg', 'fullscreen'
height: 'auto',
// icon: null,
name: 'triggerModal',
// className: '',
fade: true,
position: 'fit',
showHeader: true,
delay: 0,
// iframeBodyClass: '',
// onlyIncreaseHeight: false,
// moveable: false,
// rememberPos: false,
backdrop: true,
keyboard: true,
waittime: 0,
loadingIcon: 'icon-spinner-indicator',
scrollInside: false,
// handleLinkInIframe: false,
// iframeStyle: ''
// headerHeight: 'auto',
};
ModalTrigger.prototype.initOptions = function(options) {
if(options.url) {
if(!options.type || (options.type != STR_AJAX && options.type != 'iframe')) {
options.type = STR_AJAX;
}
}
if(options.remote) {
options.type = STR_AJAX;
if(typeof options.remote === STR_STRING) options.url = options.remote;
} else if(options.iframe) {
options.type = 'iframe';
if(typeof options.iframe === STR_STRING) options.url = options.iframe;
} else if(options.custom) {
options.type = 'custom';
if(typeof options.custom === STR_STRING) {
var $doms;
try {
$doms = $(options.custom);
} catch(e) {}
if($doms && $doms.length) {
options.custom = $doms;
} else if(typeof window[options.custom] === 'function') {
options.custom = window[options.custom];
}
}
}
return options;
};
ModalTrigger.prototype.init = function(options) {
var that = this;
var $modal = $('#' + options.name);
if($modal.length) {
if(!that.isShown) $modal.off(ZUI_MODAL);
$modal.remove();
}
$modal = $('<div id="' + options.name + '" class="modal modal-trigger ' + (options.className || '') + '">' + (typeof options.loadingIcon === 'string' && options.loadingIcon.indexOf('icon-') === 0 ? ('<div class="icon icon-spin loader ' + options.loadingIcon + '"></div>') : options.loadingIcon) + '<div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button class="close" data-dismiss="modal">×</button><h4 class="modal-title"><i class="modal-icon"></i> <span class="modal-title-name"></span></h4></div><div class="modal-body"></div></div></div></div>').appendTo('body').data(NAME, that);
var bindEvent = function(optonName, eventName, handleFunc) {
handleFunc = handleFunc || options[optonName];
if(typeof handleFunc === 'function') $modal.on(eventName + ZUI_MODAL, handleFunc);
};
bindEvent('onShow', 'show');
bindEvent('shown', 'shown');
bindEvent('onHide', 'hide', function(e) {
if (options.type === 'iframe' && that.$iframeBody) {
var result = that.$iframeBody.triggerHandler('modalhide' + ZUI_MODAL, [that]);
if (result === false) {
e.preventDefault();
}
}
var handleFunc = options.onHide;
if (handleFunc) {
return handleFunc(e);
}
});
bindEvent('hidden', 'hidden');
bindEvent('loaded', 'loaded');
$modal.on('shown' + ZUI_MODAL, function() {
that.isShown = true;
}).on('hidden' + ZUI_MODAL, function() {
that.isShown = false;
});
this.$modal = $modal;
this.$dialog = $modal.find('.modal-dialog');
if(options.mergeOptions) this.options = options;
};
ModalTrigger.prototype.show = function(option) {
var that = this;
var options = $.extend({}, ModalTrigger.DEFAULTS, that.options, {
url: that.$trigger ? (that.$trigger.attr('href') || that.$trigger.attr('data-url') || that.$trigger.data('url')) : that.options.url
}, option);
var isShown = that.isShown;
options = that.initOptions(options);
if (!isShown) {
that.init(options);
}
var $modal = that.$modal;
var $dialog = $modal.find('.modal-dialog');
var custom = options.custom;
var $body = $dialog.find('.modal-body').css('padding', '').toggleClass('load-indicator loading', !!isShown),
$header = $dialog.find('.modal-header'),
$content = $dialog.find('.modal-content');
$modal.toggleClass('fade', options.fade)
.addClass(options.className)
.toggleClass('modal-loading', !isShown)
.toggleClass('modal-scroll-inside', !!options.scrollInside);
$dialog.toggleClass('modal-md', options.size === 'md')
.toggleClass('modal-sm', options.size === 'sm')
.toggleClass('modal-lg', options.size === 'lg')
.toggleClass('modal-fullscreen', options.size === 'fullscreen');
$header.toggle(options.showHeader);
$header.find('.modal-icon').attr('class', 'modal-icon icon-' + options.icon);
$header.find('.modal-title-name').text(options.title || '');
if(options.size && options.size === 'fullscreen') {
options.width = '';
options.height = '';
}
var resizeDialog = function() {
clearTimeout(this.resizeTask);
this.resizeTask = setTimeout(function() {
that.adjustPosition(options.position);
}, 100);
};
var readyToShow = function(delay, callback) {
if(typeof delay === 'undefined') delay = options.delay;
return setTimeout(function() {
$dialog = $modal.find('.modal-dialog');
if(options.width && options.width != 'auto') {
$dialog.css('width', options.width);
}
if(options.height && options.height != 'auto') {
$dialog.css('height', options.height);
if(options.type === 'iframe') $body.css('height', $dialog.height() - $header.outerHeight());
}
that.adjustPosition(options.position);
$modal.removeClass('modal-loading').removeClass('modal-updating');
if(isShown) {
$body.removeClass('loading');
}
if(options.type != 'iframe') {
$body = $dialog.off('resize.' + NAME).find('.modal-body').off('resize.' + NAME);
if(options.scrollInside) $body = $body.children().off('resize.' + NAME);
($body.length ? $body : $dialog).on('resize.' + NAME, resizeDialog);
}
callback && callback();
}, delay);
};
if(options.type === 'custom' && custom) {
if(typeof custom === 'function') {
var customContent = custom({
modal: $modal,
options: options,
modalTrigger: that,
ready: readyToShow
});
if(typeof customContent === STR_STRING) {
$body.html(customContent);
readyToShow();
}
} else if(custom instanceof $) {
$body.html($('<div>').append(custom.clone()).html());
readyToShow();
} else {
$body.html(custom);
readyToShow();
}
} else if(options.url) {
var onLoadBroken = function() {
var brokenContent = $modal.callComEvent(that, 'broken');
if(typeof brokenContent === 'string') {
$body.html(brokenContent);
}
readyToShow();
};
$modal.attr('ref', options.url);
if(options.type === 'iframe') {
$modal.addClass('modal-iframe');
this.firstLoad = true;
var iframeName = 'iframe-' + options.name;
$header.detach();
$body.detach();
$content.empty().append($header).append($body);
$body.css('padding', 0)
.html('<iframe id="' + iframeName + '" name="' + iframeName + '" src="' + options.url + '" frameborder="no" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" allowtransparency="true" scrolling="auto" style="width: 100%; height: 100%; left: 0px;"></iframe>');
if(options.waittime > 0) {
that.waitTimeout = readyToShow(options.waittime, onLoadBroken);
}
var frame = document.getElementById(iframeName);
frame.onload = frame.onreadystatechange = function(e) {
var scrollInside = !!options.scrollInside;
if(that.firstLoad) $modal.addClass('modal-loading');
if(this.readyState && this.readyState != 'complete') return;
that.firstLoad = false;
if(options.waittime > 0) {
clearTimeout(that.waitTimeout);
}
try {
$modal.attr('ref', frame.contentWindow.location.href);
var frame$ = window.frames[iframeName].$;
if(frame$ && options.height === 'auto' && options.size != 'fullscreen') {
// todo: update iframe url to ref attribute
var $framebody = frame$('body').addClass('body-modal').toggleClass('body-modal-scroll-inside', scrollInside);
that.$iframeBody = $framebody;
if(options.iframeBodyClass) $framebody.addClass(options.iframeBodyClass);
var frameSizeRecords = [];
var ajustFrameSize = function(check) {
$modal.removeClass('fade');
var height = $framebody.outerHeight();
if(check === true && options.onlyIncreaseHeight) {
height = Math.max(height, $body.data('minModalHeight') || 0);
$body.data('minModalHeight', height);
}
if (scrollInside) {
var headerHeight = options.headerHeight;
if (typeof headerHeight !== 'number') {
headerHeight = $header.outerHeight();
} else if (typeof headerHeight === 'function') {
headerHeight = headerHeight($header);
}
var winHeight = $(window).height();
height = Math.min(height, winHeight - headerHeight);
}
if (frameSizeRecords.length > 1 && height === frameSizeRecords[0]) {
height = Math.max(height, frameSizeRecords[1]);
}
frameSizeRecords.push(height);
while (frameSizeRecords.length > 2) {
frameSizeRecords.shift();
}
$body.css('height', height);
if(options.fade) $modal.addClass('fade');
readyToShow();
};
$modal.callComEvent(that, 'loaded', {
modalType: 'iframe',
jQuery: frame$
});
setTimeout(ajustFrameSize, 100);
$framebody.off('resize.' + NAME).on('resize.' + NAME, ajustFrameSize);
if (scrollInside) {
$(window).off('resize.' + NAME).on('resize.' + NAME, ajustFrameSize);
}
} else {
readyToShow();
}
var handleLinkInIframe = options.handleLinkInIframe;
if (handleLinkInIframe) {
frame$('body').on('click', typeof handleLinkInIframe === 'string' ? handleLinkInIframe : 'a[href]', function() {
if ($(this).is('[data-toggle="modal"]')) return;
$modal.addClass('modal-updating');
});
}
if (options.iframeStyle) {
frame$('head').append('<style>' + options.iframeStyle + '</style>');
}
} catch(e) {
readyToShow();
}
};
} else {
$.ajax($.extend({
url: options.url,
success: function(data) {
try {
var $data = $(data);
if($data.filter('.modal-dialog').length) {
$dialog.parent().empty().append($data);
} else if($data.filter('.modal-content').length) {
$dialog.find('.modal-content').replaceWith($data);
} else {
$body.wrapInner($data);
}
} catch(e) {
if (window.console && window.console.warn) {
console.warn('ZUI: Cannot recogernize remote content.', {error: e, data: data});
}
$modal.html(data);
}
$modal.callComEvent(that, 'loaded', {
modalType: STR_AJAX
});
readyToShow();
if (options.scrollInside) {
$(window).off('resize.' + NAME).on('resize.' + NAME, resizeDialog);
}
},
error: onLoadBroken
}, options.ajaxOptions));
}
}
if (!isShown) {
$modal.modal({
show : 'show',
backdrop : options.backdrop,
moveable : options.moveable,
rememberPos : options.rememberPos,
keyboard : options.keyboard,
scrollInside : options.scrollInside,
});
}
};
ModalTrigger.prototype.close = function(callback, redirect) {
var that = this;
if(callback || redirect) {
that.$modal.on('hidden' + ZUI_MODAL, function() {
if(typeof callback === 'function') callback();
if(typeof redirect === STR_STRING && redirect.length && !that.$modal.data('cancel-reload')) {
if(redirect === 'this') window.location.reload();
else window.location = redirect;
}
});
}
that.$modal.modal('hide');
};
ModalTrigger.prototype.toggle = function(options) {
if(this.isShown) this.close();
else this.show(options);
};
ModalTrigger.prototype.adjustPosition = function(position) {
position = position === undefined ? this.options.position : position;
if (typeof position === 'function') {
position = position(this);
}
this.$modal.modal('adjustPosition', position);
};
$.zui({
ModalTrigger: ModalTrigger,
modalTrigger: new ModalTrigger()
});
$.fn.modalTrigger = function(option, settings) {
return $(this).each(function() {
var $this = $(this);
var data = $this.data(NAME),
options = $.extend({
title: $this.attr('title') || $this.text(),
url: $this.attr('href'),
type: $this.hasClass('iframe') ? 'iframe' : ''
}, $this.data(), $.isPlainObject(option) && option);
if(!data) $this.data(NAME, (data = new ModalTrigger(options, $this)));
else {
if(typeof option == STR_STRING) data[option](settings);
else if(options.show) data.show(settings);
return;
}
$this.on((options.trigger || 'click') + '.toggle.' + NAME, function(e) {
options = $.extend(options, {
url: $this.attr('href') || $this.attr('data-url') || $this.data('url') || options.url
});
data.toggle(options);
if($this.is('a')) e.preventDefault();
});
});
};
var old = $.fn.modal;
$.fn.modal = function(option, settings) {
return $(this).each(function() {
var $this = $(this);
if($this.hasClass('modal')) old.call($this, option, settings);
else $this.modalTrigger(option, settings);
});
};
$.fn.modal.bs = old;
var getModal = function(modal) {
if (!modal) {
modal = $('.modal.modal-trigger');
if (!modal.length) {
}
} else {
modal = $(modal);
}
if(modal && (modal instanceof $)) return modal;
return null;
};
// callback, redirect, modal
var closeModal = function(modal, callback, redirect) {
var originModal = modal;
if(typeof modal === 'function') {
var oldModal = redirect;
redirect = callback;
callback = modal;
modal = oldModal;
}
modal = getModal(modal);
if(modal && modal.length) {
modal.each(function() {
$(this).data(NAME).close(callback, redirect);
});
} else if(!$('body').hasClass('modal-open') && !$('.modal.in').length) {
// check if current page is as modal iframe
if ($('body').hasClass('body-modal')) {
window.parent.$.zui.closeModal(originModal, callback, redirect);
}
}
};
var adjustModalPosition = function(position, modal) {
modal = getModal(modal);
if(modal && modal.length) {
modal.modal('adjustPosition', position);
}
};
var reloadModal = function(options, modal) {
if (typeof options === 'string') {
options = {url: options};
}
var $modal = getModal(modal);
if($modal && $modal.length) {
$modal.each(function() {
$(this).data(NAME).show(options);
});
}
};
$.zui({
reloadModal: reloadModal,
closeModal: closeModal,
ajustModalPosition: adjustModalPosition,
adjustModalPosition: adjustModalPosition,
});
$(document).on('click.' + NAME + '.data-api', '[data-toggle="modal"]', function(e) {
var $this = $(this);
var href = $this.attr('href');
var $target = null;
try {
$target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, '')));
} catch(ex) {}
if(!$target || !$target.length) {
if(!$this.data(NAME)) {
$this.modalTrigger({
show: true,
});
} else {
$this.trigger('.toggle.' + NAME);
}
}
if($this.is('a')) {
e.preventDefault();
}
}).on('click.' + NAME + '.data-api', '[data-dismiss="modal"]', function() {
$.zui.closeModal();
});
}(window.jQuery, window, undefined));
/* ========================================================================
* Bootstrap: tooltip.js v3.0.0
* http://twzui.github.com/bootstrap/javascript.html#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
*
* 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';
// TOOLTIP PUBLIC CLASS DEFINITION
// ===============================
var Tooltip = function(element, options) {
this.type = null
this.options = null
this.enabled = null
this.timeout = null
this.hoverState = null
this.$element = null
this.init('tooltip', element, options)
}
Tooltip.DEFAULTS = {
animation: true,
placement: 'top',
selector: false,
template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
trigger: 'hover focus',
title: '',
delay: 0,
html: false,
container: false
}
Tooltip.prototype.init = function(type, element, options) {
this.enabled = true
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
var triggers = this.options.trigger.split(' ')
for(var i = triggers.length; i--;) {
var trigger = triggers[i]
if(trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, this.toggle.bind(this))
} else if(trigger != 'manual') {
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
this.$element.on(eventIn + '.' + this.type, this.options.selector, this.enter.bind(this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, this.leave.bind(this))
}
}
this.options.selector ?
(this._options = $.extend({}, this.options, {
trigger: 'manual',
selector: ''
})) :
this.fixTitle()
}
Tooltip.prototype.getDefaults = function() {
return Tooltip.DEFAULTS
}
Tooltip.prototype.getOptions = function(options) {
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
if(options.delay && typeof options.delay == 'number') {
options.delay = {
show: options.delay,
hide: options.delay
}
}
return options
}
Tooltip.prototype.getDelegateOptions = function() {
var options = {}
var defaults = this.getDefaults()
this._options && $.each(this._options, function(key, value) {
if(defaults[key] != value) options[key] = value
})
return options
}
Tooltip.prototype.enter = function(obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('zui.' + this.type)
clearTimeout(self.timeout)
self.hoverState = 'in'
if(!self.options.delay || !self.options.delay.show) return self.show()
self.timeout = setTimeout(function() {
if(self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
Tooltip.prototype.leave = function(obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('zui.' + this.type)
clearTimeout(self.timeout)
self.hoverState = 'out'
if(!self.options.delay || !self.options.delay.hide) return self.hide()
self.timeout = setTimeout(function() {
if(self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
Tooltip.prototype.show = function(content) {
var e = $.Event('show.zui.' + this.type)
if((content || this.hasContent()) && this.enabled) {
var that = this
that.$element.trigger(e)
if(e.isDefaultPrevented()) return
var $tip = that.tip()
that.setContent(content)
if(that.options.animation) $tip.addClass('fade')
var placement = typeof that.options.placement == 'function' ?
that.options.placement.call(that, $tip[0], that.$element[0]) :
that.options.placement
var autoToken = /\s?auto?\s?/i
var autoPlace = autoToken.test(placement)
if(autoPlace) placement = placement.replace(autoToken, '') || 'top'
$tip
.detach()
.css({
top: 0,
left: 0,
display: 'block'
})
.addClass(placement)
that.options.container ? $tip.appendTo(that.options.container) : $tip.insertAfter(that.$element)
var pos = that.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if(autoPlace) {
var $parent = that.$element.parent()
var orgPlacement = placement
var docScroll = document.documentElement.scrollTop || document.body.scrollTop
var parentWidth = that.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
var parentHeight = that.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
var parentLeft = that.options.container == 'body' ? 0 : $parent.offset().left
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
placement
$tip
.removeClass(orgPlacement)
.addClass(placement)
}
var calculatedOffset = that.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
that.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.zui.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && that.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(150) :
complete()
}
}
Tooltip.prototype.applyPlacement = function(offset, placement) {
var replace
var $tip = this.tip()
var width = $tip[0].offsetWidth
var height = $tip[0].offsetHeight
// manually read margins because getBoundingClientRect includes difference
var marginTop = parseInt($tip.css('margin-top'), 10)
var marginLeft = parseInt($tip.css('margin-left'), 10)
// we must check for NaN for ie 8/9
if(isNaN(marginTop)) marginTop = 0
if(isNaN(marginLeft)) marginLeft = 0
offset.top = offset.top + marginTop
offset.left = offset.left + marginLeft
$tip
.offset(offset)
.addClass('in')
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if(placement == 'top' && actualHeight != height) {
replace = true
offset.top = offset.top + height - actualHeight
}
if(/bottom|top/.test(placement)) {
var delta = 0
if(offset.left < 0) {
delta = offset.left * -2
offset.left = 0
$tip.offset(offset)
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
}
this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
} else {
this.replaceArrow(actualHeight - height, actualHeight, 'top')
}
if(replace) $tip.offset(offset)
}
Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
}
Tooltip.prototype.setContent = function(content) {
var $tip = this.tip()
var title = content || this.getTitle()
if(this.options.tipId) $tip.attr('id', this.options.tipId)
if(this.options.tipClass) $tip.addClass(this.options.tipClass)
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in top bottom left right')
}
Tooltip.prototype.hide = function() {
var that = this
var $tip = this.tip()
var e = $.Event('hide.zui.' + this.type)
function complete() {
if(that.hoverState != 'in') $tip.detach()
}
this.$element.trigger(e)
if(e.isDefaultPrevented()) return
$tip.removeClass('in')
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one($.support.transition.end, complete)
.emulateTransitionEnd(150) :
complete()
this.$element.trigger('hidden.zui.' + this.type)
return this
}
Tooltip.prototype.fixTitle = function() {
var $e = this.$element
if($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
Tooltip.prototype.hasContent = function() {
return this.getTitle()
}
Tooltip.prototype.getPosition = function() {
var el = this.$element[0]
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
width: el.offsetWidth,
height: el.offsetHeight
}, this.$element.offset())
}
Tooltip.prototype.getCalculatedOffset = function(placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? {
top: pos.top + pos.height,
left: pos.left + pos.width / 2 - actualWidth / 2
} :
placement == 'top' ? {
top: pos.top - actualHeight,
left: pos.left + pos.width / 2 - actualWidth / 2
} :
placement == 'left' ? {
top: pos.top + pos.height / 2 - actualHeight / 2,
left: pos.left - actualWidth
} :
/* placement == 'right' */
{
top: pos.top + pos.height / 2 - actualHeight / 2,
left: pos.left + pos.width
}
}
Tooltip.prototype.getTitle = function() {
var title
var $e = this.$element
var o = this.options
title = $e.attr('data-original-title') || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
return title
}
Tooltip.prototype.tip = function() {
return this.$tip = this.$tip || $(this.options.template)
}
Tooltip.prototype.arrow = function() {
return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
}
Tooltip.prototype.validate = function() {
if(!this.$element[0].parentNode) {
this.hide()
this.$element = null
this.options = null
}
}
Tooltip.prototype.enable = function() {
this.enabled = true
}
Tooltip.prototype.disable = function() {
this.enabled = false
}
Tooltip.prototype.toggleEnabled = function() {
this.enabled = !this.enabled
}
Tooltip.prototype.toggle = function(e) {
var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('zui.' + this.type) : this
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
}
Tooltip.prototype.destroy = function() {
this.hide().$element.off('.' + this.type).removeData('zui.' + this.type)
}
// TOOLTIP PLUGIN DEFINITION
// =========================
var old = $.fn.tooltip
$.fn.tooltip = function(option, params) {
return this.each(function() {
var $this = $(this)
var data = $this.data('zui.tooltip')
var options = typeof option == 'object' && option
if(!data) $this.data('zui.tooltip', (data = new Tooltip(this, options)))
if(typeof option == 'string') data[option](params)
})
}
$.fn.tooltip.Constructor = Tooltip
// TOOLTIP NO CONFLICT
// ===================
$.fn.tooltip.noConflict = function() {
$.fn.tooltip = old
return this
}
}(window.jQuery);
/* ========================================================================
* Bootstrap: popover.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#popovers
*
* 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';
// POPOVER PUBLIC CLASS DEFINITION
// ===============================
var Popover = function(element, options) {
this.init('popover', element, options)
}
if(!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right',
trigger: 'click',
content: '',
template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
})
// NOTE: POPOVER EXTENDS tooltip.js
// ================================
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
Popover.prototype.constructor = Popover
Popover.prototype.getDefaults = function() {
return Popover.DEFAULTS
}
Popover.prototype.setContent = function() {
var $tip = this.tip()
var target = this.getTarget()
if(target) {
if(target.find('.arrow').length < 1)
$tip.addClass('no-arrow')
$tip.html(target.html())
return
}
var title = this.getTitle()
var content = this.getContent()
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
$tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
$tip.removeClass('fade top bottom left right in')
if(this.options.tipId) $tip.attr('id', this.options.tipId)
if(this.options.tipClass) $tip.addClass(this.options.tipClass)
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
// this manually by checking the contents.
if(!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
}
Popover.prototype.hasContent = function() {
return this.getTarget() || this.getTitle() || this.getContent()
}
Popover.prototype.getContent = function() {
var $e = this.$element
var o = this.options
return $e.attr('data-content') || (typeof o.content == 'function' ?
o.content.call($e[0]) :
o.content)
}
Popover.prototype.getTarget = function() {
var $e = this.$element
var o = this.options
var target = $e.attr('data-target') || (typeof o.target == 'function' ?
o.target.call($e[0]) :
o.target)
return(target && true) ? (target == '$next' ? $e.next('.popover') : $(target)) : false
}
Popover.prototype.arrow = function() {
return this.$arrow = this.$arrow || this.tip().find('.arrow')
}
Popover.prototype.tip = function() {
if(!this.$tip) this.$tip = $(this.options.template)
return this.$tip
}
// POPOVER PLUGIN DEFINITION
// =========================
var old = $.fn.popover
$.fn.popover = function(option) {
return this.each(function() {
var $this = $(this)
var data = $this.data('zui.popover')
var options = typeof option == 'object' && option
if(!data) $this.data('zui.popover', (data = new Popover(this, options)))
if(typeof option == 'string') data[option]()
})
}
$.fn.popover.Constructor = Popover
// POPOVER NO CONFLICT
// ===================
$.fn.popover.noConflict = function() {
$.fn.popover = old
return this
}
}(window.jQuery);
/* ========================================================================
* Bootstrap: dropdown.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#dropdowns
*
* 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';
// DROPDOWN CLASS DEFINITION
// =========================
var zuiname = 'zui.dropdown';
var backdrop = '.dropdown-backdrop'
var toggle = '[data-toggle=dropdown]'
var Dropdown = function(element) {
var $el = $(element).on('click.' + zuiname, this.toggle)
}
Dropdown.prototype.toggle = function(e) {
var $this = $(this)
if($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
clearMenus()
if(!isActive) {
if('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
}
$parent.trigger(e = $.Event('show.' + zuiname))
if(e.isDefaultPrevented()) return
$parent
.toggleClass('open')
.trigger('shown.' + zuiname)
$this.focus()
}
return false
}
Dropdown.prototype.keydown = function(e) {
if(!/(38|40|27)/.test(e.keyCode)) return
var $this = $(this)
e.preventDefault()
e.stopPropagation()
if($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if(!isActive || (isActive && e.keyCode == 27)) {
if(e.which == 27) $parent.find(toggle).focus()
return $this.click()
}
var $items = $('[role=menu] li:not(.divider):visible a', $parent)
if(!$items.length) return
var index = $items.index($items.filter(':focus'))
if(e.keyCode == 38 && index > 0) index-- // up
if(e.keyCode == 40 && index < $items.length - 1) index++ // down
if(!~index) index = 0
$items.eq(index).focus()
}
function clearMenus(e) {
$(backdrop).remove()
$(toggle).each(function(e) {
var $parent = getParent($(this))
if(!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.' + zuiname))
if(e.isDefaultPrevented()) return
$parent.removeClass('open').trigger('hidden.' + zuiname)
})
}
function getParent($this) {
var selector = $this.attr('data-target')
if(!selector) {
selector = $this.attr('href')
selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
var $parent;
try {
$parent = selector && $(selector);
} catch(e) {}
return $parent && $parent.length ? $parent : $this.parent()
}
// DROPDOWN PLUGIN DEFINITION
// ==========================
var old = $.fn.dropdown
$.fn.dropdown = function(option) {
return this.each(function() {
var $this = $(this)
var data = $this.data('dropdown')
if(!data) $this.data('dropdown', (data = new Dropdown(this)))
if(typeof option == 'string') data[option].call($this)
})
}
$.fn.dropdown.Constructor = Dropdown
// DROPDOWN NO CONFLICT
// ====================
$.fn.dropdown.noConflict = function() {
$.fn.dropdown = old
return this
}
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
var apiName = zuiname + '.data-api'
$(document)
.on('click.' + apiName, clearMenus)
.on('click.' + apiName, '.dropdown form,.not-clear-menu', function(e) {
e.stopPropagation()
})
.on('click.' + apiName, toggle, Dropdown.prototype.toggle)
.on('keydown.' + apiName, toggle + ', [role=menu]', Dropdown.prototype.keydown)
}(window.jQuery);
/* ========================================================================
* Bootstrap: carousel.js v3.0.0
* http://twzui.github.com/bootstrap/javascript.html#carousel
*
* 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.
* ========================================================================
* Updates in ZUI:
* 1. support touch event for touchable devices
* ======================================================================== */
+ function($) {
'use strict';
// CAROUSEL CLASS DEFINITION
// =========================
var Carousel = function(element, options) {
this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
this.paused =
this.sliding =
this.interval =
this.$active =
this.$items = null
this.options.pause == 'hover' && this.$element
.on('mouseenter', this.pause.bind(this))
.on('mouseleave', this.cycle.bind(this))
}
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
wrap: true,
touchable: true
}
Carousel.prototype.touchable = function() {
if(!this.options.touchable) return;
this.$element.on('touchstart touchmove touchend', touch);
var touchStartX, touchStartY;
var that = this;
/* listen the touch event */
function touch(event) {
var event = event || window.event;
if(event.originalEvent) event = event.originalEvent;
var carousel = $(this);
switch(event.type) {
case "touchstart":
touchStartX = event.touches[0].pageX;
touchStartY = event.touches[0].pageY;
break;
case "touchend":
var distanceX = event.changedTouches[0].pageX - touchStartX;
var distanceY = event.changedTouches[0].pageY - touchStartY;
if(Math.abs(distanceX) > Math.abs(distanceY)) {
handleCarousel(carousel, distanceX);
if(Math.abs(distanceX) > 10) {
event.preventDefault();
}
} else {
var $w = $(window);
$('body,html').animate({
scrollTop: $w.scrollTop() - distanceY
}, 400)
}
break;
}
}
function handleCarousel(carousel, distance) {
if(distance > 10) that.prev();
else if(distance < -10) that.next();
}
}
Carousel.prototype.cycle = function(e) {
e || (this.paused = false)
this.interval && clearInterval(this.interval)
this.options.interval && !this.paused && (this.interval = setInterval(this.next.bind(this), this.options.interval))
return this
}
Carousel.prototype.getActiveIndex = function() {
this.$active = this.$element.find('.item.active')
this.$items = this.$active.parent().children()
return this.$items.index(this.$active)
}
Carousel.prototype.to = function(pos) {
var that = this
var activeIndex = this.getActiveIndex()
if(pos > (this.$items.length - 1) || pos < 0) return
if(this.sliding) return this.$element.one('slid', function() {
that.to(pos)
})
if(activeIndex == pos) return this.pause().cycle()
return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
}
Carousel.prototype.pause = function(e) {
e || (this.paused = true)
if(this.$element.find('.next, .prev').length && $.support.transition.end) {
this.$element.trigger($.support.transition.end)
this.cycle(true)
}
this.interval = clearInterval(this.interval)
return this
}
Carousel.prototype.next = function() {
if(this.sliding) return
return this.slide('next')
}
Carousel.prototype.prev = function() {
if(this.sliding) return
return this.slide('prev')
}
Carousel.prototype.slide = function(type, next) {
var $active = this.$element.find('.item.active')
var $next = next || $active[type]()
var isCycling = this.interval
var direction = type == 'next' ? 'left' : 'right'
var fallback = type == 'next' ? 'first' : 'last'
var that = this
if(!$next.length) {
if(!this.options.wrap) return
$next = this.$element.find('.item')[fallback]()
}
this.sliding = true
isCycling && this.pause()
var e = $.Event('slide.zui.carousel', {
relatedTarget: $next[0],
direction: direction
})
if($next.hasClass('active')) return
if(this.$indicators.length) {
this.$indicators.find('.active').removeClass('active')
this.$element.one('slid', function() {
var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
$nextIndicator && $nextIndicator.addClass('active')
})
}
if($.support.transition && this.$element.hasClass('slide')) {
this.$element.trigger(e)
if(e.isDefaultPrevented()) return
$next.addClass(type)
$next[0].offsetWidth // force reflow
$active.addClass(direction)
$next.addClass(direction)
$active
.one($.support.transition.end, function() {
$next.removeClass([type, direction].join(' ')).addClass('active')
$active.removeClass(['active', direction].join(' '))
that.sliding = false
setTimeout(function() {
that.$element.trigger('slid')
}, 0)
})
.emulateTransitionEnd(600)
} else {
this.$element.trigger(e)
if(e.isDefaultPrevented()) return
$active.removeClass('active')
$next.addClass('active')
this.sliding = false
this.$element.trigger('slid')
}
isCycling && this.cycle()
return this
}
// CAROUSEL PLUGIN DEFINITION
// ==========================
var old = $.fn.carousel
$.fn.carousel = function(option) {
return this.each(function() {
var $this = $(this)
var data = $this.data('zui.carousel')
var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
var action = typeof option == 'string' ? option : options.slide
if(!data) $this.data('zui.carousel', (data = new Carousel(this, options)))
if(typeof option == 'number') data.to(option)
else if(action) data[action]()
else if(options.interval) data.pause().cycle()
if(options.touchable) data.touchable()
})
}
$.fn.carousel.Constructor = Carousel
// CAROUSEL NO CONFLICT
// ====================
$.fn.carousel.noConflict = function() {
$.fn.carousel = old
return this
}
// CAROUSEL DATA-API
// =================
$(document).on('click.zui.carousel.data-api', '[data-slide], [data-slide-to]', function(e) {
var $this = $(this),
href
var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
var options = $.extend({}, $target.data(), $this.data())
var slideIndex = $this.attr('data-slide-to')
if(slideIndex) options.interval = false
$target.carousel(options)
if(slideIndex = $this.attr('data-slide-to')) {
$target.data('zui.carousel').to(slideIndex)
}
e.preventDefault()
})
$(window).on('load', function() {
$('[data-ride="carousel"]').each(function() {
var $carousel = $(this)
$carousel.carousel($carousel.data())
})
})
}(window.jQuery);