lu2
Version:
Simple and flexible UI component library based on native HTML and JavaScript
244 lines (203 loc) • 5.71 kB
JavaScript
/**
* @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;
}));