以下是 jquery多功能手风琴特效代码 的示例演示效果:
部分效果截图:
HTML代码(index.html):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jquery多功能手风琴</title>
<script type="text/javascript" src="javascript/prototype.js"></script>
<script type="text/javascript" src="javascript/effects.js"></script>
<script type="text/javascript" src="javascript/accordion.js"></script>
<script type="text/javascript" src="javascript/code_highlighter.js"></script>
<script type="text/javascript" src="javascript/javascript.js"></script>
<script type="text/javascript" src="javascript/html.js"></script>
<link rel="stylesheet" type="text/css" href="css/default.css" />
<script type="text/javascript">
Event.observe(window, 'load', loadAccordions, false);
function loadAccordions() {
var topAccordion = new accordion('horizontal_container', {
classNames : {
toggle : 'horizontal_accordion_toggle',
toggleActive : 'horizontal_accordion_toggle_active',
content : 'horizontal_accordion_content'
},
defaultSize : {
width : 525
},
direction : 'horizontal'
});
var bottomAccordion = new accordion('vertical_container');
var nestedVerticalAccordion = new accordion('vertical_nested_container', {
classNames : {
toggle : 'vertical_accordion_toggle',
toggleActive : 'vertical_accordion_toggle_active',
content : 'vertical_accordion_content'
}
});
// Open first one
bottomAccordion.activate($$('#vertical_container .accordion_toggle')[0]);
// Open second one
topAccordion.activate($$('#horizontal_container .horizontal_accordion_toggle')[2]);
}
</script>
<!-- CSS -->
<style type="text/css" >
/*
Vertical Accordions
*/
.accordion_toggle {
display: block;
height: 30px;
width: 680px;
background: url(images/accordion_toggle.jpg) no-repeat top right #a9d06a;
padding: 0 10px 0 10px;
line-height: 30px;
color: #ffffff;
font-weight: normal;
text-decoration: none;
outline: none;
font-size: 12px;
color: #000000;
border-bottom: 1px solid #cde99f;
cursor: pointer;
margin: 0 0 0 0;
}
.accordion_toggle_active {
background: url(images/accordion_toggle_active.jpg) no-repeat top right #e0542f;
color: #ffffff;
border-bottom: 1px solid #f68263;
}
.accordion_content {
background-color: #ffffff;
color: #444444;
overflow: hidden;
}
.accordion_content h2 {
margin: 15px 0 5px 10px;
color: #0099FF;
}
.accordion_content p {
line-height: 150%;
padding: 5px 10px 15px 10px;
}
.vertical_accordion_toggle {
display: block;
height: 30px;
width: 600px;
background: url(images/accordion_toggle.jpg) no-repeat top right #a9d06a;
padding: 0 10px 0 10px;
line-height: 30px;
color: #ffffff;
font-weight: normal;
text-decoration: none;
outline: none;
font-size: 12px;
color: #000000;
border-bottom: 1px solid #cde99f;
cursor: pointer;
margin: 0 0 0 0;
}
.vertical_accordion_toggle_active {
background: url(images/accordion_toggle_active.jpg) no-repeat top right #e0542f;
color: #ffffff;
border-bottom: 1px solid #f68263;
}
.vertical_accordion_content {
background-color: #ffffff;
color: #444444;
overflow: hidden;
}
.vertical_accordion_content h2 {
margin: 15px 0 5px 10px;
color: #0099FF;
}
.vertical_accordion_content p {
line-height: 150%;
padding: 5px 10px 15px 10px;
}
/*
Horizontal Accordion
*/
.horizontal_accordion_toggle {
/* REQUIRED */
float: left; /* This make sure it stays horizontal */
/* REQUIRED */
display: block;
height: 100px;
width: 30px;
background: url(images/h_accordion_toggle.jpg) no-repeat top left #a9d06a;
color: #ffffff;
text-decoration: none;
outline: none;
border-right: 1px solid #cde99f;
cursor: pointer;
margin: 0 0 0 0;
}
.horizontal_accordion_toggle_active {
background: url(images/h_accordion_toggle_active.jpg) no-repeat top left #e0542f;
border-right: 1px solid #f68263;
}
.horizontal_accordion_content {
/* REQUIRED */
height: 100px; /* We need to define a height for the accordion as it stretches the width */
float: left; /* This make sure it stays horizontal */
/* REQUIRED */
overflow: hidden;
background-color: #ffffff;
color: #444444;
}
.horizontal_accordion_content p {
width: 450px;
line-height: 150%;
padding: 5px 10px 15px 10px;
}
/* Container styling*/
#horizontal_container {
margin: 20px auto 20px auto;
width: 680px;
height: 100px;
}
#vertical_nested_container {
margin: 20px auto 20px auto;
width: 620px;
}
</style>
</head>
<body>
<div id="container">
<h1><span>jquery多功能手风琴</span> v2.0</h1>
<br>
<div id="vertical_container" >
<h1 class="accordion_toggle">Changelog</h1>
<div class="accordion_content">
<h2>What's new in v2.0?</h2>
<p>Well i listened to all you guys out there in my forum and my blog and now all those wishes have been granted!</p>
<p>
<ul style="margin: 0 0 0 50px;">
<li>Open/Close functionality added (Click on an active accordion).</li>
<li>Nested Vertical Accordions</li>
<li>Accordions will dynamically resize on content added REAL TIME!</li>
<li>...lots of bug fixes!</li>
</ul>
</p>
</div>
<h1 class="accordion_toggle">Donate! Help me get a MacBook Pro</h1>
<div class="accordion_content">
<h2>Help me get a MacBook Pro!</h2>
<p>
Hello everyone, I have now released my accordion script and its better than any other one out there! That's right I said it. I will be releasing a few more of my scripts in the weeks to come. In the meantime though help me get a MacBook Pro so I have a mac to test on! Anything you could throw my way would be appreciated, I will also give back in my forums, so no worries, I give back even more!
</p>
<p> </p>
<p> </p>
</div>
<h1 class="accordion_toggle">Why another Accordion?</h1>
<div class="accordion_content">
<h2>Uhm... There wasn't one, well not a good one.</h2>
<p>
Haha! Like there was one. Well there was, but only for Rico and a bloated one by mootools, that's right I said bloated, live with it. For some reason there wasn't one for scriptaculous but now there is. The why is pretty simple, just like every other library, I had a need for it. Hope you can get some use out of it.
</p>
<p>
Oh, by the way, not only does this script handle <strong>vertical</strong> accordions, but <strong>horizontal</strong> as well!
</p>
</div>
<h1 class="accordion_toggle">A Horizontal Accordion! (Nested)</h1>
<div class="accordion_content">
<h2>Oh yeah, just a few options... BAM Horizontal!</h2>
<div id="horizontal_container" >
<h3 class="horizontal_accordion_toggle"></h3>
<div class="horizontal_accordion_content">
<p>
Integer commodo nibh sit amet odio. Pellentesque semper. Integer dolor. Donec scelerisque sapien placerat velit.
</p>
</div>
<h3 class="horizontal_accordion_toggle"></h3>
<div class="horizontal_accordion_content">
<p>
Sed at pede vitae turpis porta condimentum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla facilisi. Morbi erat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
</p>
</div>
<h3 class="horizontal_accordion_toggle"></h3>
<div class="horizontal_accordion_content">
<p>
Curabitur quam lorem, laoreet molestie, eleifend id, pulvinar vel, nunc. Proin congue felis quis purus. Aenean porttitor, lacus vel bibendum pulvinar, leo nulla suscipit leo, nec lobortis orci diam eget turpis. Sed eu eros et orci consectetuer molestie. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
</div>
<h3 class="horizontal_accordion_toggle"></h3>
<div class="horizontal_accordion_content">
<p>
Sed at pede vitae turpis porta condimentum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla facilisi. Morbi erat.
</p>
</div>
<h3 class="horizontal_accordion_toggle"></h3>
<div class="horizontal_accordion_content">
<p>
Integer commodo nibh sit amet odio. Pellentesque semper. Integer dolor. Donec scelerisque sapien placerat velit. Nulla suscipit, elit quis pretium hendrerit, nisi sapien lobortis libero, et consectetuer lorem sapien id urna.
</p>
</div>
</div>
</div>
<h1 class="accordion_toggle">A Vertical Nested Accordion!</h1>
<div class="accordion_content">
<div id="vertical_nested_container" >
<h3 class="vertical_accordion_toggle">Hablo pig-latin?</h3>
<div class="vertical_accordion_content">
<p>
Integer commodo nibh sit amet odio. Pellentesque semper. Integer dolor. Donec scelerisque sapien placerat velit.
</p>
</div>
<h3 class="vertical_accordion_toggle">Isn't this kewl?'</h3>
<div class="vertical_accordion_content">
<p>
Sed at pede vitae turpis porta condimentum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla facilisi. Morbi erat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
</p>
</div>
<h3 class="vertical_accordion_toggle">Click me!</h3>
<div class="vertical_accordion_content">
<p>
Curabitur quam lorem, laoreet molestie, eleifend id, pulvinar vel, nunc. Proin congue felis quis purus. Aenean porttitor, lacus vel bibendum pulvinar, leo nulla suscipit leo, nec lobortis orci diam eget turpis. Sed eu eros et orci consectetuer molestie. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
</div>
<h3 class="vertical_accordion_toggle">Don't you dare....'</h3>
<div class="vertical_accordion_content">
<p>
Sed at pede vitae turpis porta condimentum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla facilisi. Morbi erat.
</p>
</div>
<h3 class="vertical_accordion_toggle">Your Mom!</h3>
<div class="vertical_accordion_content">
<p>
Integer commodo nibh sit amet odio. Pellentesque semper. Integer dolor. Donec scelerisque sapien placerat velit. Nulla suscipit, elit quis pretium hendrerit, nisi sapien lobortis libero, et consectetuer lorem sapien id urna.
</p>
</div>
</div>
</div>
<h1 class="accordion_toggle">Download the code!</h1>
<div class="accordion_content">
<h2>Download</h2>
<p>
Get it here <a href="accordion.zip">accordion v1.0</a>
</p>
<p>Oh and... help me with a MacBook Pro?</p>
</div>
<h1 class="accordion_toggle">How to Use</h1>
<div class="accordion_content">
<h2>Include the files</h2>
<p>
You need to include accordion.js but it requires prototype.js and effects.js (like I said this is for scriptaculous!). As long as you are using at least the latest stable builds you are fine.
<pre><code class="html"><script type="text/javascript" src="javascript/prototype.js"></script>
<script type="text/javascript" src="javascript/effects.js"></script>
<script type="text/javascript" src="javascript/accordion.js"></script></code></pre>
<h2>The Markup</h2>
<p>
Pretty much anything will work, so its really up to you. The presentation is up to you (see the source of this page for some examples). Ideally you should probably use header tags with div's containing the content as this would be best symantically speaking and for seo. Below is a basic example.
</p>
<pre><code class="html"><h2 class="accordion_toggle">Title Bar</h2>
<div class="accordion_content">...</div>
...
...
...
<h2 class="accordion_toggle">Title Bar</h2>
<div class="accordion_content">...</div></code></pre>
<p>
The important thing here is that it need to be the title element then the content element and so on, nothing in between, just like every other accordion.
</p>
<h2>The Options</h2>
<p>
Not many options, but all you need to make this thing do anything you may require!
</p>
<pre><code class="javascript">// The speed of the accordion
resizeSpeed : 8,
// The classnames to look for
classNames : {
// The standard class for the title bar
toggle : 'accordion_toggle',
// The class used for the active state of the title bar
toggleActive : 'accordion_toggle_active',
// The class used to find the content
content : 'accordion_content'
},
// If you don't want the accordion to stretch to fit
// its content, set a value here, handy for horixontal examples.
defaultSize : {
height : null,
width : null
},
// The direction of the accordion
direction : 'vertical',
// Should the accordion activate on click or say on mouseover? (apple.com)
onEvent : 'click'</code></pre>
<p>
Now these are the default options set automatically, so let's now take a look on how to create an accordion and change those options.
</p>
<h2>The Javascript</h2>
<p>
Below is how I created the two accordions you see on this page, one vertical, one horizontal with a specified width.
</p>
<pre><code class="javascript">// General Syntax
new accordion('container-selector', options);
// Horizontal example
var horizontalAccordion = new accordion('#top_container', {
classNames : {
toggle : 'horizontal_accordion_toggle',
toggleActive : 'horizontal_accordion_toggle_active',
content : 'horizontal_accordion_content'
},
defaultSize : {
width : 525
},
direction : 'horizontal'
});
// Vertical Accordion
var verticalAccordion = new accordion('#bottom_container');</code></pre>
<p>
Ok, so now we know how to do the markup, hopefully you got creative with the css and looked at the source of this page to get started, and not you know how make an accordion. What if you want to use javascript to open a slide on load or at any time... here is how.
</p>
<pre><code class="javascript">// Let's create it
var verticalAccordion = new accordion('#bottom_container');
// Now lets open the first slide
verticalAccordion.activate($$('#bottom_container .accordion_toggle')[0]);
</code></pre>
<p>
So we use the selector method from prototype to get the first title bar from the container+classname and we want the first one so we use [0]. Couldn't be easier!
</p>
<h2>Preload</h2>
<p>So let's say you want all your accordions closed on page load but don't want the nasty flash and don't want to sacrifice accessibility. </p>
<pre><code class="javascript">// Special thanks go out to Will Shaver @ http://primedigit.com/
var verticalAccordions = $$('.accordion_toggle');
verticalAccordions.each(function(accordion) {
$(accordion.next(0)).setStyle({
height: '0px'
});
});
</code></pre>
</div>
</div>
</div>
<script type="text/javascript" >
var verticalAccordions = $$('.accordion_toggle');
verticalAccordions.each(function(accordion) {
$(accordion.next(0)).setStyle({
height: '0px'
});
});
</script>
<br><br>
</body>
</html>
JS代码(accordion.js):
// accordion.js v2.0//// Copyright (c) 2007 stickmanlabs// Author:Kevin P Miller | http://www.stickmanlabs.com//// Accordion is freely distributable under the terms of an MIT-style license.//// I don't care what you think about the file size...// Be a pro:// http://www.thinkvitamin.com/features/webapps/serving-javascript-fast// http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files///*-----------------------------------------------------------------------------------------------*/
if (typeof Effect == 'undefined')throw("accordion.js requires including script.aculo.us' effects.js library!");
var accordion = Class.create();
accordion.prototype ={
//// Setup the Variables//showAccordion:null,currentAccordion:null,duration:null,effects:[],animating:false,//// Initialize the accordions//initialize:function(container,options){
if (!$(container)){
throw(container+" doesn't exist!");
return false;
}
this.options = Object.extend({
resizeSpeed:8,classNames:{
toggle:'accordion_toggle',toggleActive:'accordion_toggle_active',content:'accordion_content'}
,defaultSize:{
height:null,width:null}
,direction:'vertical',onEvent:'click'}
,options ||{
}
);
this.duration = ((11-this.options.resizeSpeed)*0.15);
var accordions = $$('#'+container+' .'+this.options.classNames.toggle);
accordions.each(function(accordion){
Event.observe(accordion,this.options.onEvent,this.activate.bind(this,accordion),false);
if (this.options.onEvent == 'click'){
accordion.onclick = function(){
return false;
}
;
}
if (this.options.direction == 'horizontal'){
var options = $H({
width:'0px'}
);
}
else{
var options = $H({
height:'0px'}
);
}
options.merge({
display:'none'}
);
this.currentAccordion = $(accordion.next(0)).setStyle(options);
}
.bind(this));
}
,//// Activate an accordion//activate:function(accordion){
if (this.animating){
return false;
}
this.effects = [];
this.currentAccordion = $(accordion.next(0));
this.currentAccordion.setStyle({
display:'block'}
);
this.currentAccordion.previous(0).addClassName(this.options.classNames.toggleActive);
if (this.options.direction == 'horizontal'){
this.scaling = $H({
scaleX:true,scaleY:false}
);
}
else{
this.scaling = $H({
scaleX:false,scaleY:true}
);
}
if (this.currentAccordion == this.showAccordion){
this.deactivate();
}
else{
this._handleAccordion();
}
}
,//// Deactivate an active accordion//deactivate:function(){
var options = $H({
duration:this.duration,scaleContent:false,transition:Effect.Transitions.sinoidal,queue:{
position:'end',scope:'accordionAnimation'}
,scaleMode:{
originalHeight:this.options.defaultSize.height ? this.options.defaultSize.height:this.currentAccordion.scrollHeight,originalWidth:this.options.defaultSize.width ? this.options.defaultSize.width:this.currentAccordion.scrollWidth}
,afterFinish:function(){
this.showAccordion.setStyle({
height:'auto',display:'none'}
);
this.showAccordion = null;
this.animating = false;
}
.bind(this)}
);
options.merge(this.scaling);
this.showAccordion.previous(0).removeClassName(this.options.classNames.toggleActive);
new Effect.Scale(this.showAccordion,0,options);
}
,// // Handle the open/close actions of the accordion //_handleAccordion:function(){
var options = $H({
sync:true,scaleFrom:0,scaleContent:false,transition:Effect.Transitions.sinoidal,scaleMode:{
originalHeight:this.options.defaultSize.height ? this.options.defaultSize.height:this.currentAccordion.scrollHeight,originalWidth:this.options.defaultSize.width ? this.options.defaultSize.width:this.currentAccordion.scrollWidth}
}
);
options.merge(this.scaling);
this.effects.push(new Effect.Scale(this.currentAccordion,100,options));
if (this.showAccordion){
this.showAccordion.previous(0).removeClassName(this.options.classNames.toggleActive);
options = $H({
sync:true,scaleContent:false,transition:Effect.Transitions.sinoidal}
);
options.merge(this.scaling);
this.effects.push(new Effect.Scale(this.showAccordion,0,options));
}
new Effect.Parallel(this.effects,{
duration:this.duration,queue:{
position:'end',scope:'accordionAnimation'}
,beforeStart:function(){
this.animating = true;
}
.bind(this),afterFinish:function(){
if (this.showAccordion){
this.showAccordion.setStyle({
display:'none'}
);
}
$(this.currentAccordion).setStyle({
height:'auto'}
);
this.showAccordion = this.currentAccordion;
this.animating = false;
}
.bind(this)}
);
}
}
JS代码(effects.js):
// script.aculo.us effects.js v1.7.0,Fri Jan 19 19:16:36 CET 2007// Copyright (c) 2005,2006 Thomas Fuchs (http://script.aculo.us,http://mir.aculo.us)// Contributors:// Justin Palmer (http://encytemedia.com/)// Mark Pilgrim (http://diveintomark.org/)// Martin Bialasinki//// script.aculo.us is freely distributable under the terms of an MIT-style license.// For details,see the script.aculo.us web site:http://script.aculo.us/// converts rgb() and #xxx to #xxxxxx format,// returns self (or first argument) if not convertableString.prototype.parseColor = function(){
var color = '#';
if(this.slice(0,4) == 'rgb('){
var cols = this.slice(4,this.length-1).split(',');
var i=0;
do{
color += parseInt(cols[i]).toColorPart()}
while (++i<3);
}
else{
if(this.slice(0,1) == '#'){
if(this.length==4) for(var i=1;
i<4;
i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
if(this.length==7) color = this.toLowerCase();
}
}
return(color.length==7 ? color:(arguments[0] || this));
}
/*--------------------------------------------------------------------------*/
Element.collectTextNodes = function(element){
return $A($(element).childNodes).collect( function(node){
return (node.nodeType==3 ? node.nodeValue:(node.hasChildNodes() ? Element.collectTextNodes(node):''));
}
).flatten().join('');
}
Element.collectTextNodesIgnoreClass = function(element,className){
return $A($(element).childNodes).collect( function(node){
return (node.nodeType==3 ? node.nodeValue:((node.hasChildNodes() && !Element.hasClassName(node,className)) ? Element.collectTextNodesIgnoreClass(node,className):''));
}
).flatten().join('');
}
Element.setContentZoom = function(element,percent){
element = $(element);
element.setStyle({
fontSize:(percent/100) + 'em'}
);
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
return element;
}
Element.getOpacity = function(element){
return $(element).getStyle('opacity');
}
Element.setOpacity = function(element,value){
return $(element).setStyle({
opacity:value}
);
}
Element.getInlineOpacity = function(element){
return $(element).style.opacity || '';
}
Element.forceRerendering = function(element){
try{
element = $(element);
var n = document.createTextNode(' ');
element.appendChild(n);
element.removeChild(n);
}
catch(e){
}
}
;
/*--------------------------------------------------------------------------*/
Array.prototype.call = function(){
var args = arguments;
this.each(function(f){
f.apply(this,args)}
);
}
/*--------------------------------------------------------------------------*/
var Effect ={
_elementDoesNotExistError:{
name:'ElementDoesNotExistError',message:'The specified DOM element does not exist,but is required for this effect to operate'}
,tagifyText:function(element){
if(typeof Builder == 'undefined') throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
var tagifyStyle = 'position:relative';
if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';
zoom:1';
element = $(element);
$A(element.childNodes).each( function(child){
if(child.nodeType==3){
child.nodeValue.toArray().each( function(character){
element.insertBefore( Builder.node('span',{
style:tagifyStyle}
,character == ' ' ? String.fromCharCode(160):character),child);
}
);
Element.remove(child);
}
}
);
}
,multiple:function(element,effect){
var elements;
if(((typeof element == 'object') || (typeof element == 'function')) && (element.length)) elements = element;
else elements = $(element).childNodes;
var options = Object.extend({
speed:0.1,delay:0.0}
,arguments[2] ||{
}
);
var masterDelay = options.delay;
$A(elements).each( function(element,index){
new effect(element,Object.extend(options,{
delay:index * options.speed + masterDelay}
));
}
);
}
,PAIRS:{
'slide':['SlideDown','SlideUp'],'blind':['BlindDown','BlindUp'],'appear':['Appear','Fade']}
,toggle:function(element,effect){
element = $(element);
effect = (effect || 'appear').toLowerCase();
var options = Object.extend({
queue:{
position:'end',scope:(element.id || 'global'),limit:1}
}
,arguments[2] ||{
}
);
Effect[element.visible() ? Effect.PAIRS[effect][1]:Effect.PAIRS[effect][0]](element,options);
}
}
;
var Effect2 = Effect;
// deprecated/* ------------- transitions ------------- */
Effect.Transitions ={
linear:Prototype.K,sinoidal:function(pos){
return (-Math.cos(pos*Math.PI)/2) + 0.5;
}
,reverse:function(pos){
return 1-pos;
}
,flicker:function(pos){
return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
}
,wobble:function(pos){
return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
}
,pulse:function(pos,pulses){
pulses = pulses || 5;
return ( Math.round((pos % (1/pulses)) * pulses) == 0 ? ((pos * pulses * 2) - Math.floor(pos * pulses * 2)):1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) );
}
,none:function(pos){
return 0;
}
,full:function(pos){
return 1;
}
}
;
/* ------------- core effects ------------- */
Effect.ScopedQueue = Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype,Enumerable),{
initialize:function(){
this.effects = [];
this.interval = null;
}
,_each:function(iterator){
this.effects._each(iterator);
}
,add:function(effect){
var timestamp = new Date().getTime();
var position = (typeof effect.options.queue == 'string') ? effect.options.queue:effect.options.queue.position;
switch(position){
case 'front':// move unstarted effects after this effect this.effects.findAll(function(e){
return e.state=='idle'}
).each( function(e){
e.startOn += effect.finishOn;
e.finishOn += effect.finishOn;
}
);
break;
case 'with-last':timestamp = this.effects.pluck('startOn').max() || timestamp;
break;
case 'end':// start effect after last queued effect has finished timestamp = this.effects.pluck('finishOn').max() || timestamp;
break;
}
effect.startOn += timestamp;
effect.finishOn += timestamp;
if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) this.effects.push(effect);
if(!this.interval) this.interval = setInterval(this.loop.bind(this),15);
}
,remove:function(effect){
this.effects = this.effects.reject(function(e){
return e==effect}
);
if(this.effects.length == 0){
clearInterval(this.interval);
this.interval = null;
}
}
,loop:function(){
var timePos = new Date().getTime();
for(var i=0,len=this.effects.length;
i<len;
i++) if(this.effects[i]) this.effects[i].loop(timePos);
}
}
);
Effect.Queues ={
instances:$H(),get:function(queueName){
if(typeof queueName != 'string') return queueName;
if(!this.instances[queueName]) this.instances[queueName] = new Effect.ScopedQueue();
return this.instances[queueName];
}
}
Effect.Queue = Effect.Queues.get('global');
Effect.DefaultOptions ={
transition:Effect.Transitions.sinoidal,duration:1.0,// seconds fps:60.0,// max. 60fps due to Effect.Queue implementation sync:false,// true for combining from:0.0,to:1.0,delay:0.0,queue:'parallel'}
Effect.Base = function(){
}
;
Effect.Base.prototype ={
position:null,start:function(options){
this.options = Object.extend(Object.extend({
}
,Effect.DefaultOptions),options ||{
}
);
this.currentFrame = 0;
this.state = 'idle';
this.startOn = this.options.delay*1000;
this.finishOn = this.startOn + (this.options.duration*1000);
this.event('beforeStart');
if(!this.options.sync) Effect.Queues.get(typeof this.options.queue == 'string' ? 'global':this.options.queue.scope).add(this);
}
,loop:function(timePos){
if(timePos >= this.startOn){
if(timePos >= this.finishOn){
this.render(1.0);
this.cancel();
this.event('beforeFinish');
if(this.finish) this.finish();
this.event('afterFinish');
return;
}
var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
var frame = Math.round(pos * this.options.fps * this.options.duration);
if(frame > this.currentFrame){
this.render(pos);
this.currentFrame = frame;
}
}
}
,render:function(pos){
if(this.state == 'idle'){
this.state = 'running';
this.event('beforeSetup');
if(this.setup) this.setup();
this.event('afterSetup');
}
if(this.state == 'running'){
if(this.options.transition) pos = this.options.transition(pos);
pos *= (this.options.to-this.options.from);
pos += this.options.from;
this.position = pos;
this.event('beforeUpdate');
if(this.update) this.update(pos);
this.event('afterUpdate');
}
}
,cancel:function(){
if(!this.options.sync) Effect.Queues.get(typeof this.options.queue == 'string' ? 'global':this.options.queue.scope).remove(this);
this.state = 'finished';
}
,event:function(eventName){
if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
if(this.options[eventName]) this.options[eventName](this);
}
,inspect:function(){
var data = $H();
for(property in this) if(typeof this[property] != 'function') data[property] = this[property];
return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
}
}
Effect.Parallel = Class.create();
Object.extend(Object.extend(Effect.Parallel.prototype,Effect.Base.prototype),{
initialize:function(effects){
this.effects = effects || [];
this.start(arguments[1]);
}
,update:function(position){
this.effects.invoke('render',position);
}
,finish:function(position){
this.effects.each( function(effect){
effect.render(1.0);
effect.cancel();
effect.event('beforeFinish');
if(effect.finish) effect.finish(position);
effect.event('afterFinish');
}
);
}
}
);
Effect.Event = Class.create();
Object.extend(Object.extend(Effect.Event.prototype,Effect.Base.prototype),{
initialize:function(){
var options = Object.extend({
duration:0}
,arguments[0] ||{
}
);
this.start(options);
}
,update:Prototype.emptyFunction}
);
Effect.Opacity = Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype,Effect.Base.prototype),{
initialize:function(element){
this.element = $(element);
if(!this.element) throw(Effect._elementDoesNotExistError);
// make this work on IE on elements without 'layout' if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) this.element.setStyle({
zoom:1}
);
var options = Object.extend({
from:this.element.getOpacity() || 0.0,to:1.0}
,arguments[1] ||{
}
);
this.start(options);
}
,update:function(position){
this.element.setOpacity(position);
}
}
);
Effect.Move = Class.create();
Object.extend(Object.extend(Effect.Move.prototype,Effect.Base.prototype),{
initialize:function(element){
this.element = $(element);
if(!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
x:0,y:0,mode:'relative'}
,arguments[1] ||{
}
);
this.start(options);
}
,setup:function(){
// Bug in Opera:Opera returns the "real" position of a static element or // relative element that does not have top/left explicitly set. // ==> Always set top and left for position relative elements in your stylesheets // (to 0 if you do not need them) this.element.makePositioned();
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
if(this.options.mode == 'absolute'){
// absolute movement,so we need to calc deltaX and deltaY this.options.x = this.options.x - this.originalLeft;
this.options.y = this.options.y - this.originalTop;
}
}
,update:function(position){
this.element.setStyle({
left:Math.round(this.options.x * position + this.originalLeft) + 'px',top:Math.round(this.options.y * position + this.originalTop) + 'px'}
);
}
}
);
// for backwards compatibilityEffect.MoveBy = function(element,toTop,toLeft){
return new Effect.Move(element,Object.extend({
x:toLeft,y:toTop}
,arguments[3] ||{
}
));
}
;
Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype,Effect.Base.prototype),{
initialize:function(element,percent){
this.element = $(element);
if(!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:'box',// 'box' or 'contents' or{
}
with provided values scaleFrom:100.0,scaleTo:percent}
,arguments[2] ||{
}
);
this.start(options);
}
,setup:function(){
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
this.elementPositioning = this.element.getStyle('position');
this.originalStyle ={
}
;
['top','left','width','height','fontSize'].each( function(k){
this.originalStyle[k] = this.element.style[k];
}
.bind(this));
this.originalTop = this.element.offsetTop;
this.originalLeft = this.element.offsetLeft;
var fontSize = this.element.getStyle('font-size') || '100%';
['em','px','%','pt'].each( function(fontSizeType){
if(fontSize.indexOf(fontSizeType)>0){
this.fontSize = parseFloat(fontSize);
this.fontSizeType = fontSizeType;
}
}
.bind(this));
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
this.dims = null;
if(this.options.scaleMode=='box') this.dims = [this.element.offsetHeight,this.element.offsetWidth];
if(/^content/.test(this.options.scaleMode)) this.dims = [this.element.scrollHeight,this.element.scrollWidth];
if(!this.dims) this.dims = [this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth];
}
,update:function(position){
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
if(this.options.scaleContent && this.fontSize) this.element.setStyle({
fontSize:this.fontSize * currentScale + this.fontSizeType}
);
this.setDimensions(this.dims[0] * currentScale,this.dims[1] * currentScale);
}
,finish:function(position){
if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
}
,setDimensions:function(height,width){
var d ={
}
;
if(this.options.scaleX) d.width = Math.round(width) + 'px';
if(this.options.scaleY) d.height = Math.round(height) + 'px';
if(this.options.scaleFromCenter){
var topd = (height - this.dims[0])/2;
var leftd = (width - this.dims[1])/2;
if(this.elementPositioning == 'absolute'){
if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
}
else{
if(this.options.scaleY) d.top = -topd + 'px';
if(this.options.scaleX) d.left = -leftd + 'px';
}
}
this.element.setStyle(d);
}
}
);
Effect.Highlight = Class.create();
Object.extend(Object.extend(Effect.Highlight.prototype,Effect.Base.prototype),{
initialize:function(element){
this.element = $(element);
if(!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
startcolor:'#ffff99'}
,arguments[1] ||{
}
);
this.start(options);
}
,setup:function(){
// Prevent executing on elements not in the layout flow if(this.element.getStyle('display')=='none'){
this.cancel();
return;
}
// Disable background image during the effect this.oldStyle ={
}
;
if (!this.options.keepBackgroundImage){
this.oldStyle.backgroundImage = this.element.getStyle('background-image');
this.element.setStyle({
backgroundImage:'none'}
);
}
if(!this.options.endcolor) this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
if(!this.options.restorecolor) this.options.restorecolor = this.element.getStyle('background-color');
// init color calculations this._base = $R(0,2).map(function(i){
return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16)}
.bind(this));
this._delta = $R(0,2).map(function(i){
return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i]}
.bind(this));
}
,update:function(position){
this.element.setStyle({
backgroundColor:$R(0,2).inject('#',function(m,v,i){
return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart());
}
.bind(this))}
);
}
,finish:function(){
this.element.setStyle(Object.extend(this.oldStyle,{
backgroundColor:this.options.restorecolor}
));
}
}
);
Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype,Effect.Base.prototype),{
initialize:function(element){
this.element = $(element);
this.start(arguments[1] ||{
}
);
}
,setup:function(){
Position.prepare();
var offsets = Position.cumulativeOffset(this.element);
if(this.options.offset) offsets[1] += this.options.offset;
var max = window.innerHeight ? window.height - window.innerHeight:document.body.scrollHeight - (document.documentElement.clientHeight ? document.documentElement.clientHeight:document.body.clientHeight);
this.scrollStart = Position.deltaY;
this.delta = (offsets[1] > max ? max:offsets[1]) - this.scrollStart;
}
,update:function(position){
Position.prepare();
window.scrollTo(Position.deltaX,this.scrollStart + (position*this.delta));
}
}
);
/* ------------- combination effects ------------- */
Effect.Fade = function(element){
element = $(element);
var oldOpacity = element.getInlineOpacity();
var options = Object.extend({
from:element.getOpacity() || 1.0,to:0.0,afterFinishInternal:function(effect){
if(effect.options.to!=0) return;
effect.element.hide().setStyle({
opacity:oldOpacity}
);
}
}
,arguments[1] ||{
}
);
return new Effect.Opacity(element,options);
}
Effect.Appear = function(element){
element = $(element);
var options = Object.extend({
from:(element.getStyle('display') == 'none' ? 0.0:element.getOpacity() || 0.0),to:1.0,// force Safari to render floated elements properly afterFinishInternal:function(effect){
effect.element.forceRerendering();
}
,beforeSetup:function(effect){
effect.element.setOpacity(effect.options.from).show();
}
}
,arguments[1] ||{
}
);
return new Effect.Opacity(element,options);
}
Effect.Puff = function(element){
element = $(element);
var oldStyle ={
opacity:element.getInlineOpacity(),position:element.getStyle('position'),top:element.style.top,left:element.style.left,width:element.style.width,height:element.style.height}
;
return new Effect.Parallel( [ new Effect.Scale(element,200,{
sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}
),new Effect.Opacity(element,{
sync:true,to:0.0}
) ],Object.extend({
duration:1.0,beforeSetupInternal:function(effect){
Position.absolutize(effect.effects[0].element)}
,afterFinishInternal:function(effect){
effect.effects[0].element.hide().setStyle(oldStyle);
}
}
,arguments[1] ||{
}
) );
}
Effect.BlindUp = function(element){
element = $(element);
element.makeClipping();
return new Effect.Scale(element,0,Object.extend({
scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(effect){
effect.element.hide().undoClipping();
}
}
,arguments[1] ||{
}
) );
}
Effect.BlindDown = function(element){
element = $(element);
var elementDimensions = element.getDimensions();
return new Effect.Scale(element,100,Object.extend({
scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{
originalHeight:elementDimensions.height,originalWidth:elementDimensions.width}
,restoreAfterFinish:true,afterSetup:function(effect){
effect.element.makeClipping().setStyle({
height:'0px'}
).show();
}
,afterFinishInternal:function(effect){
effect.element.undoClipping();
}
}
,arguments[1] ||{
}
));
}
Effect.SwitchOff = function(element){
element = $(element);
var oldOpacity = element.getInlineOpacity();
return new Effect.Appear(element,Object.extend({
duration:0.4,from:0,transition:Effect.Transitions.flicker,afterFinishInternal:function(effect){
new Effect.Scale(effect.element,1,{
duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetup:function(effect){
effect.element.makePositioned().makeClipping();
}
,afterFinishInternal:function(effect){
effect.element.hide().undoClipping().undoPositioned().setStyle({
opacity:oldOpacity}
);
}
}
)}
}
,arguments[1] ||{
}
));
}
Effect.DropOut = function(element){
element = $(element);
var oldStyle ={
top:element.getStyle('top'),left:element.getStyle('left'),opacity:element.getInlineOpacity()}
;
return new Effect.Parallel( [ new Effect.Move(element,{
x:0,y:100,sync:true}
),new Effect.Opacity(element,{
sync:true,to:0.0}
) ],Object.extend({
duration:0.5,beforeSetup:function(effect){
effect.effects[0].element.makePositioned();
}
,afterFinishInternal:function(effect){
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
}
}
,arguments[1] ||{
}
));
}
Effect.Shake = function(element){
element = $(element);
var oldStyle ={
top:element.getStyle('top'),left:element.getStyle('left')}
;
return new Effect.Move(element,{
x:20,y:0,duration:0.05,afterFinishInternal:function(effect){
new Effect.Move(effect.element,{
x:-40,y:0,duration:0.1,afterFinishInternal:function(effect){
new Effect.Move(effect.element,{
x:40,y:0,duration:0.1,afterFinishInternal:function(effect){
new Effect.Move(effect.element,{
x:-40,y:0,duration:0.1,afterFinishInternal:function(effect){
new Effect.Move(effect.element,{
x:40,y:0,duration:0.1,afterFinishInternal:function(effect){
new Effect.Move(effect.element,{
x:-20,y:0,duration:0.05,afterFinishInternal:function(effect){
effect.element.undoPositioned().setStyle(oldStyle);
}
}
)}
}
)}
}
)}
}
)}
}
)}
}
);
}
Effect.SlideDown = function(element){
element = $(element).cleanWhitespace();
// SlideDown need to have the content of the element wrapped in a container element with fixed height! var oldInnerBottom = element.down().getStyle('bottom');
var elementDimensions = element.getDimensions();
return new Effect.Scale(element,100,Object.extend({
scaleContent:false,scaleX:false,scaleFrom:window.opera ? 0:1,scaleMode:{
originalHeight:elementDimensions.height,originalWidth:elementDimensions.width}
,restoreAfterFinish:true,afterSetup:function(effect){
effect.element.makePositioned();
effect.element.down().makePositioned();
if(window.opera) effect.element.setStyle({
top:''}
);
effect.element.makeClipping().setStyle({
height:'0px'}
).show();
}
,afterUpdateInternal:function(effect){
effect.element.down().setStyle({
bottom:(effect.dims[0] - effect.element.clientHeight) + 'px'}
);
}
,afterFinishInternal:function(effect){
effect.element.undoClipping().undoPositioned();
effect.element.down().undoPositioned().setStyle({
bottom:oldInnerBottom}
);
}
}
,arguments[1] ||{
}
) );
}
Effect.SlideUp = function(element){
element = $(element).cleanWhitespace();
var oldInnerBottom = element.down().getStyle('bottom');
return new Effect.Scale(element,window.opera ? 0:1,Object.extend({
scaleContent:false,scaleX:false,scaleMode:'box',scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(effect){
effect.element.makePositioned();
effect.element.down().makePositioned();
if(window.opera) effect.element.setStyle({
top:''}
);
effect.element.makeClipping().show();
}
,afterUpdateInternal:function(effect){
effect.element.down().setStyle({
bottom:(effect.dims[0] - effect.element.clientHeight) + 'px'}
);
}
,afterFinishInternal:function(effect){
effect.element.hide().undoClipping().undoPositioned().setStyle({
bottom:oldInnerBottom}
);
effect.element.down().undoPositioned();
}
}
,arguments[1] ||{
}
) );
}
// Bug in opera makes the TD containing this element expand for a instance after finishEffect.Squish = function(element){
return new Effect.Scale(element,window.opera ? 1:0,{
restoreAfterFinish:true,beforeSetup:function(effect){
effect.element.makeClipping();
}
,afterFinishInternal:function(effect){
effect.element.hide().undoClipping();
}
}
);
}
Effect.Grow = function(element){
element = $(element);
var options = Object.extend({
direction:'center',moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.full}
,arguments[1] ||{
}
);
var oldStyle ={
top:element.style.top,left:element.style.left,height:element.style.height,width:element.style.width,opacity:element.getInlineOpacity()}
;
var dims = element.getDimensions();
var initialMoveX,initialMoveY;
var moveX,moveY;
switch (options.direction){
case 'top-left':initialMoveX = initialMoveY = moveX = moveY = 0;
break;
case 'top-right':initialMoveX = dims.width;
initialMoveY = moveY = 0;
moveX = -dims.width;
break;
case 'bottom-left':initialMoveX = moveX = 0;
initialMoveY = dims.height;
moveY = -dims.height;
break;
case 'bottom-right':initialMoveX = dims.width;
initialMoveY = dims.height;
moveX = -dims.width;
moveY = -dims.height;
break;
case 'center':initialMoveX = dims.width / 2;
initialMoveY = dims.height / 2;
moveX = -dims.width / 2;
moveY = -dims.height / 2;
break;
}
return new Effect.Move(element,{
x:initialMoveX,y:initialMoveY,duration:0.01,beforeSetup:function(effect){
effect.element.hide().makeClipping().makePositioned();
}
,afterFinishInternal:function(effect){
new Effect.Parallel( [ new Effect.Opacity(effect.element,{
sync:true,to:1.0,from:0.0,transition:options.opacityTransition}
),new Effect.Move(effect.element,{
x:moveX,y:moveY,sync:true,transition:options.moveTransition}
),new Effect.Scale(effect.element,100,{
scaleMode:{
originalHeight:dims.height,originalWidth:dims.width}
,sync:true,scaleFrom:window.opera ? 1:0,transition:options.scaleTransition,restoreAfterFinish:true}
) ],Object.extend({
beforeSetup:function(effect){
effect.effects[0].element.setStyle({
height:'0px'}
).show();
}
,afterFinishInternal:function(effect){
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
}
}
,options) )}
}
);
}
Effect.Shrink = function(element){
element = $(element);
var options = Object.extend({
direction:'center',moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.none}
,arguments[1] ||{
}
);
var oldStyle ={
top:element.style.top,left:element.style.left,height:element.style.height,width:element.style.width,opacity:element.getInlineOpacity()}
;
var dims = element.getDimensions();
var moveX,moveY;
switch (options.direction){
case 'top-left':moveX = moveY = 0;
break;
case 'top-right':moveX = dims.width;
moveY = 0;
break;
case 'bottom-left':moveX = 0;
moveY = dims.height;
break;
case 'bottom-right':moveX = dims.width;
moveY = dims.height;
break;
case 'center':moveX = dims.width / 2;
moveY = dims.height / 2;
break;
}
return new Effect.Parallel( [ new Effect.Opacity(element,{
sync:true,to:0.0,from:1.0,transition:options.opacityTransition}
),new Effect.Scale(element,window.opera ? 1:0,{
sync:true,transition:options.scaleTransition,restoreAfterFinish:true}
),new Effect.Move(element,{
x:moveX,y:moveY,sync:true,transition:options.moveTransition}
) ],Object.extend({
beforeStartInternal:function(effect){
effect.effects[0].element.makePositioned().makeClipping();
}
,afterFinishInternal:function(effect){
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle);
}
}
,options) );
}
Effect.Pulsate = function(element){
element = $(element);
var options = arguments[1] ||{
}
;
var oldOpacity = element.getInlineOpacity();
var transition = options.transition || Effect.Transitions.sinoidal;
var reverser = function(pos){
return transition(1-Effect.Transitions.pulse(pos,options.pulses))}
;
reverser.bind(transition);
return new Effect.Opacity(element,Object.extend(Object.extend({
duration:2.0,from:0,afterFinishInternal:function(effect){
effect.element.setStyle({
opacity:oldOpacity}
);
}
}
,options),{
transition:reverser}
));
}
Effect.Fold = function(element){
element = $(element);
var oldStyle ={
top:element.style.top,left:element.style.left,width:element.style.width,height:element.style.height}
;
element.makeClipping();
return new Effect.Scale(element,5,Object.extend({
scaleContent:false,scaleX:false,afterFinishInternal:function(effect){
new Effect.Scale(element,1,{
scaleContent:false,scaleY:false,afterFinishInternal:function(effect){
effect.element.hide().undoClipping().setStyle(oldStyle);
}
}
);
}
}
,arguments[1] ||{
}
));
}
;
Effect.Morph = Class.create();
Object.extend(Object.extend(Effect.Morph.prototype,Effect.Base.prototype),{
initialize:function(element){
this.element = $(element);
if(!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
style:{
}
}
,arguments[1] ||{
}
);
if (typeof options.style == 'string'){
if(options.style.indexOf(':') == -1){
var cssText = '',selector = '.' + options.style;
$A(document.styleSheets).reverse().each(function(styleSheet){
if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
else if (styleSheet.rules) cssRules = styleSheet.rules;
$A(cssRules).reverse().each(function(rule){
if (selector == rule.selectorText){
cssText = rule.style.cssText;
throw $break;
}
}
);
if (cssText) throw $break;
}
);
this.style = cssText.parseStyle();
options.afterFinishInternal = function(effect){
effect.element.addClassName(effect.options.style);
effect.transforms.each(function(transform){
if(transform.style != 'opacity') effect.element.style[transform.style.camelize()] = '';
}
);
}
}
else this.style = options.style.parseStyle();
}
else this.style = $H(options.style) this.start(options);
}
,setup:function(){
function parseColor(color){
if(!color || ['rgba(0,0,0,0)','transparent'].include(color)) color = '#ffffff';
color = color.parseColor();
return $R(0,2).map(function(i){
return parseInt( color.slice(i*2+1,i*2+3),16 )}
);
}
this.transforms = this.style.map(function(pair){
var property = pair[0].underscore().dasherize(),value = pair[1],unit = null;
if(value.parseColor('#zzzzzz') != '#zzzzzz'){
value = value.parseColor();
unit = 'color';
}
else if(property == 'opacity'){
value = parseFloat(value);
if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) this.element.setStyle({
zoom:1}
);
}
else if(Element.CSS_LENGTH.test(value)) var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/),value = parseFloat(components[1]),unit = (components.length == 3) ? components[2]:null;
var originalValue = this.element.getStyle(property);
return $H({
style:property,originalValue:unit=='color' ? parseColor(originalValue):parseFloat(originalValue || 0),targetValue:unit=='color' ? parseColor(value):value,unit:unit}
);
}
.bind(this)).reject(function(transform){
return ( (transform.originalValue == transform.targetValue) || ( transform.unit != 'color' && (isNaN(transform.originalValue) || isNaN(transform.targetValue)) ) )}
);
}
,update:function(position){
var style = $H(),value = null;
this.transforms.each(function(transform){
value = transform.unit=='color' ? $R(0,2).inject('#',function(m,v,i){
return m+(Math.round(transform.originalValue[i]+ (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart()}
):transform.originalValue + Math.round( ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
style[transform.style] = value;
}
);
this.element.setStyle(style);
}
}
);
Effect.Transform = Class.create();
Object.extend(Effect.Transform.prototype,{
initialize:function(tracks){
this.tracks = [];
this.options = arguments[1] ||{
}
;
this.addTracks(tracks);
}
,addTracks:function(tracks){
tracks.each(function(track){
var data = $H(track).values().first();
this.tracks.push($H({
ids:$H(track).keys().first(),effect:Effect.Morph,options:{
style:data}
}
));
}
.bind(this));
return this;
}
,play:function(){
return new Effect.Parallel( this.tracks.map(function(track){
var elements = [$(track.ids) || $$(track.ids)].flatten();
return elements.map(function(e){
return new track.effect(e,Object.extend({
sync:true}
,track.options))}
);
}
).flatten(),this.options );
}
}
);
Element.CSS_PROPERTIES = $w( 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + 'fontSize fontWeight height left letterSpacing lineHeight ' + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + 'right textIndent top width wordSpacing zIndex');
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
String.prototype.parseStyle = function(){
var element = Element.extend(document.createElement('div'));
element.innerHTML = '<div style="' + this + '"></div>';
var style = element.down().style,styleRules = $H();
Element.CSS_PROPERTIES.each(function(property){
if(style[property]) styleRules[property] = style[property];
}
);
if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1){
styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
}
return styleRules;
}
;
Element.morph = function(element,style){
new Effect.Morph(element,Object.extend({
style:style}
,arguments[2] ||{
}
));
return element;
}
;
['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom','collectTextNodes','collectTextNodesIgnoreClass','morph'].each( function(f){
Element.Methods[f] = Element[f];
}
);
Element.Methods.visualEffect = function(element,effect,options){
s = effect.gsub(/_/,'-').camelize();
effect_class = s.charAt(0).toUpperCase() + s.substring(1);
new Effect[effect_class](element,options);
return $(element);
}
;
Element.addMethods();
CSS代码(default.css):
/*Yes this layout was inspired by lightbox v2.0's page,the reason being,the layout works really well for a doc*/
*,html,body{margin:0 0 0 0;padding:0 0 0 0;}
html{height:100%;}
body{background:#171b20;color:#ffffff;font-family:'Lucida Grande',Verdana,Arial;font-size:12px;height:100%;}
h1{color:#96BF55;font-size:20px;font-weight:normal;margin:5px 0 5px 0;text-align:left;}
h1 span{color:#ffffff;font-size:20px;font-weight:normal;margin:5px 5px 5px 0;text-align:left;}
.description{font-size:12px;line-height:18px;color:#ffffbe;padding:5px 0 15px 0;}
#container{margin:20px auto 0 auto;width:700px;}
#top_container{width:680px;height:130px;margin:10px auto 10px auto;}
#bottom_container{clear:both;width:700px;}
.page-top{position:fixed;top:0;left:0;width:100%;height:10px;background-color:#09f;border-bottom:5px solid #444444;}
.page-sidebar{position:fixed;top:30px;left:20px;width:250px;}
* html .page-sidebar{top:30px;left:20px;width:250px;position:absolute;}
.page-title{margin:0;padding:0 0 10px 0;text-align:left;}
.page-title h1{margin:0 0 5px 0;}
.page-title h2{clear:both;font-size:100%;color:#FF9;font-weight:normal;margin:0;}
.page-body{margin:0 10% 0 315px;width:600px;padding:30px 0 20px 0;text-align:left;}
.page-footer{margin:20px 0 0 0;text-align:left;font-size:10px;}
.page-body ul,.page-body ol{color:#ffffff;margin:10px 0 30px 25px;}
.page-body ul li,.page-body ol li{padding:0;margin:0 0 5px 0;color:#cccccc;line-height:140%;font-size:100%;}
.page-footer p{margin:0;}
.page-title h1 span{text-align:left;font-weight:normal;font-size:100%;color:#ffffff;margin:5px 0 15px 0;}
a,a:link,a:visited{color:#09f;}
h2{text-align:left;font-weight:normal;font-size:150%;color:#09f;margin:5px 0 15px 0;}
h2 span{clear:both;font-size:70%;color:#FF9;}
.notice{border:3px solid #ffffbe;padding:10px;color:#ffffff;background-color:#09f;margin:0 0 20px 0;}
.notice p,.notice p a,li a{color:#ffffff;text-decoration:none;}
.navigation{list-style:none;margin:10px 0 30px 0;width:200px;}
.navigation li{padding:0;margin:0;}
.navigation a,.navigation a:visited{display:block;height:25px;line-height:25px;padding:0 10px 0 10px;border-bottom:3px solid #171B20;color:#ffffff;background-color:#333333;text-decoration:none;}
.navigation a:hover{color:#000000;background-color:#a9d06a;}
a.page-options{color:#000000;text-decoration:none;display:block;text-align:left;padding:5px;background:#a9d06a;margin:3px 0 0 0;border-bottom:1px solid #333333;border-bottom:1px solid #555555;}
a.page-options:hover,a.page-options:focus{color:#fff;background:#09F;}
p small,li small{color:#09F;font-size:100%;}
p em,em{color:#ffffff;}
.hidden{display:none;}
pre{font-size:11px;padding:10px;background:#000000;overflow:auto;margin:10px 0 10px 0;}
code{color:#ffffff;background:#000000;font-family:Monaco,Courier,monotype;}
/** RUBY / JAVASCRIPT **/
code span.comment{color:#BD48B3;}
code span.string{color:#99FF00;}
code span.brackets{}
code span.symbol{color:#6BCFF7;}
code span.keywords{color:#FF8400;}
code span.erb{background:#333;}
code span.symbol{color:#07DFFC;}
/** HTML **/
code.html span.tag{color:#fff;}
code.html span.attribute{color:#FFD500;}
code.html span.string{color:#99FF00;}
code.html span.comment{color:#999;}
code.html span.doctype{color:#D7FF80;}
/* CSS Document */