lu2
Version:
Simple and flexible UI component library based on native HTML and JavaScript
2,161 lines (1,874 loc) • 228 kB
JavaScript
/**
* @Radio.js
* @author xunxuzhang
* @version
* Created: 15-06-17
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
factory().init();
}
}(this, function () {
//require('plugin/jquery');
/**
* 模拟单选效果
* 只针对IE8-浏览器进行处理
* 状态关键字为checked
*/
var CHECKED = 'checked';
/**
* jQuery模式下的扩展方法,
* 只针对IE8-浏览器进行处理
* 根据当前单复选框的选中态toggle类名checked
* @example
* $('[type=radio]').propMatch();
*/
$.fn.propMatch = function() {
if (!window.addEventListener) {
var _match = function(element) {
element = $(element);
if (element.prop(CHECKED)) {
element.attr(CHECKED, CHECKED);
} else {
element.removeAttr(CHECKED);
}
// 触发重绘,使相邻选择器渲染
element.parent().addClass('z').toggleClass('i_i');
};
if ($(this).length == 1 && $(this).attr('type') == 'radio') {
// 单选框含有组的概念
// 也就是a选中的时候,b则变成非选中态
// 因此,类名切换不能只关注当前元素
var name = $(this).attr('name');
$('input[type=radio][name='+ name +']').each(function() {
_match(this);
});
} else {
$(this).each(function() {
_match(this);
});
}
return $(this);
}
};
return {
// 使用面对对象模式暴露给其他方法使用,例如Checkbox.js
// 当然,你也可以直接使用$().propMatch()方法
match: function(control) {
control.propMatch();
},
init: function() {
if (!window.addEventListener && !window.initedRadio) {
// 压缩的时候少36字节
var selector = 'input[type=radio]';
// 全局委托
$(document.body).delegate(selector, 'click', function() {
$(this).propMatch();
});
// 首次页面载入,对页面所有单选框(根据是否选中态)进行初始化
$(selector).propMatch();
// 防止多次初始化
window.initedRadio = true;
}
}
};
}));
/**
* @Checkbox.js
* @author xunxuzhang
* @version
* Created: 15-06-18
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
factory().init();
}
}(this, function () {
if (!$().propMatch && window.console) {
console.error('need Radio.js');
}
return {
init: function() {
if (!window.addEventListener && !window.initedCheckbox && $().propMatch) {
var selector = 'input[type=checkbox]';
$(document.body).delegate(selector, 'click', function() {
$(this).propMatch();
});
// 首次页面载入,对页面所有复选框(根据是否选中态)进行初始化
$(selector).propMatch();
// 防止多次初始化
window.initedCheckbox = true;
}
}
};
}));
/**
* @Placeholder.js
* @author xunxuzhang
* @version
* Created: 15-06-17
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.Placeholder = factory();
}
}(this, function () {
var PLACEHOLDER = 'placeholder';
/**
* 针对IE7-IE9浏览器的placeholder占位符效果
* 支持jQuery用法,以及模块化使用
* @使用示例
* $('input').placeholder();
* or
* new Placeholder($('input'));
*/
$.fn[PLACEHOLDER] = function() {
return $(this).each(function(index, element) {
var placeholder = $(this).data(PLACEHOLDER);
if (placeholder) {
placeholder.visibility();
} else {
new Placeholder($(this));
}
});
};
var Placeholder = function(el) {
// IE10+不处理
if (typeof history.pushState == 'function') return this;
// 默认所有的占位符元素
if (!el) {
el = $('['+ PLACEHOLDER +']').placeholder();
return this;
}
var self = this;
// 暴露的元素
this.el = {};
this.el.target = el;
// 创建
// 1. 得到对应的id, 没有则赋值
var attribute = el.attr(PLACEHOLDER), id = el.attr('id');
// 需要有placeholder属性值,以及不能重复实例化
if (!attribute || el.data(PLACEHOLDER)) return this;
if (!id) {
// 如果没有id, 设置随机id,使placeholder所在的label元素与之关联
id = PLACEHOLDER + (Math.random() + '').replace('.', '');
el.attr('id', id);
}
// 2. 对应的label元素
var elePlaceholder = $('<label class="ui-'+ PLACEHOLDER +'" for='+ id +'>'+ attribute +'</label>').hide();
// 插入
var isHide = el.is(':visible') == false;
// 当input是内联时候,后置; 块状时候,下置
if (isHide == false) {
if (el.css('display') != 'block') {
elePlaceholder.insertAfter(el);
} else {
$('<div aria-hidden="true"></div>').append(elePlaceholder).insertAfter(el);
}
// 事件
// IE9 使用input事件
// IE7/IE8使用propertychange事件
if (window.addEventListener) {
el.on('input', function() {
self.visibility();
});
} else {
el.get(0).attachEvent('onpropertychange', function(event) {
if (event && event.propertyName == "value") {
self.visibility();
}
});
}
// 元素上存储对应的实例对象
el.data(PLACEHOLDER, self);
// 实例存储
this.el.placeholder = elePlaceholder;
// 显示或隐藏
this.visibility();
} else {
$(document.body).click(function() {
// 全局委托
if (el.is(':visible') && !el.data(PLACEHOLDER)) {
self = new Placeholder(el);
}
// 实时同步文本框的显隐状态
if (el.data(PLACEHOLDER)) {
self.visibility();
}
});
// 遇到DOM载入后fadeIn效果,导致初始化时候,元素还是隐藏的,加个定时器看看
setTimeout(function() {
self.visibility();
}, 200);
}
};
Placeholder.prototype.position = function() {
var target = this.el.target, label = this.el.placeholder;
// 创建label元素
var mt = parseInt(target.css('marginTop')) || 0,
mr = parseInt(target.css('marginRight')) || 0,
mb = parseInt(target.css('marginBottom')) || 0,
ml = parseInt(target.css('marginLeft')) || 0,
width = target.width(),
outerWidth = target.outerWidth(),
outerHeight = target.outerHeight();
// 块状
if (label.parent().attr('aria-hidden')) {
// 块状
label.css({
width: width,
marginLeft: ml,
marginTop: (outerHeight + mb) * -1
});
} else {
// 内联
label.css({
width: width,
marginTop: mt,
marginLeft: (outerWidth + mr) * -1
});
}
// if (target.attr('id') == 'spanSearch') location.href += '#' + label.get(0).outerHTML;
return this;
};
Placeholder.prototype.visibility = function() {
var target = this.el.target;
if (target.is(':visible') == false || $.trim(target.val())) {
this.hide();
} else {
this.show();
}
return this;
};
Placeholder.prototype.show = function() {
if (this.el.placeholder) {
this.el.placeholder.html(this.el.target.attr(PLACEHOLDER)).show();
// 显示同时重定位,各种复杂场景都能适应
this.position();
}
return this;
};
Placeholder.prototype.hide = function() {
if (this.el.placeholder) this.el.placeholder.hide();
return this;
};
return Placeholder;
}));/**
* @Follow.js
* @author xunxuzhang
* @version
* Created: 15-06-25
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.Follow = factory();
}
}(this, function () {
/**
* 绝对定位元素的定位效果
* 针对所有浏览器
* 自动含边界判断
* 可用在DropDown, Tips等组件上
* 支持链式调用和模块化调用
* @example
* $().follow(trigger, options);
* new Follow(trigger, target, options);
* 文档见:http://www.zhangxinxu.com/wordpress/?p=1328 position()方法
**/
$.fn.follow = function(trigger, options) {
var defaults = {
offsets: {
x: 0,
y: 0
},
position: "4-1", //trigger-target
edgeAdjust: true //边缘位置自动调整
};
var params = $.extend({}, defaults, options || {});
return $(this).each(function() {
var target = $(this);
if (trigger.length == 0) {
return;
}
var pos, tri_h = 0, tri_w = 0, tri_l, tri_t, tar_l, tar_t, cor_l, cor_t,
tar_h = target.data("height"), tar_w = target.data("width"),
st = $(window).scrollTop(), sl = $(window).scrollLeft(),
off_x = parseInt(params.offsets.x, 10) || 0, off_y = parseInt(params.offsets.y, 10) || 0,
mousePos = this.cacheData;
//缓存目标对象高度,宽度,提高鼠标跟随时显示性能,元素隐藏时缓存清除
if (!tar_h) {
tar_h = target.outerHeight();
}
if (!tar_w) {
tar_w = target.outerWidth();
}
pos = trigger.offset();
tri_h = trigger.outerHeight();
tri_w = trigger.outerWidth();
tri_l = pos.left;
tri_t = pos.top;
var funMouseL = function() {
if (tri_l < 0) {
tri_l = 0;
} else if (tri_l + tri_h > $(window).width()) {
tri_l = $(window).width() - tri_w;
}
}, funMouseT = function() {
if (tri_t < 0) {
tri_t = 0;
} else if (tri_t + tri_h > $(document).height()) {
tri_t = $(document).height() - tri_h;
}
};
var arrLegalPos = ["4-1", "1-4", "5-7", "2-3", "2-1", "6-8", "3-4", "4-3", "8-6", "1-2", "7-5", "3-2"],
align = params.position,
alignMatch = false,
strDirect;
$.each(arrLegalPos, function(i, n) {
if (n === align) {
alignMatch = true;
return;
}
});
// 如果没有匹配的对齐方式,使用默认的对齐方式
if (!alignMatch) {
align = defaults.position;
}
var funDirect = function(a) {
var dir = "bottom";
//确定方向
switch (a) {
case "1-4": case "5-7": case "2-3": {
dir = "top";
break;
}
case "2-1": case "6-8": case "3-4": {
dir = "right";
break;
}
case "1-2": case "8-6": case "4-3": {
dir = "left";
break;
}
case "4-1": case "7-5": case "3-2": {
dir = "bottom";
break;
}
}
return dir;
};
//居中判断
var funCenterJudge = function(a) {
if (a === "5-7" || a === "6-8" || a === "8-6" || a === "7-5") {
return true;
}
return false;
};
var funJudge = function(dir) {
var totalHeight = 0, totalWidth = 0;
if (dir === "right") {
totalWidth = tri_l + tri_w + tar_w + off_x;
if (totalWidth > $(window).width()) {
return false;
}
} else if (dir === "bottom") {
totalHeight = tri_t + tri_h + tar_h + off_y;
if (totalHeight > st + $(window).height()) {
return false;
}
} else if (dir === "top") {
totalHeight = tar_h + off_y;
if (totalHeight > tri_t - st) {
return false;
}
} else if (dir === "left") {
totalWidth = tar_w + off_x;
if (totalWidth > tri_l) {
return false;
}
}
return true;
};
//此时的方向
strDirect = funDirect(align);
//边缘过界判断
if (params.edgeAdjust) {
//根据位置是否溢出显示界面重新判定定位
if (funJudge(strDirect)) {
//该方向不溢出
(function() {
if (funCenterJudge(align)) { return; }
var obj = {
top: {
right: "2-3",
left: "1-4"
},
right: {
top: "2-1",
bottom: "3-4"
},
bottom: {
right: "3-2",
left: "4-1"
},
left: {
top: "1-2",
bottom: "4-3"
}
};
var o = obj[strDirect], name;
if (o) {
for (name in o) {
if (!funJudge(name)) {
align = o[name];
}
}
}
})();
} else {
//该方向溢出
(function() {
if (funCenterJudge(align)) {
var center = {
"5-7": "7-5",
"7-5": "5-7",
"6-8": "8-6",
"8-6": "6-8"
};
align = center[align];
} else {
var obj = {
top: {
left: "3-2",
right: "4-1"
},
right: {
bottom: "1-2",
top: "4-3"
},
bottom: {
left: "2-3",
right: "1-4"
},
left: {
bottom: "2-1",
top: "3-4"
}
};
var o = obj[strDirect], arr = [];
for (name in o) {
arr.push(name);
}
if (funJudge(arr[0]) || !funJudge(arr[1])) {
align = o[arr[0]];
} else {
align = o[arr[1]];
}
}
})();
}
}
// 是否变换了方向
var strNewDirect = funDirect(align), strFirst = align.split("-")[0];
//确定left, top值
switch (strNewDirect) {
case "top": {
tar_t = tri_t - tar_h;
if (strFirst == "1") {
tar_l = tri_l;
} else if (strFirst === "5") {
tar_l = tri_l - (tar_w - tri_w) / 2;
} else {
tar_l = tri_l - (tar_w - tri_w);
}
break;
}
case "right": {
tar_l = tri_l + tri_w ;
if (strFirst == "2") {
tar_t = tri_t;
} else if (strFirst === "6") {
tar_t = tri_t - (tar_h - tri_h) / 2;
} else {
tar_t = tri_t - (tar_h - tri_h);
}
break;
}
case "bottom": {
tar_t = tri_t + tri_h;
if (strFirst == "4") {
tar_l = tri_l;
} else if (strFirst === "7") {
tar_l = tri_l - (tar_w - tri_w) / 2;
} else {
tar_l = tri_l - (tar_w - tri_w);
}
break;
}
case "left": {
tar_l = tri_l - tar_w;
if (strFirst == "2") {
tar_t = tri_t;
} else if (strFirst === "6") {
tar_t = tri_t - (tar_w - tri_w) / 2;
} else {
tar_t = tri_t - (tar_h - tri_h);
}
break;
}
}
if (params.edgeAdjust && funCenterJudge(align)) {
var winWidth = $(window).width(), winHeight = $(window).height();
// 是居中定位
// 变更的不是方向,而是offset大小
// 偏移处理
if (align == '7-5' || align == '5-7') {
// 左右是否超出
if (tar_l - sl < 0.5 * winWidth) {
// 左半边,判断左边缘
if (tar_l - sl < 0) {
tar_l = sl;
}
} else if (tar_l - sl + tar_w > winWidth) {
tar_l = winWidth + sl - tar_w;
}
} else {
// 上下是否超出
if (tar_t - st < 0.5 * winHeight) {
// 左半边,判断左边缘
if (tar_t - st < 0) {
tar_t = st;
}
} else if (tar_t - st + tar_h > winHeight) {
tar_t = winHeight + st - tar_h;
}
}
}
if (strNewDirect == "top" || strNewDirect == "left") {
tar_l = tar_l - off_x;
tar_t = tar_t - off_y;
} else {
tar_l = tar_l + off_x;
tar_t = tar_t + off_y;
}
//浮动框显示
target.css({
position: "absolute",
left: Math.round(tar_l),
top: Math.round(tar_t)
}).attr('data-align', align);
// 层级
// z-index自动最高
var zIndex = target.css('zIndex') * 1 || 19, maxIndex = zIndex;
$('body').children().each(function() {
var z, ele = this, el = $(ele);
if (ele !== target[0] && el.css('display') !== 'none' && (z = el.css('zIndex') * 1)) {
maxIndex = Math.max(z, maxIndex);
}
});
if (zIndex < maxIndex) {
target.css('zIndex', maxIndex + 1);
}
});
};
var Follow = function(trigger, target, options) {
target.follow(trigger, options);
};
Follow.prototype.hide = function() {
target.remove();
};
return Follow;
}));/**
* @Tab.js
* @author xunxuzhang
* @version
* Created: 15-06-12
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.Tab = factory();
}
}(this, function () {
/**
* 定制级极简的选项卡
* 选项卡效果本质上就是单选框切换效果
* 因此,状态类名使用.checked
* @使用示例
* new Tab($('#container > a'), {
* callback: function() {}
* });
* 或者包装器用法
* $('#container > a').tab({
* callback: function() {}
* });
*/
var STATE = 'checked';
$.fn.eqAttr = function(key) {
key = key || "data-rel";
// 获得属性对应的值
var value = $(this).attr(key);
if (!value) return $();
// 当作id来处理
var target = $("#" + value);
if (target.length) return target;
// 否则当作className处理
return $("." + value);
};
// 根据属性获得对应的元素
$.fn.tab = function(options) {
if (!$(this).data('tab')) {
$(this).data('tab', new Tab($(this), options));
}
};
$.queryString = function(key, value, str) {
// 有则替换,无则加勉
var href = (str || location.href).split('#')[0], root = '', hash = location.hash;
// 查询数组
var arr_query = href.split('?'), arr_map = [];
if (arr_query.length > 1) {
if (arr_query[1] != '') {
arr_map = $.grep(arr_query[1].split('&'), function(query) {
return query.split('=')[0] != key;
});
}
root = arr_query[0] + '?' + arr_map.join('&') + '&';
root = root.replace('?&', '?');
} else {
root = href + '?';
}
return root + key + '=' + value + hash;
};
var Tab = function(el, options) {
// 选项卡元素,点击主体
el = $(el);
// 如果元素没有,打道回府
if (el.length == 0) return;
// 下面3语句参数获取
options = options || {};
var defaults = {
eventType: 'click',
index: 'auto', // 'auto' 表示根据选项卡上的状态类名,如.checked获取index值
history: true, // 是否使用HTML5 history在URL上标记当前选项卡位置,for IE10+
callback: $.noop
};
var params = $.extend({}, defaults, options);
// 很重要的索引
var indexTab = params.index;
// 首先,获得索引值
el.each(function(index) {
if (typeof indexTab != 'number' && $(this).hasClass(STATE)) {
indexTab = index;
}
$(this).data('index', index);
});
if (typeof indexTab != 'number') {
indexTab = 0;
}
// 获得选项卡对应的面板元素
// 两种情况
// 1. 直接切换
// 2. ajax并载入
// 目前先第一种
// 则直接就是页面元素
// 事件gogogo
el.on(params.eventType, function(event) {
if ($(this).hasClass(STATE)) {
if (event.isTrigger) {
// 让可能不匹配的content面板的checked状态同步
// 一般出现在选项卡查询关键字变化后
// 因为项目原因,内部面板默认display跟nav不匹配
// 后注释是因为发现体验比较差
/*el.each(function() {
$(this).eqAttr().removeClass(STATE);
});
$(this).eqAttr().addClass(STATE);*/
params.callback.call(this, this, $(), $(), $());
}
return;
}
// 选项卡样式变变变
// 类名变化
var targetTab = $(this).addClass(STATE),
// 要移除类名的选项卡
resetTab = el.eq(indexTab).removeClass(STATE);
// 面板的变化
var targetPanel = targetTab.eqAttr().addClass(STATE),
resetPanel = resetTab.eqAttr().removeClass(STATE);
// 索引参数变化
indexTab = targetTab.data('index');
// 回调方法
params.callback.call(this, targetTab, resetTab, targetPanel, resetPanel);
if (/^(:?javas|#)/.test(this.getAttribute('href'))) {
var rel = targetTab.attr('data-rel');
if (params.history && history.replaceState) {
history.replaceState(null, document.title, $.queryString('targetTab', rel));
} else if (params.history) {
location.hash = '#targetTab=' + rel;
}
event.preventDefault();
}
});
// 默认就来一发
$(function() {
el.eq(indexTab).trigger(params.eventType);
});
// 暴露的属性或方法,供外部调用
this.el = {
tab: el
};
this.params = params;
};
return Tab;
}));
/**
* @Select.js
* @author xunxuzhang
* @version
* Created: 15-06-18
*
**/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
factory().init();
}
}(this, function () {
/**
* 模拟下拉框效果
* 只针对all浏览器进行处理
* 基于原生的<select>元素生成
*
*/
/*
* 支持jQuery API调用
* @example
* $('select').selectMatch();
* 如果不依赖seajs,则载入改JS就会页面所有下拉UI初始化
*/
$.fn.selectMatch = function(options) {
// 常量变量
var SELECT = 'select', SELECTED = 'selected', DISABLED = 'disabled', ACTIVE = 'active', REVERSE = 'reverse';
// 默认参数
var defaults = {
prefix: 'ui-', // 一些UI样式类名的前缀
trigger: ['change'] // 触发原始下拉框的事件,默认只触发change事件
};
// 参数合并
var params = $.extend({}, defaults, options || {});
// 通用前缀
var PREFIX = params.prefix + SELECT, joiner = params.prefix.replace(/[a-z]/gi, '');
// 根据下拉框获得相关数据的私有方法
var _get = function(el) {
var selectedIndex = 0, htmlOptions = '';
// 遍历下拉框的options选项
el.find('option').each(function(index) {
var arrCl = [PREFIX + joiner + 'datalist'+ joiner +'li', this.className];
if (this[SELECTED]) {
selectedIndex = index;
arrCl.push(SELECTED);
}
if (this[DISABLED]) {
arrCl.push(DISABLED);
}
htmlOptions = htmlOptions + '<a href="javascript:" class="'+ arrCl.join(' ') +'" data-index='+ index +'>'+ this.innerHTML +'</a>';
});
return {
index: selectedIndex,
html: htmlOptions
}
}
return $(this).each(function(index, element) {
var sel = $(this).hide().data(SELECT);
if (!sel) {
// 如果没有关联的模拟下拉元素生成
// 创建新的模拟下拉元素
sel = $('<div></div>').on('click', 'a._', function() {
if ($(element).prop(DISABLED)) return false;
// 显示与隐藏
sel.toggleClass(ACTIVE);
// 边界判断
if (sel.hasClass(ACTIVE)) {
var ul = sel.children('div[id]'),
overflow = ul.offset().top + ul.outerHeight() > Math.max($(document.body).height(), $(window).height());
sel[overflow? 'addClass': 'removeClass'](REVERSE);
// 滚动与定位
var arrData = sel.data('scrollTop'), selected = ul.find('.' + SELECTED);
// 严格验证
if (arrData && arrData[1] == selected.attr('data-index') && arrData[2] == selected.text()) {
ul.scrollTop(arrData[0]);
// 重置
sel.removeData('scrollTop');
}
} else {
sel.removeClass(REVERSE);
}
}).on('click', 'a[data-index]', function(event, istrigger) {
var indexOption = $(this).attr('data-index'),
scrollTop = $(this).parent().scrollTop();
// 下拉收起
sel.removeClass(ACTIVE);
// 存储可能的滚动定位需要的数据
sel.data('scrollTop', [scrollTop, indexOption, $(this).text()]);
// 修改下拉选中项
$(element).find('option').eq(indexOption).get(0)[SELECTED] = true;
// 更新下拉框
$(element).selectMatch(params);
// 回调处理
$.each(params.trigger, function(i, eventType) {
$(element).trigger(eventType, [istrigger]);
});
});
// 存储对象
$(this).data(SELECT, sel);
// 载入元素
$(this).after(sel);
// 点击页面空白要隐藏
$(document).mouseup(function(event) {
var target = event.target;
if (target && sel.hasClass(ACTIVE) && sel.get(0) !== target && sel.get(0).contains(target) == false) {
sel.removeClass(ACTIVE).removeClass(REVERSE);
}
});
}
// 根据当前下拉元素,重新刷新
// 0. 获得我们需要的一些数据
var data = _get($(this)), option = $(this).find('option').eq(data.index);
// 1. 与select元素匹配的类名, 以及宽度
sel.attr('class', element.className + ' ' + PREFIX).width($(this).outerWidth());
// 2. 全新的按钮元素
var id = ('id_' + Math.random()).replace('0.', '');
var button = '<a href="javascript:" class="'+ PREFIX + joiner + 'button _" data-target="'+ id +'">'+
'<span class="'+ PREFIX + joiner + 'text">' + option.html() + '</span>'+
'<i class="'+ PREFIX + joiner + 'icon"></i></a>';
// 3. 全新的列表
var datalist = '<div id="'+ id +'" class="'+ PREFIX + joiner + 'datalist">'+ data.html +'</div>';
// 4. 刷新
sel.html(button + datalist);
});
};
return {
init: function(el, options) {
el = el || $('select');
el.selectMatch(options);
}
};
}));
/**
* @Drop.js
* @author xunxuzhang
* @version
* Created: 15-06-30
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.Drop = factory();
}
}(this, function (require, exports, module) {
// require
if (typeof require == 'function') {
require('common/ui/Follow');
} else if (!$().follow) {
if (window.console) {
console.error('need Follow.js');
}
return {};
}
/*
* 元素的下拉显示
*/
/*
* 支持jQuery API调用和模块化调用两种
* @example
* $('trigger').drop(target, options);
* or
* new Drop(trigger, target, options)
*/
$.fn.drop = function(target, options) {
return $(this).each(function() {
var drop = $(this).data('drop');
if (!drop) {
$(this).data('drop', new Drop($(this), target, options));
}
});
};
// 实例方法
var Drop = function(trigger, target, options) {
var defaults = {
eventType: 'null', // 触发元素显示的事件,‘null’直接显示;‘hover’是hover方法;‘click’是点击显示,
selector: '', // 新增,实现点击或hover事件的委托实现
offsets: {
x: 0,
y: 0
},
edgeAdjust: true,
position: '7-5',
onShow: $.noop,
onHide: $.noop
};
var params = $.extend({}, defaults, options || {});
// 元素暴露给实例
this.el = {};
this.el.trigger = trigger;
this.el.target = target;
// 偏移
this.offsets = params.offsets;
// 回调
this.callback = {
show: params.onShow,
hide: params.onHide
};
// 位置
this.position = params.position;
// 边缘调整
this.edgeAdjust = params.edgeAdjust;
// 实例的显示状态
this.display = false;
var drop = this;
switch (params.eventType) {
case 'null': {
this.show();
break;
}
case 'hover': {
// hover处理需要增加延时
var timerHover;
// 同时,从trigger移动到target也需要延时,因为两者可能有间隙,不能单纯移出就隐藏
var timerHold;
trigger.delegate(params.selector, 'mouseenter', function() {
drop.el.trigger = $(this);
// 显示的定时器
timerHover = setTimeout(function() {
drop.show();
}, 150);
// 去除隐藏的定时器
clearTimeout(timerHold);
});
trigger.delegate(params.selector, 'mouseleave', function() {
// 清除显示的定时器
clearTimeout(timerHover);
// 隐藏的定时器
timerHold = setTimeout(function() {
drop.hide();
}, 200);
});
if (!target.data('dropHover')) {
target.hover(function() {
// 去除隐藏的定时器
clearTimeout(timerHold);
}, function() {
// 隐藏
timerHold = setTimeout(function() {
drop.hide();
}, 100);
});
target.data('dropHover', true);
}
break;
}
case 'click': {
trigger.delegate(params.selector, 'click', function(event) {
drop.el.trigger = $(this);
// 点击即显示
if (drop.display == false) {
drop.show();
} else {
drop.hide();
}
event.preventDefault();
});
break;
}
}
// 点击页面空白区域隐藏
if (params.eventType == 'null' || params.eventType == 'click') {
$(document).mousedown(function(event) {
var clicked = event && event.target;
if (!clicked || !drop || drop.display != true) return;
var tri = drop.el.trigger.get(0), tar = drop.el.target.get(0);
if (clicked != tri && clicked != tar && tri.contains(clicked) == false && tar.contains(clicked) == false) {
drop.hide();
}
});
}
// 窗体尺寸改变生活的重定位
$(window).resize(function() {
drop.follow();
});
};
Drop.prototype.follow = function() {
if (this.display = true && this.el.trigger.css('display') != 'none') {
this.el.target.follow(this.el.trigger, {
offsets: this.offsets,
position: this.position,
edgeAdjust: this.edgeAdjust
});
}
};
Drop.prototype.show = function() {
// target需要在页面中
var target = this.el.target;
if (target && $.contains(document.body, target.get(0)) == false) {
$('body').append(target);
}
this.display = true;
target.css('position', 'absolute').show();
// 定位
this.follow();
// onShow callback
if ($.isFunction(this.callback.show)) {
this.callback.show.call(this, this.el.trigger, this.el.target);
}
};
Drop.prototype.hide = function() {
this.el.target.hide();
this.display = false;
// onHide callback
if ($.isFunction(this.callback.hide)) {
this.callback.hide.call(this, this.el.trigger, this.el.target);
}
};
return Drop;
}));
/**
* @DropList.js
* @author xinxuzhang
* @version
* Created: 15-06-30
* 2017-03-13 使也支持委托
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.DropList = factory();
}
}(this, function (require) {
// require
if (typeof require == 'function') {
require('common/ui/Drop');
} else if (!$().drop) {
if (window.console) {
console.error('need Drop.js');
}
return {};
}
/*
* 下拉列表
* @trigger 触发下拉的按钮元素
* @data 下拉列表数据,数组,例如:
* [{
* id: 1,
* value: '所有评论',
* selected: true
* }, {
* id: 2,
* value: '未审核评论',
* disabled: true
* }, {
* id: 3,
* value: '通过评论'
* }]
* 也可以是Function函数,表示数据是动态呈现的
*/
var prefixDropList = 'ui-droplist-', SELECTED = 'selected', DISABLED = 'disabled';
var DropList = function(trigger, data, options) {
var defaults = {
eventType: 'click', // 触发元素显示的事件,‘null’直接显示;‘hover’是hover方法;‘click’是点击显示;其他为手动显示与隐藏
offsets: {
x: 0,
y: 0
},
selector: '',
width: '',
onShow: $.noop,
onHide: $.noop,
onSelect: $.noop // this为当前点击的列表元素,支持两个参数,第一个参数为列表元素对应的数据(纯对象),第二个是当前实例对象
};
var params = $.extend({}, defaults, options || {});
// 列表元素
var target = $('<div></div>').addClass(prefixDropList + 'x').css('width', params.width);
// 下拉三角
var arrow = trigger.find('.' + prefixDropList + 'arrow');
// 下拉三角元素的HTML代码
var htmlArrow = arrow.length? arrow.get(0).outerHTML: '';
// trigger除去三角以外的HTML代码
var htmlLeft = $.trim(trigger.html().replace(htmlArrow, ''));
// 创建列表
// 不管怎样,data需要是个有数据的数组
// 如果不符合条件,我们只能反馈没有数据
if ($.isArray(data) && data.length == 0) {
data = [{
value: '没有数据',
disabled: true
}];
} else if ($.isArray(data) && params.selector == '') {
// 1. 如果列表数据含有selected: true, 则自动重置trigger里面的内容
// 2. 如果列表数据没有selected: true, 则根据trigger的内容信息确定哪个数据是selected
var hasSelected = false, matchIndex = -1;
$.each(data, function(index, obj) {
if (obj.selected) {
trigger.html(obj.value + htmlArrow);
hasSelected = true;
}
if ($.trim(obj.value) == htmlLeft) {
matchIndex = index;
}
});
if (hasSelected == false && matchIndex != -1) {
data[matchIndex].selected = true;
}
}
// 根据data组装列表
var _get = function(arr) {
var html = '';
$.each(arr, function(index, obj) {
// 选中列表的类名
var clSelected = '';
if (obj[SELECTED]) clSelected = ' ' + SELECTED;
// 禁用态和非禁用使用标签区分
if (obj[DISABLED] != true) {
html = html + '<a href="javascript:;" class="'+ prefixDropList +'li'+ clSelected +'" data-index="'+ index +'">'+ obj.value +'</a>';
} else {
html = html + '<span class="'+ prefixDropList +'li">'+ obj.value +'</span>';
}
});
return html;
};
// 下拉面板
trigger.drop(target, {
eventType: params.eventType,
offsets: params.offsets,
selector: params.selector,
onShow: function() {
var _data = this.data;
if ($.isFunction(data)) {
_data = data();
// 更新
drop.data = _data;
}
target.html(_get(_data));
params.onShow.apply(this, [trigger, target]);
},
onHide: params.onHide
});
var drop = trigger.data('drop');
drop.data = data;
// 列表元素内容,事件
target.delegate('a', 'click', function() {
var index = $(this).attr('data-index') * 1;
if ($(this).hasClass(SELECTED) == false) {
// 除去所有的selected
if ($.isArray(data)) {
$.each(data, function(i, obj) {
if (obj[SELECTED]) {
obj[SELECTED] = null;
}
if (i == index) {
obj[SELECTED] = true;
}
});
// 缓存新的数据
drop.data = data;
trigger.html($(this).html() + htmlArrow);
}
params.onSelect.call(this, drop.data[index], drop);
}
drop.hide();
});
return drop;
};
return DropList;
}));
/**
* @DropPanel.js
* @author xinxuzhang
* @version
* Created: 15-07-01
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.DropPanel = factory();
}
}(this, function (require) {
// require
if (typeof require == 'function') {
require('common/ui/Drop');
} else if (!$().drop) {
if (window.console) {
console.error('need Drop.js');
}
return {};
}
/*
* 下拉面板
* @trigger 触发下拉的按钮元素
* @options 面板数据以及下拉参数,例如:
*{
* title: '删除评论',
* content: '删除后,您的粉丝在文章中将无法看到该评论。',
* buttons: [{}, {}]
* }
*/
var prefixGlobal = 'ui-', joiner = '-', prefixDropPanel = 'ui-dropanel-', SELECTED = 'selected', DISABLED = 'disabled';
// 关闭SVG
var svg = window.addEventListener? '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><path d="M116.152,99.999l36.482-36.486c2.881-2.881,2.881-7.54,0-10.42 l-5.215-5.215c-2.871-2.881-7.539-2.881-10.42,0l-36.484,36.484L64.031,47.877c-2.881-2.881-7.549-2.881-10.43,0l-5.205,5.215 c-2.881,2.881-2.881,7.54,0,10.42l36.482,36.486l-36.482,36.482c-2.881,2.881-2.881,7.549,0,10.43l5.205,5.215 c2.881,2.871,7.549,2.871,10.43,0l36.484-36.488L137,152.126c2.881,2.871,7.549,2.871,10.42,0l5.215-5.215 c2.881-2.881,2.881-7.549,0-10.43L116.152,99.999z"/></svg>': '';
var DropPanel = function(trigger, options) {
var defaults = {
title: '',
content: '',
buttons: [{}, {}],
width: 'auto',
eventType: 'click', // 触发元素显示的事件,‘null’直接显示;‘hover’是hover方法;‘click’是点击显示;其他为手动显示与隐藏
offsets: {
x: 0,
y: 0
},
onShow: $.noop,
onHide: $.noop
};
var params = $.extend({}, defaults, options || {});
// 面板容器
var target = $('<div></div>').addClass(prefixDropPanel + 'x');
if (/\d/.test(params.width)) {
target.width(params.width);
}
// 创建轻弹框面板的各个元素
var el = {};
// title
el.title = $('<h5></h5>').addClass(prefixDropPanel + 'title').html(params.title);
// close button
el.close = $('<a></a>').attr({
href: 'javascript:;'
}).html(svg).addClass(prefixDropPanel + 'close').click(function() {
drop.hide();
});
el.content = $('<div></div>').addClass(prefixDropPanel + 'content').html(params.content);
// footer
el.footer = $('<div></div>').addClass(prefixDropPanel + 'footer');
// 按钮
$.each(params.buttons, function(i, btn) {
// 避免btn为null等值报错
btn = btn || {};
// 按钮的默认参数
var type = i? (btn.type || ''): (btn.type || 'warning'),
value = i? (btn.value || '取消'): (btn.value || '确定'),
events = btn.events || {
click: function() {
drop.hide();
}
};
// 按钮的类名值
var cl = prefixGlobal +'button';
if (type) cl = cl + ' ' + cl + joiner + type;
el.footer.append(el['button' + i] =
$('<a href="javascript:;" class="'+ cl +'">'+ value + '</a>').bind(events)
);
});
// 组装
target.append(el.title).append(el.close).append(el.content).append(el.footer);
// 基于drop的面板显隐效果
trigger.drop(target, {
eventType: params.eventType,
offsets: params.offsets,
onShow: params.onShow,
onHide: params.onHide
});
var drop = trigger.data('drop');
for (key in el) {
drop.el[key] = el[key];
}
return drop;
};
return DropPanel;
}));
/**
* @Tips.js
* @author xunxuzhang
* @version
* Created: 15-06-25
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.Tips = factory();
}
}(this, function (require) {
if (typeof require == 'function') {
require('common/ui/Follow');
} else if (!$().follow) {
if (window.console) {
console.error('need Follow.js');
}
return {};
}
/**
* 黑色tips效果
* 支持jQuery包装器调用以及模块化调用
* @example
* $().tips(options);
* new Tips(el, options)
**/
// 类名变量
var CL = 'ui-tips', prefixTips = CL + '-';
$.fn.tips = function(options) {
return $(this).each(function() {
if (!$(this).data('tips')) {
$(this).data('tips', new Tips($(this), options));
}
});
};
var Tips = function(el, options) {
var defaults = {
attribute: 'title',
eventType: 'hover', // 'click', 'null'
content: '',
align: 'center',
delay: 100,
onShow: $.noop,
onHide: $.noop
};
if (typeof el == 'string') {
el = $(el);
}
if (!el || !el.length) {
return this;
}
var params = $.extend({}, defaults, options || {});
// 创建元素
var trigger = el, before, after;
// 分两种情况
// 1. IE9+ 纯CSS(伪元素)实现,使用类名ui-tips; IE7-IE8 内入两元素,水平居中效果JS实现
// 2. 所有浏览器都绝对定位跟随, 手动绑定
// 对于第一种情况
if (trigger.hasClass(CL)) {
// 如果元素含有title, 需要转换成data-title
var title = trigger.attr('title') || trigger.attr('data-title');
if (title) {
trigger.attr('data-title', title)
// 原本的title移除
.removeAttr('title');
}
// 对于IE7和IE8浏览器,我们需要插入两个元素
if (!window.addEventListener) {
before = $('<span class="'+ prefixTips +'before"></span>').html(title);
after = $('<i class="'+ prefixTips +'after"></i>');
// 前后插入
trigger.prepend(before);
trigger.append(after);
// 水平居中必须
before.css('margin-left', before.outerWidth() * -0.5);
after.css('margin-left', after.outerWidth() * -0.5);
// 其余交给CSS
}
trigger.data('tips', true);
return;
}
var self = this, tips, timer;
var _content = function() {
var content = params.content;
if (!content) {
content = trigger.attr(params.attribute);
// 如果是title, 移除避免重复交互
if (params.attribute == 'title') {
content = content || trigger.data('title');
if (content) {
trigger.data('title', content)
}
trigger.removeAttr('title');
}
}
return content;
}
// 暴露参数
this.el = {
trigger: trigger,
tips: tips
};
this.callback = {
show: params.onShow,
hide: params.onHide
};
this.align = params.align;
// 事件走起
if (params.eventType == 'hover') {
trigger.hover(function() {
var content = _content();
timer = setTimeout(function() {
self.show(content);
}, params.delay);
}, function() {
clearTimeout(timer);
self.hide();
});
} else if (params.eventType == "click") {
trigger.click(function() {
self.show(_content());
});
$(document).mouseup(function(event) {
var target = event.target, dom = trigger.get(0);
if (self.display == true && dom != target && dom.contains(target) == false && self.el.tips.get(0).contains(target) == false) {
self.hide();
}
});
} else {
this.show(_content());
}
return this;
};
Tips.prototype.show = function(content) {
if (!content) return this;
var trigger = this.el.trigger, tips = this.el.tips, before, after;
// 一些参数
if (tips) {
tips.show();
before = tips.find('span').html(content);
after = tips.find('i');
} else {
tips = $('<div></div>').addClass(prefixTips + 'x');
// 两个元素
before = $('<span class="'+ prefixTips +'before"></span>').html(content);
after = $('<i class="'+ prefixTips +'after"></i>');
$(document.body).append(tips.append(before).append(after));
}
// 水平偏移大小
var offsetX = 0, position = '5-7';
if (this.align == 'left') {
offsetX = -0.5 * before.width() + parseInt(before.css('padding-left')) || 0;
} else if (this.align == 'right') {
offsetX = 0.5 * before.width() - parseInt(before.css('padding-right')) || 0;
} else if (this.align == 'rotate') {
position = '6-8'
} else if (typeof this.align == 'number') {
offsetX = this.align;
}
tips.addClass(prefixTips + this.align);
if (this.align != 'rotate') after.css({
// 尖角的位置永远对准元素
left: offsetX
});
// 定位
tips.follow(trigger, {
offsets: {
x: offsetX,
y: 0
},
position: position, // trigger-target
edgeAdjust: false // 边界溢出不自动修正
});
// 显示的回调
this.callback.show.call(trigger, tips);
this.el.tips = tips;
this.display = true;
return this;
};
Tips.prototype.hide = function() {
if (this.el.tips) {
this.el.tips.hide();
// 移除回调
this.callback.hide.call(this.el.trigger, this.el.tips);
}
this.display = false;
return this;
};
Tips.prototype.init = function() {
$('.' + CL).tips();
// 全局委托,因为上面的初始化对于动态创建的IE7,IE8浏览器无效
$(document).mouseover(function(event) {
var target = event && event.target;
if (target && $(target).hasClass(CL) && !$(target).data('tips')) {
$(target).tips();
}
});
return this;
}
return Tips;
}));
/**
* @LightTip.js
* @author xunxuzhang
* @version
* Created: 15-06-25
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.LightTip = factory();
}
}(this, function () {
/**
* 顶部的请提示效果
* 支持jQuery $全局调用以及模块化调用
* @example
* $.lightTip.success(message);
* $.lightTip.error(message);
* new LightTip().success(message);
* new LightTip().error(message);
**/
// 类名变量
var CL = 'ui-lightip', prefixTips = CL + '-';
$.lightTip = (function() {
// 下面是两个私有方法
var _create = function(message) {
return _position($('<div class="'+ CL +'"></div>')
.html('<i class="'+ prefixTips +'icon"> </i><span class="'+ prefixTips +'text">' + message + '</span>')
.appendTo($(document.body)));
}, _position = function(tips) {
var zIndex = tips.css('z-index'), newZIndex = 0;
$('body').children().each(function() {
newZIndex = Math.max(zIndex, parseInt($(this).css('z-index')) || 0);
});
if (zIndex != newZIndex) {
tips.css('z-index', newZIndex);
}
return tips.css({
left: '50%',
marginLeft: tips.outerWidth() * -0.5
});
};
return {
success: function(message, time) {
var lightTips = _create(message).addClass(prefixTips + 'success');
setTimeout(function() {
lightTips.fadeOut(function() {
lightTips.remove();
lightTips = null;
});
}, time || 3000);
return lightTips;
},
error: function(message, time) {
var lightTips = _create(message).addClass(prefixTips + 'error');
setTimeout(function() {
lightTips.fadeOut(function() {
lightTips.remove();
lightTips = null;
});
}, time || 3000);
return lightTips;
}
}
})();
var LightTip = function() {
this.el = {};
return this;
};
LightTip.prototype.success = function(message) {
this.el.container = $.lightTip.success(message);
return this;
};
LightTip.prototype.error = function(message) {
this.el.container = $.lightTip.error(message);
return this;
};
return LightTip;
}));
/**
* @ErrorTip.js
* @author xunxuzhang
* @version
* Created: 15-07-01
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.ErrorTip = factory();
}
}(this, function (require, exports, module) {
if (typeof require == 'function') {
require('common/ui/Follow');
} else if (!$().follow) {
if (window.console) {
console.error('need Follow.js');
}
return {};
}
/**
* 红色的tips错误提示效果
* 支持jQuery包装器调用以及模块化调用
* @example
* $().tips(options);
* new Tips(el, options)
**/
// 类名变量
var CL = 'ui-tips', prefixTips = CL + '-';
$.fn.errorTip = function(content, options) {
var defaults = {
unique: true,
align: 'center',
onShow: $.noop,
onHide: $.noop
};
var params = $.extend({}, defaults, options || {});
// 要显示的字符内容
if ($.isFunction(content)) content = content();
if (typeof content != 'string') return this;
return $(this).each(function(index, element) {
// 单实例模式下,我们只处理第一个包装器元素
if (params.unique == true && index > 0) { return; }
// 一些元素
var trigger = $(this), tips, before, after;
if (params.unique == true && window.errorTip) {
tips = errorTip.data('trigger', trigger);
} else if (params.unique == false && trigger.data('errorTip')) {
tips = trigger.data('errorTip');
} else {
tips = $('<div class="'+ prefixTips +'x '+ prefixTips +'error"></div>').html(
'<span class="'+ prefixTips +'before"></span><i class="'+ prefixTips +'after"></i>'
);
$(document.body).append(tips.append(before).append(after));
// 如果是唯一模式,全局存储
if (params.unique == true) {
window.errorTip = tips.data('trigger', trigger);
} else {
trigger.data('errorTip', tips);
}
// 隐藏
var hide = function() {
if (tips.css('display') != 'none') {
tips.hide();
params.onHide.call((tips.data('trigger') || trigger).removeClass('error'), tips);
}
};
// 任何键盘操作,点击,或者拉伸都会隐藏错误提示框
$(document).bind({
keydown: function(event) {
// ctrl/shift键等不隐藏
if (event.keyCode != 16 && event.keyCode != 17) {
hide();
}
},
mousedown: function(event) {
var activeElement = document.activeElement,
activeTrigger = tips.data('trigger'),
activeTarget = event.target;
if (activeElement && activeTrigger && activeElement == activeTarget &&
activeElement == activeTrigger.get(0) &&
// 这个与Datalist.js关联
activeTrigger.data('focus') == false
) {
return;
}
hide();
}
});
$(window).bind({
resize: hide
});
}
// 显示提示
tips.show();
// 两个元素
before = tips.find('span');
after = tips.find('i');
// 修改content内容
before.html(content);
// 水平偏移大小
var offsetX = 0;
if (params.align == 'left') {
offsetX = -0.5 * before.width() + parseInt(before.css('padding-left')) || 0;
} else if (params.align == 'right') {
offsetX = 0.5 * before.width() - parseInt(before.css('padding-right')) || 0;
} else if (typeof params.align == 'number') {
offsetX = params.align;
}
after.css({
// 尖角的位置永远对准元素
left: offsetX
});
// 定位
tips.follow(trigger, {
align: params.align,
position: "5-7", //trigger-target
edgeAdjust: false // 边界溢出不自动修正
});
// 显示的回调
params.onShow.call(trigger.addClass('error valided'), tips);
});
};
var ErrorTip = function(el, content, options) {
el.errorTip(content, options);
this.el = {
trigger: el
};
this.cl = CL;
return this;
};
return ErrorTip;
}));
/**
* @Range.js
* @author xunxuzhang
* @version
* Created: 15-07-20
*/
(function (global, factory) {
if (typeof define === 'function' && (define.amd || define.cmd)) {
define(factory);
} else {
global.Range = factory();
}
}(this, function (require) {
if (typeof require == 'function') {
require('common/ui/Tips');
} else if (!$().tips) {
if (window.console) {
console.error('need Tips.js');
}
return {};
}
/**
* 基于HTML原生range范围选择框的模拟选择框效果
* 兼容IE7+
* min/max/step
*/
var CL = 'ui-range', rangePrefix = CL + '-';
$.fn.range = function(options) {
return $(this).each(function() {
if (!$(this).data('range')) {
$(this).data('range', new Range($(this), options));
}
});
};
var Range = function(el, options) {
var self = this;
// el就是type类型为range的input元素
var defaults = {
tips: function(value) {
return value;
}
};
var params = $.extend({}, defaults, options || {});
// 一些属性值获取
var min = el.attr('min') || 0, max = el.attr('max') || 100, step = el.attr('step') || 1;
// 一些元素的创建
// 容器元素有一个类名直接取自input元素,宽度啊,margin什么的,直接就交给CSS了
var container = $('<div></div>').attr('class', el.attr('class')).addClass(CL);
// 轨道元素
var track = $('<div></div>').addClass(rangePrefix + 'track');
// 中间的圈圈
var thumb = $('<a></a>').addClass(rangePrefix + 'thumb');
// 前置插入
el.before(container);
// 如果元素没宽度,则使用el计算的宽度
if (container.width() == 0) {
container.width(el.width());
}
// 组装
track.append(thumb);
container.append(track);
// 事件
container.click(function(event) {
var target = event && event.target;
if (target && target != thumb.get(0)) {
// 根据点击的位置在圈圈的左侧还是右侧判断选择值的增减
var distance = event.clientX - (thumb.offset().left - $(window).scrollLeft()) - thumb.width() / 2;
// 根据点击的距离,判断值
self.value(el.val() * 1 + (max - min) * distance / $(this).width());
}
});
// 拖动
var posThumb = {};
thumb.mousedown(function(event) {
posThumb.x = event.clientX;
posThumb.value = el.val() * 1;
// 黑色提示
if ($.isFunction(params.tips)) {
if (self.tips) {
self.tips.show(params.tips.call(el, posThumb.value));
} else {
thumb.tips({
eventType: 'null',
content: params.tips(posThumb.value)
});
self.tips = thumb.data('tips');
}
}
$(this).addClass('active');
});
$(document).mousemove(function(event) {
if (typeof posThumb.x == 'number') {
var distance = event.clientX - posThumb.x;
// 根据移动的距离,判断值
self.value(posThumb.value + (max - min) * distance / container.width());
if (self.tips) { self.tips.show(params.tips.call(el, el.val())); }
event.preventDefault();
}
});
$(document).mouseup(function(event) {
posThumb.x = null;
posThumb.value = null;
thumb.removeClass('active');
if (self.tips) { self.tips.hide(); }
});
// 全局
this.num = {
min: +min,
max: +max,
step: +step
};
this.el = {
input: el,
container: container,
track: track,
thumb: thumb
};
this.obj = {};
// 初始化
this.value();
return this;
};
Range.prototype.value = function(value) {
var input = this.el.input, oldvalue = input.val();
// 一些值
var max = this.num.max, min = this.num.min, step = this.num.step;
if (!value) {
oldvalue = value;
value = $.trim(input.val());
}
// 区域范围判断以及值是否合法的判断
if (value > max || (max - value) < step / 2) {
value = max;
} else if (value == '' || value < min || (value - min) < step / 2) {
value = min;
} else {
// 寻找最近的合法value值
value = min + Math.round((value - min) / step) * step;
}
input.val(value);
this.position();
if (value != oldvalue) {
input.trigger('change');
}
return this;
};
Range.prototype.position = function() {
var input = this.el.input, value = input.val();
// 一些值
var max = this.num.max, min = this.num.min, step = this.num.step;
// 计算百分比
this.el.track.css('borderLeftWidth', this.el.container.width() * (value - min) / (max - min));
return this;
};
return Range;
}));
/**
* @Color.js
* @author xunxuzhang