原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-410510
原作者:我佛山人
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//
类似手风琴的伸缩效果,需要结合Fx.Elements理解
// 演示:http://demos.mootools.net/Accordion
var Accordion = new Class({
// 继承自Fx.Elements
Extends: Fx.Elements,
options: { /*
//伸展显示事件
onActive: $empty,
//压缩隐藏事件
onBackground: $empty, */
// 显示的索引值
display: 0 ,
// 显示的索引值
show: false ,
// 高度的显示方式
height: true ,
// 宽度的显示方式
width: false ,
// 透明度的显示方式
opacity: true ,
// 是否固定高度
fixedHeight: false ,
// 是否固定宽度
fixedWidth: false ,
// 是否等待前一次动画结束
wait: false ,
// 永远隐藏
alwaysHide: false
},
// 构造函数
initialize: function () {
// 利用Array.link读取参数并归类
var params = Array.link(arguments, { ' container ' : Element.type, ' options ' : Object.type, ' togglers ' : $defined, ' elements ' : $defined});
// 调用父类Fx.Elements的同名方法
arguments.callee.parent(params.elements, params.options);
// 取能toggle的Elements(点击时伸缩的对象)
this .togglers = $$(params.togglers);
// 整个UI容器
this .container = $(params.container);
// 最后激活的对象索引
this .previous = - 1 ;
// 如果设置
if ( this .options.alwaysHide) this .options.wait = true ;
// 如果设置显示的索引值
if ($chk( this .options.show)) {
// 忽略display的设置
this .options.display = false ;
// 更新指向
this .previous = this .options.show;
}
// 如果手工执行start方法
if ( this .options.start) {
// 忽略display指定的值
this .options.display = false ;
// 忽略show指定的值
this .options.show = false ;
}
// 提供Fx.Eleemnts中变化的属性集
this .effects = {};
// 如果指定透明度,设效果中的透明属性值为完全透明
if ( this .options.opacity) this .effects.opacity = ' fullOpacity ' ;
// 如果指定宽度,当同时指定固定宽度时,设效果中的宽度属性值为全尺寸宽度,否则为当前宽度
if ( this .options.width) this .effects.width = this .options.fixedWidth ? ' fullWidth ' : ' offsetWidth ' ;
// 如果指定高度,当同时指定固定高度时,设效果中的高度属性值为全尺寸宽度,否则为当前高度
if ( this .options.height) this .effects.height = this .options.fixedHeight ? ' fullHeight ' : ' scrollHeight ' ;
// 遍历处理,为每一项添加事件
for ( var i = 0 , l = this .togglers.length; i < l; i ++ ) this .addSection( this .togglers[i], this .elements[i]);
// 遍历找到显示的指定项
this .elements.each( function (el, i) {
// 如果指定显示当前项
if ( this .options.show === i) {
// 触发onActive事件
this .fireEvent( ' onActive ' , [ this .togglers[i], el]);
} else {
// 设置非显示项的相关CSS属性为0
for ( var fx in this .effects) el.setStyle(fx, 0 );
}
}, this );
// 如果display有定义非0值,
if ($chk( this .options.display)) this .display( this .options.display);
},
// 添加节点
// togger为伸缩句柄,eleemnt为内容容器,pos为添加到的位置索引
addSection: function (toggler, element, pos) {
// 取对象
toggler = $(toggler);
element = $(element);
// 测试togglers集合中是否已包含toggler
var test = this .togglers.contains(toggler);
// 取集合长度
var len = this .togglers.length;
// 将toggler包含进togglers集合
this .togglers.include(toggler);
// 将element包含进elements集合
this .elements.include(element);
// 如果集合不为空,并且不包含当前项或添加位置大于0
if (len && ( ! test || pos)) {
// 取合法的位置
pos = $pick(pos, len - 1 );
// 插入到指定索引的项前
toggler.inject( this .togglers[pos], ' before ' );
// 内容容器插入其后
element.inject(toggler, ' after ' );
// 否则,如果指定父容器并且不在集合中
} else if ( this .container && ! test) {
// 插入到父容器中
toggler.inject( this .container);
element.inject( this .container);
}
// 取当前索引值
var idx = this .togglers.indexOf(toggler);
// 添加单击事件监听,在单击时显示当前索引位置上的对象
toggler.addEvent( ' click ' , this .display.bind( this , idx));
// 如果指定高度,为了兼容,将会影响高度值的padding和boder的上下值置0
if ( this .options.height) element.setStyles({ ' padding-top ' : 0 , ' border-top ' : ' none ' , ' padding-bottom ' : 0 , ' border-bottom ' : ' none ' });
// 如果指定宽度,为了兼容,将会影响宽度值的padding和boder的左右值置0
if ( this .options.width) element.setStyles({ ' padding-left ' : 0 , ' border-left ' : ' none ' , ' padding-right ' : 0 , ' border-right ' : ' none ' });
element.fullOpacity = 1 ;
// 如果设置固定宽度
if ( this .options.fixedWidth) element.fullWidth = this .options.fixedWidth;
// 如果设置固定高度
if ( this .options.fixedHeight) element.fullHeight = this .options.fixedHeight;
// 剪切溢出内容
element.setStyle( ' overflow ' , ' hidden ' );
// 如果集合中不包含当前项
if ( ! test) {
// 设置容器相关CSS属性为0
for ( var fx in this .effects) element.setStyle(fx, 0 );
}
return this ;
},
// 显示指定索引位置上的项
display: function (index) {
// 如果参数类型为对象,取对象在集合中的索引
index = ($type(index) == ' element ' ) ? this .elements.indexOf(index) : index;
// 如果已经开始显示并且设置要等待,或者指定索引与最后显示的相同并且不是指定永远隐藏,退出处理
if (( this .timer && this .options.wait) || (index === this .previous && ! this .options.alwaysHide)) return this ;
// 更新最后索引的指向
this .previous = index;
var ōbj = {};
// 遍历其余项,取得变化的属性集合,为start方法提供参数
this .elements.each( function (el, i) {
obj[i] = {};
// 计算需要隐藏的项
var hide = (i != index) || ( this .options.alwaysHide && (el.offsetHeight > 0 ));
// 根据显示或隐藏触发不同的事件
this .fireEvent(hide ? ' onBackground ' : ' onActive ' , [ this .togglers[i], el]);
// 隐藏时设置每个属性值为0
for ( var fx in this .effects) obj[i][fx] = hide ? 0 : el[ this .effects[fx]];
}, this );
// 开始执行效果
return this .start(obj);
}
});
// 演示:http://demos.mootools.net/Accordion
var Accordion = new Class({
// 继承自Fx.Elements
Extends: Fx.Elements,
options: { /*
//伸展显示事件
onActive: $empty,
//压缩隐藏事件
onBackground: $empty, */
// 显示的索引值
display: 0 ,
// 显示的索引值
show: false ,
// 高度的显示方式
height: true ,
// 宽度的显示方式
width: false ,
// 透明度的显示方式
opacity: true ,
// 是否固定高度
fixedHeight: false ,
// 是否固定宽度
fixedWidth: false ,
// 是否等待前一次动画结束
wait: false ,
// 永远隐藏
alwaysHide: false
},
// 构造函数
initialize: function () {
// 利用Array.link读取参数并归类
var params = Array.link(arguments, { ' container ' : Element.type, ' options ' : Object.type, ' togglers ' : $defined, ' elements ' : $defined});
// 调用父类Fx.Elements的同名方法
arguments.callee.parent(params.elements, params.options);
// 取能toggle的Elements(点击时伸缩的对象)
this .togglers = $$(params.togglers);
// 整个UI容器
this .container = $(params.container);
// 最后激活的对象索引
this .previous = - 1 ;
// 如果设置
if ( this .options.alwaysHide) this .options.wait = true ;
// 如果设置显示的索引值
if ($chk( this .options.show)) {
// 忽略display的设置
this .options.display = false ;
// 更新指向
this .previous = this .options.show;
}
// 如果手工执行start方法
if ( this .options.start) {
// 忽略display指定的值
this .options.display = false ;
// 忽略show指定的值
this .options.show = false ;
}
// 提供Fx.Eleemnts中变化的属性集
this .effects = {};
// 如果指定透明度,设效果中的透明属性值为完全透明
if ( this .options.opacity) this .effects.opacity = ' fullOpacity ' ;
// 如果指定宽度,当同时指定固定宽度时,设效果中的宽度属性值为全尺寸宽度,否则为当前宽度
if ( this .options.width) this .effects.width = this .options.fixedWidth ? ' fullWidth ' : ' offsetWidth ' ;
// 如果指定高度,当同时指定固定高度时,设效果中的高度属性值为全尺寸宽度,否则为当前高度
if ( this .options.height) this .effects.height = this .options.fixedHeight ? ' fullHeight ' : ' scrollHeight ' ;
// 遍历处理,为每一项添加事件
for ( var i = 0 , l = this .togglers.length; i < l; i ++ ) this .addSection( this .togglers[i], this .elements[i]);
// 遍历找到显示的指定项
this .elements.each( function (el, i) {
// 如果指定显示当前项
if ( this .options.show === i) {
// 触发onActive事件
this .fireEvent( ' onActive ' , [ this .togglers[i], el]);
} else {
// 设置非显示项的相关CSS属性为0
for ( var fx in this .effects) el.setStyle(fx, 0 );
}
}, this );
// 如果display有定义非0值,
if ($chk( this .options.display)) this .display( this .options.display);
},
// 添加节点
// togger为伸缩句柄,eleemnt为内容容器,pos为添加到的位置索引
addSection: function (toggler, element, pos) {
// 取对象
toggler = $(toggler);
element = $(element);
// 测试togglers集合中是否已包含toggler
var test = this .togglers.contains(toggler);
// 取集合长度
var len = this .togglers.length;
// 将toggler包含进togglers集合
this .togglers.include(toggler);
// 将element包含进elements集合
this .elements.include(element);
// 如果集合不为空,并且不包含当前项或添加位置大于0
if (len && ( ! test || pos)) {
// 取合法的位置
pos = $pick(pos, len - 1 );
// 插入到指定索引的项前
toggler.inject( this .togglers[pos], ' before ' );
// 内容容器插入其后
element.inject(toggler, ' after ' );
// 否则,如果指定父容器并且不在集合中
} else if ( this .container && ! test) {
// 插入到父容器中
toggler.inject( this .container);
element.inject( this .container);
}
// 取当前索引值
var idx = this .togglers.indexOf(toggler);
// 添加单击事件监听,在单击时显示当前索引位置上的对象
toggler.addEvent( ' click ' , this .display.bind( this , idx));
// 如果指定高度,为了兼容,将会影响高度值的padding和boder的上下值置0
if ( this .options.height) element.setStyles({ ' padding-top ' : 0 , ' border-top ' : ' none ' , ' padding-bottom ' : 0 , ' border-bottom ' : ' none ' });
// 如果指定宽度,为了兼容,将会影响宽度值的padding和boder的左右值置0
if ( this .options.width) element.setStyles({ ' padding-left ' : 0 , ' border-left ' : ' none ' , ' padding-right ' : 0 , ' border-right ' : ' none ' });
element.fullOpacity = 1 ;
// 如果设置固定宽度
if ( this .options.fixedWidth) element.fullWidth = this .options.fixedWidth;
// 如果设置固定高度
if ( this .options.fixedHeight) element.fullHeight = this .options.fixedHeight;
// 剪切溢出内容
element.setStyle( ' overflow ' , ' hidden ' );
// 如果集合中不包含当前项
if ( ! test) {
// 设置容器相关CSS属性为0
for ( var fx in this .effects) element.setStyle(fx, 0 );
}
return this ;
},
// 显示指定索引位置上的项
display: function (index) {
// 如果参数类型为对象,取对象在集合中的索引
index = ($type(index) == ' element ' ) ? this .elements.indexOf(index) : index;
// 如果已经开始显示并且设置要等待,或者指定索引与最后显示的相同并且不是指定永远隐藏,退出处理
if (( this .timer && this .options.wait) || (index === this .previous && ! this .options.alwaysHide)) return this ;
// 更新最后索引的指向
this .previous = index;
var ōbj = {};
// 遍历其余项,取得变化的属性集合,为start方法提供参数
this .elements.each( function (el, i) {
obj[i] = {};
// 计算需要隐藏的项
var hide = (i != index) || ( this .options.alwaysHide && (el.offsetHeight > 0 ));
// 根据显示或隐藏触发不同的事件
this .fireEvent(hide ? ' onBackground ' : ' onActive ' , [ this .togglers[i], el]);
// 隐藏时设置每个属性值为0
for ( var fx in this .effects) obj[i][fx] = hide ? 0 : el[ this .effects[fx]];
}, this );
// 开始执行效果
return this .start(obj);
}
});