[转帖]Mootools源码分析-45 -- Tips
原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-409496
原作者:我佛山人
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//信息提示层
//演示地址:http://demos.mootools.net/Tips
var Tips = new Class({
//继承自Events和Options,UI插件的特点
Implements: [Events, Options],
options: {
//显示事件
onShow: function(tip) {
tip.setStyle('visibility', 'visible');
},
//隐藏事件
onHide: function(tip) {
tip.setStyle('visibility', 'hidden');
},
//显示延时
showDelay: 100,
//隐藏延时
hideDelay: 100,
//提示层样式名
className: null,
//提示层显示时相对于鼠标位置的偏移量
offsets: {x: 16, y: 16},
//显示时是否不随鼠标移动
fixed: false
},
//构造函数
initialize: function() {
//利用Array.link自动选择参数
var params = Array.link(arguments, {options: Object.type, elements: $defined});
//合并参数
this.setOptions(params.options);
//提示层对象
this.tip = new Element('div').inject(document.body);
//如果指定CSS类名,添加
if (this.options.className) this.tip.addClass(this.options.className);
//提示层顶部
var top = new Element('div', {'class': 'tip-top'}).inject(this.tip);
//提示层内容的容器
this.container = new Element('div', {'class': 'tip'}).inject(this.tip);
//提示层底部
var bottom = new Element('div', {'class': 'tip-bottom'}).inject(this.tip);
//绝对位置,不可见
this.tip.setStyles({position: 'absolute', top: 0, left: 0, visibility: 'hidden'});
//附加使用提示层的对象
if (params.elements) this.attach(params.elements);
},
//为使用提示层的对象附加事件监听
attach: function(elements) {
//遍历每项
$$(elements).each(function(element) {
//获取缓存标题
var title = element.retrieve('tip:title', element.get('title'));
//获取缓存内容
var text = element.retrieve('tip:text', element.get('rel') || element.get('href'));
//缓存鼠标进入监听事件
var enter = element.retrieve('tip:enter', this.elementEnter.bindWithEvent(this, element));
//缓存鼠标离开监听事件
var leave = element.retrieve('tip:leave', this.elementLeave.bindWithEvent(this, element));
//添加鼠标进入和离开事件监听
element.addEvents({mouseenter: enter, mouseleave: leave});
//如果跟随鼠标
if (!this.options.fixed) {
//缓存鼠标移动监听事件
var move = element.retrieve('tip:move', this.elementMove.bindWithEvent(this, element));
//添加鼠标移动事件监听
element.addEvent('mousemove', move);
}
element.store('tip:native', element.get('title'));
//去除原title属性,避免显示重复的提示
element.erase('title');
}, this);
return this;
},
//移除事件监听
detach: function(elements) {
//遍历每项
$$(elements).each(function(element) {
//移除鼠标进入的事件监听
element.removeEvent('mouseenter', element.retrieve('tip:enter') || $empty);
//移除鼠标离开的事件监听
element.removeEvent('mouseleave', element.retrieve('tip:leave') || $empty);
//移除鼠标移动的事件监听
element.removeEvent('mousemove', element.retrieve('tip:move') || $empty);
//移除鼠标进入的事件监听
element.eliminate('tip:enter').eliminate('tip:leave').eliminate('tip:move');
//读取缓存的title值
var ōriginal = element.retrieve('tip:native');
//如果存在恢复其属性值
if (original) element.set('title', original);
});
return this;
},
//鼠标进入当前对象时的处理
elementEnter: function(event, element) {
//清空提示内容
this.container.empty();
//读取缓存的提示标题
var title = element.retrieve('tip:title');
//如果存在标题缓存
if (title) {
//创建对象并加到内容容器
this.titleElement = new Element('div', {'class': 'tip-title'}).inject(this.container);
//以缓存标题填充
this.fill(this.titleElement, title);
}
//读取缓存的提示内容
var text = element.retrieve('tip:text');
//如果存在标题缓存
if (text) {
//创建对象并加到内容容器
this.textElement = new Element('div', {'class': 'tip-text'}).inject(this.container);
//以缓存内容填充
this.fill(this.textElement, text);
}
//为防止重复,先清除计时器
this.timer = $clear(this.timer);
//延时显示
this.timer = this.show.delay(this.options.showDelay, this);
//如果设置提示层随鼠标移动,传送鼠标坐标信息,否则传送当前对象的坐标信息
this.position((!this.options.fixed) ? event : {page: element.getPosition()});
},
//鼠标离开时的处理
elementLeave: function(event) {
//清除计时器
$clear(this.timer);
//延时隐藏提示层
this.timer = this.hide.delay(this.options.hideDelay, this);
},
//鼠标移动时的处理
elementMove: function(event) {
//重新定位提示层
this.position(event);
},
//定位提示层
position: function(event) {
//获取文档窗口的尺寸和滚动条信息
var size = window.getSize(), scroll = window.getScroll();
//提示层的尺寸
var tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight};
//用于定位需要遍历的属性
var props = {x: 'left', y: 'top'};
//遍历定位需要处理的属性
for (var z in props) {
//计算出当前坐标方向上的目标值
var pos = event.page[z] + this.options.offsets[z];
//对于提示层超出窗口时的处理
if ((pos + tip[z] - scroll[z]) > size[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
//设置当前坐标方向上的坐标值
this.tip.setStyle(props[z], pos);
}
},
//以指定内容或对象填充对象
fill: function(element, contents) {
(typeof contents == 'string') ? element.set('html', contents) : element.adopt(contents);
},
//显示提示层
show: function() {
//触发onShow事件
this.fireEvent('onShow', this.tip);
},
//显示提示层
hide: function() {
//触发onShow事件
this.fireEvent('onHide', this.tip);
}
});
//演示地址:http://demos.mootools.net/Tips
var Tips = new Class({
//继承自Events和Options,UI插件的特点
Implements: [Events, Options],
options: {
//显示事件
onShow: function(tip) {
tip.setStyle('visibility', 'visible');
},
//隐藏事件
onHide: function(tip) {
tip.setStyle('visibility', 'hidden');
},
//显示延时
showDelay: 100,
//隐藏延时
hideDelay: 100,
//提示层样式名
className: null,
//提示层显示时相对于鼠标位置的偏移量
offsets: {x: 16, y: 16},
//显示时是否不随鼠标移动
fixed: false
},
//构造函数
initialize: function() {
//利用Array.link自动选择参数
var params = Array.link(arguments, {options: Object.type, elements: $defined});
//合并参数
this.setOptions(params.options);
//提示层对象
this.tip = new Element('div').inject(document.body);
//如果指定CSS类名,添加
if (this.options.className) this.tip.addClass(this.options.className);
//提示层顶部
var top = new Element('div', {'class': 'tip-top'}).inject(this.tip);
//提示层内容的容器
this.container = new Element('div', {'class': 'tip'}).inject(this.tip);
//提示层底部
var bottom = new Element('div', {'class': 'tip-bottom'}).inject(this.tip);
//绝对位置,不可见
this.tip.setStyles({position: 'absolute', top: 0, left: 0, visibility: 'hidden'});
//附加使用提示层的对象
if (params.elements) this.attach(params.elements);
},
//为使用提示层的对象附加事件监听
attach: function(elements) {
//遍历每项
$$(elements).each(function(element) {
//获取缓存标题
var title = element.retrieve('tip:title', element.get('title'));
//获取缓存内容
var text = element.retrieve('tip:text', element.get('rel') || element.get('href'));
//缓存鼠标进入监听事件
var enter = element.retrieve('tip:enter', this.elementEnter.bindWithEvent(this, element));
//缓存鼠标离开监听事件
var leave = element.retrieve('tip:leave', this.elementLeave.bindWithEvent(this, element));
//添加鼠标进入和离开事件监听
element.addEvents({mouseenter: enter, mouseleave: leave});
//如果跟随鼠标
if (!this.options.fixed) {
//缓存鼠标移动监听事件
var move = element.retrieve('tip:move', this.elementMove.bindWithEvent(this, element));
//添加鼠标移动事件监听
element.addEvent('mousemove', move);
}
element.store('tip:native', element.get('title'));
//去除原title属性,避免显示重复的提示
element.erase('title');
}, this);
return this;
},
//移除事件监听
detach: function(elements) {
//遍历每项
$$(elements).each(function(element) {
//移除鼠标进入的事件监听
element.removeEvent('mouseenter', element.retrieve('tip:enter') || $empty);
//移除鼠标离开的事件监听
element.removeEvent('mouseleave', element.retrieve('tip:leave') || $empty);
//移除鼠标移动的事件监听
element.removeEvent('mousemove', element.retrieve('tip:move') || $empty);
//移除鼠标进入的事件监听
element.eliminate('tip:enter').eliminate('tip:leave').eliminate('tip:move');
//读取缓存的title值
var ōriginal = element.retrieve('tip:native');
//如果存在恢复其属性值
if (original) element.set('title', original);
});
return this;
},
//鼠标进入当前对象时的处理
elementEnter: function(event, element) {
//清空提示内容
this.container.empty();
//读取缓存的提示标题
var title = element.retrieve('tip:title');
//如果存在标题缓存
if (title) {
//创建对象并加到内容容器
this.titleElement = new Element('div', {'class': 'tip-title'}).inject(this.container);
//以缓存标题填充
this.fill(this.titleElement, title);
}
//读取缓存的提示内容
var text = element.retrieve('tip:text');
//如果存在标题缓存
if (text) {
//创建对象并加到内容容器
this.textElement = new Element('div', {'class': 'tip-text'}).inject(this.container);
//以缓存内容填充
this.fill(this.textElement, text);
}
//为防止重复,先清除计时器
this.timer = $clear(this.timer);
//延时显示
this.timer = this.show.delay(this.options.showDelay, this);
//如果设置提示层随鼠标移动,传送鼠标坐标信息,否则传送当前对象的坐标信息
this.position((!this.options.fixed) ? event : {page: element.getPosition()});
},
//鼠标离开时的处理
elementLeave: function(event) {
//清除计时器
$clear(this.timer);
//延时隐藏提示层
this.timer = this.hide.delay(this.options.hideDelay, this);
},
//鼠标移动时的处理
elementMove: function(event) {
//重新定位提示层
this.position(event);
},
//定位提示层
position: function(event) {
//获取文档窗口的尺寸和滚动条信息
var size = window.getSize(), scroll = window.getScroll();
//提示层的尺寸
var tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight};
//用于定位需要遍历的属性
var props = {x: 'left', y: 'top'};
//遍历定位需要处理的属性
for (var z in props) {
//计算出当前坐标方向上的目标值
var pos = event.page[z] + this.options.offsets[z];
//对于提示层超出窗口时的处理
if ((pos + tip[z] - scroll[z]) > size[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
//设置当前坐标方向上的坐标值
this.tip.setStyle(props[z], pos);
}
},
//以指定内容或对象填充对象
fill: function(element, contents) {
(typeof contents == 'string') ? element.set('html', contents) : element.adopt(contents);
},
//显示提示层
show: function() {
//触发onShow事件
this.fireEvent('onShow', this.tip);
},
//显示提示层
hide: function() {
//触发onShow事件
this.fireEvent('onHide', this.tip);
}
});