String.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 (Prototype.Browser.WebKit) window.scrollBy(0,0); return element;}; 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) { }
}; var Effect = { _elementDoesNotExistError: { name: 'ElementDoesNotExistError', message: 'The specified DOM element does not exist, but is required for this effect to operate'
}, 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) { var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; return pos > 1 ? 1 : pos;}, wobble: function(pos) { return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;}, pulse: function(pos, pulses) { pulses = pulses || 5; return ( ((pos % (1/pulses)) * pulses).round() == 0 ?
((pos * pulses * 2) - (pos * pulses * 2).floor()) :
1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) );}, spring: function(pos) { return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));}, none: function(pos) { return 0;}, full: function(pos) { return 1;}
}, DefaultOptions: { duration: 1.0, fps: 100, sync: false, from: 0.0, to: 1.0, delay: 0.0, queue: 'parallel'
}, tagifyText: function(element) { var tagifyStyle = 'position:relative'; if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; element = $(element); $A(element.childNodes).each( function(child) { if (child.nodeType==3) { child.nodeValue.toArray().each( function(character) { element.insertBefore( new Element('span', {style: tagifyStyle}).update( character == ' ' ? String.fromCharCode(160) : character), child);}); Element.remove(child);}
});}, multiple: function(element, effect) { var elements; if (((typeof element == 'object') || Object.isFunction(element)) &&
(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);}
}; Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; Effect.ScopedQueue = Class.create(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 = Object.isString(effect.options.queue) ?
effect.options.queue : effect.options.queue.position; switch(position) { case 'front':
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':
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++)
this.effects[i] && this.effects[i].loop(timePos);}
}); Effect.Queues = { instances: $H(), get: function(queueName) { if (!Object.isString(queueName)) return queueName; return this.instances.get(queueName) || this.instances.set(queueName, new Effect.ScopedQueue());}
}; Effect.Queue = Effect.Queues.get('global'); Effect.Base = Class.create({ position: null, start: function(options) { function codeForEvent(options,eventName){ return ( (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + (options[eventName] ? 'this.options.'+eventName+'(this);' : '') );}
if (options && options.transition === false) options.transition = Effect.Transitions.linear; 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.fromToDelta = this.options.to-this.options.from; this.totalTime = this.finishOn-this.startOn; this.totalFrames = this.options.fps*this.options.duration; eval('this.render = function(pos){ '+ 'if (this.state=="idle"){this.state="running";'+ codeForEvent(this.options,'beforeSetup')+ (this.setup ? 'this.setup();':'')+ codeForEvent(this.options,'afterSetup')+ '};if (this.state=="running"){'+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ 'this.position=pos;'+ codeForEvent(this.options,'beforeUpdate')+ (this.update ? 'this.update(pos);':'')+ codeForEvent(this.options,'afterUpdate')+ '}}'); this.event('beforeStart'); if (!this.options.sync)
Effect.Queues.get(Object.isString(this.options.queue) ?
'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.totalTime, frame = (pos * this.totalFrames).round(); if (frame > this.currentFrame) { this.render(pos); this.currentFrame = frame;}
}
}, cancel: function() { if (!this.options.sync)
Effect.Queues.get(Object.isString(this.options.queue) ?
'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 (!Object.isFunction(this[property])) data.set(property, this[property]); return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';}
}); Effect.Parallel = Class.create(Effect.Base, { 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.Tween = Class.create(Effect.Base, { initialize: function(object, from, to) { object = Object.isString(object) ? $(object) : object; var args = $A(arguments), method = args.last(), options = args.length == 5 ? args[3] : null; this.method = Object.isFunction(method) ? method.bind(object) :
Object.isFunction(object[method]) ? object[method].bind(object) :
function(value) { object[method] = value }; this.start(Object.extend({ from: from, to: to }, options || { }));}, update: function(position) { this.method(position);}
}); Effect.Event = Class.create(Effect.Base, { initialize: function() { this.start(Object.extend({ duration: 0 }, arguments[0] || { }));}, update: Prototype.emptyFunction
}); Effect.Opacity = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); if (Prototype.Browser.IE && (!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(Effect.Base, { 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() { this.element.makePositioned(); this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); this.originalTop = parseFloat(this.element.getStyle('top') || '0'); if (this.options.mode == 'absolute') { this.options.x = this.options.x - this.originalLeft; this.options.y = this.options.y - this.originalTop;}
}, update: function(position) { this.element.setStyle({ left: (this.options.x * position + this.originalLeft).round() + 'px', top: (this.options.y * position + this.originalTop).round() + 'px'
});}
}); Effect.MoveBy = function(element, toTop, toLeft) { return new Effect.Move(element, Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));}; Effect.Scale = Class.create(Effect.Base, { 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', 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 = width.round() + 'px'; if (this.options.scaleY) d.height = height.round() + '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(Effect.Base, { 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() { if (this.element.getStyle('display')=='none') { this.cancel(); return;}
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'); 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+((this._base[i]+(this._delta[i]*position)).round().toColorPart());}.bind(this)) });}, finish: function() { this.element.setStyle(Object.extend(this.oldStyle, { backgroundColor: this.options.restorecolor
}));}
}); Effect.ScrollTo = function(element) { var options = arguments[1] || { }, scrollOffsets = document.viewport.getScrollOffsets(), elementOffsets = $(element).cumulativeOffset(), max = (window.height || document.body.scrollHeight) - document.viewport.getHeight(); if (options.offset) elementOffsets[1] += options.offset; return new Effect.Tween(null, scrollOffsets.top, elementOffsets[1] > max ? max : elementOffsets[1], options, function(p){ scrollTo(scrollOffsets.left, p.round()) } );}; 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, 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 options = Object.extend({ distance: 20, duration: 0.5
}, arguments[1] || {}); var distance = parseFloat(options.distance); var split = parseFloat(options.duration) / 10.0; var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left') }; return new Effect.Move(element, { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { effect.element.undoPositioned().setStyle(oldStyle);}}) }}) }}) }}) }}) }});}; Effect.SlideDown = function(element) { element = $(element).cleanWhitespace(); 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'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'box', scaleFrom: 100, 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().show();}, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom:
(effect.dims[0] - effect.element.clientHeight) + 'px' });}, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});}
}, arguments[1] || { }) );}; Effect.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(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ style: { }
}, arguments[1] || { }); if (!Object.isString(options.style)) this.style = $H(options.style); else { if (options.style.include(':'))
this.style = options.style.parseStyle(); else { this.element.addClassName(options.style); this.style = $H(this.element.getStyles()); this.element.removeClassName(options.style); var css = this.element.getStyles(); this.style = this.style.reject(function(style) { return style.value == css[style.key];}); options.afterFinishInternal = function(effect) { effect.element.addClassName(effect.options.style); effect.transforms.each(function(transform) { effect.element.style[transform.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], value = pair[1], unit = null; if (value.parseColor('#zzzzzz') != '#zzzzzz') { value = value.parseColor(); unit = 'color';} else if (property == 'opacity') { value = parseFloat(value); if (Prototype.Browser.IE && (!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 { style: property.camelize(), 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 = { }, transform, i = this.transforms.length; while(i--)
style[(transform = this.transforms[i]).style] = transform.unit=='color' ? '#'+ (Math.round(transform.originalValue[0]+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + (Math.round(transform.originalValue[1]+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + (Math.round(transform.originalValue[2]+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
(transform.originalValue + (transform.targetValue - transform.originalValue) * position).toFixed(3) + (transform.unit === null ? '' : transform.unit); this.element.setStyle(style, true);}
}); Effect.Transform = Class.create({ initialize: function(tracks){ this.tracks = []; this.options = arguments[1] || { }; this.addTracks(tracks);}, addTracks: function(tracks){ tracks.each(function(track){ track = $H(track); var data = track.values().first(); this.tracks.push($H({ ids: 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 ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); var elements = [$(ids) || $$(ids)].flatten(); return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, 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.__parseStyleElement = document.createElement('div'); String.prototype.parseStyle = function(){ var style, styleRules = $H(); if (Prototype.Browser.WebKit)
style = new Element('div',{style:this}).style; else { String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; style = String.__parseStyleElement.childNodes[0].style;}
Element.CSS_PROPERTIES.each(function(property){ if (style[property]) styleRules.set(property, style[property]);}); if (Prototype.Browser.IE && this.include('opacity'))
styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); return styleRules;}; if (document.defaultView && document.defaultView.getComputedStyle) { Element.getStyles = function(element) { var css = document.defaultView.getComputedStyle($(element), null); return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { styles[property] = css[property]; return styles;});};} else { Element.getStyles = function(element) { element = $(element); var css = element.currentStyle, styles; styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { results[property] = css[property]; return results;}); if (!styles.opacity) styles.opacity = element.getOpacity(); return styles;};}; Effect.Methods = { morph: function(element, style) { element = $(element); new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); return element;}, visualEffect: function(element, effect, options) { element = $(element)
var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); new Effect[klass](element, options); return element;}, highlight: function(element, options) { element = $(element); new Effect.Highlight(element, options); return element;}
}; $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ 'pulsate shake puff squish switchOff dropOut').each( function(effect) { Effect.Methods[effect] = function(element, options){ element = $(element); Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); return element;}
} ); $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( function(f) { Effect.Methods[f] = Element[f];} ); Element.addMethods(Effect.Methods); if(Object.isUndefined(Effect))
throw("dragdrop.js requires including script.aculo.us' effects.js library"); var Droppables = { drops: [], remove: function(element) { this.drops = this.drops.reject(function(d) { return d.element==$(element) });}, add: function(element) { element = $(element); var options = Object.extend({ greedy: true, hoverclass: null, tree: false
}, arguments[1] || { }); if(options.containment) { options._containers = []; var containment = options.containment; if(Object.isArray(containment)) { containment.each( function(c) { options._containers.push($(c)) });} else { options._containers.push($(containment));}
}
if(options.accept) options.accept = [options.accept].flatten(); Element.makePositioned(element); options.element = element; this.drops.push(options);}, findDeepestChild: function(drops) { deepest = drops[0]; for (i = 1; i < drops.length; ++i)
if (Element.isParent(drops[i].element, deepest.element))
deepest = drops[i]; return deepest;}, isContained: function(element, drop) { var containmentNode; if(drop.tree) { containmentNode = element.treeNode;} else { containmentNode = element.parentNode;}
return drop._containers.detect(function(c) { return containmentNode == c });}, isAffected: function(point, element, drop) { return ( (drop.element!=element) &&
((!drop._containers) || this.isContained(element, drop)) &&
((!drop.accept) || (Element.classNames(element).detect( function(v) { return drop.accept.include(v) } ) )) &&
Position.within(drop.element, point[0], point[1]) );}, deactivate: function(drop) { if(drop.hoverclass)
Element.removeClassName(drop.element, drop.hoverclass); this.last_active = null;}, activate: function(drop) { if(drop.hoverclass)
Element.addClassName(drop.element, drop.hoverclass); this.last_active = drop;}, show: function(point, element) { if(!this.drops.length) return; var drop, affected = []; this.drops.each( function(drop) { if(Droppables.isAffected(point, element, drop))
affected.push(drop);}); if(affected.length>0)
drop = Droppables.findDeepestChild(affected); if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); if (drop) { Position.within(drop.element, point[0], point[1]); if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); if (drop != this.last_active) Droppables.activate(drop);}
}, fire: function(event, element) { if(!this.last_active) return; Position.prepare(); if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
if (this.last_active.onDrop) { this.last_active.onDrop(element, this.last_active.element, event); return true;}
}, reset: function() { if(this.last_active)
this.deactivate(this.last_active);}
}
var Draggables = { drags: [], observers: [], register: function(draggable) { if(this.drags.length == 0) { this.eventMouseUp = this.endDrag.bindAsEventListener(this); this.eventMouseMove = this.updateDrag.bindAsEventListener(this); this.eventKeypress = this.keyPress.bindAsEventListener(this); Event.observe(document, "mouseup", this.eventMouseUp); Event.observe(document, "mousemove", this.eventMouseMove); Event.observe(document, "keypress", this.eventKeypress);}
this.drags.push(draggable);}, unregister: function(draggable) { this.drags = this.drags.reject(function(d) { return d==draggable }); if(this.drags.length == 0) { Event.stopObserving(document, "mouseup", this.eventMouseUp); Event.stopObserving(document, "mousemove", this.eventMouseMove); Event.stopObserving(document, "keypress", this.eventKeypress);}
}, activate: function(draggable) { if(draggable.options.delay) { this._timeout = setTimeout(function() { Draggables._timeout = null; window.focus(); Draggables.activeDraggable = draggable;}.bind(this), draggable.options.delay);} else { window.focus(); this.activeDraggable = draggable;}
}, deactivate: function() { this.activeDraggable = null;}, updateDrag: function(event) { if(!this.activeDraggable) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; this._lastPointer = pointer; this.activeDraggable.updateDrag(event, pointer);}, endDrag: function(event) { if(this._timeout) { clearTimeout(this._timeout); this._timeout = null;}
if(!this.activeDraggable) return; this._lastPointer = null; this.activeDraggable.endDrag(event); this.activeDraggable = null;}, keyPress: function(event) { if(this.activeDraggable)
this.activeDraggable.keyPress(event);}, addObserver: function(observer) { this.observers.push(observer); this._cacheObserverCallbacks();}, removeObserver: function(element) { this.observers = this.observers.reject( function(o) { return o.element==element }); this._cacheObserverCallbacks();}, notify: function(eventName, draggable, event) { if(this[eventName+'Count'] > 0)
this.observers.each( function(o) { if(o[eventName]) o[eventName](eventName, draggable, event);}); if(draggable.options[eventName]) draggable.options[eventName](draggable, event);}, _cacheObserverCallbacks: function() { ['onStart','onEnd','onDrag'].each( function(eventName) { Draggables[eventName+'Count'] = Draggables.observers.select( function(o) { return o[eventName];} ).length;});}
}
var Draggable = Class.create({ initialize: function(element) { var defaults = { handle: false, reverteffect: function(element, top_offset, left_offset) { var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, queue: {scope:'_draggable', position:'end'}
});}, endeffect: function(element) { var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, queue: {scope:'_draggable', position:'end'}, afterFinish: function(){ Draggable._dragging[element] = false
}
});}, zindex: 1000, revert: false, quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, snap: false, delay: 0
}; if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
Object.extend(defaults, { starteffect: function(element) { element._opacity = Element.getOpacity(element); Draggable._dragging[element] = true; new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});}
}); var options = Object.extend(defaults, arguments[1] || { }); this.element = $(element); if(options.handle && Object.isString(options.handle))
this.handle = this.element.down('.'+options.handle, 0); if(!this.handle) this.handle = $(options.handle); if(!this.handle) this.handle = this.element; if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { options.scroll = $(options.scroll); this._isScrollChild = Element.childOf(this.element, options.scroll);}
Element.makePositioned(this.element); this.options = options; this.dragging = false; this.eventMouseDown = this.initDrag.bindAsEventListener(this); Event.observe(this.handle, "mousedown", this.eventMouseDown); Draggables.register(this);}, destroy: function() { Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); Draggables.unregister(this);}, currentDelta: function() { return([ parseInt(Element.getStyle(this.element,'left') || '0'), parseInt(Element.getStyle(this.element,'top') || '0')]);}, initDrag: function(event) { if(!Object.isUndefined(Draggable._dragging[this.element]) &&
Draggable._dragging[this.element]) return; if(Event.isLeftClick(event)) { var src = Event.element(event); if((tag_name = src.tagName.toUpperCase()) && ( tag_name=='INPUT' || tag_name=='SELECT' || tag_name=='OPTION' || tag_name=='BUTTON' || tag_name=='TEXTAREA')) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; var pos = Position.cumulativeOffset(this.element); this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); Draggables.activate(this); Event.stop(event);}
}, startDrag: function(event) { this.dragging = true; if(!this.delta)
this.delta = this.currentDelta(); if(this.options.zindex) { this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); this.element.style.zIndex = this.options.zindex;}
if(this.options.ghosting) { this._clone = this.element.cloneNode(true); this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); if (!this.element._originallyAbsolute)
Position.absolutize(this.element); this.element.parentNode.insertBefore(this._clone, this.element);}
if(this.options.scroll) { if (this.options.scroll == window) { var where = this._getWindowScroll(this.options.scroll); this.originalScrollLeft = where.left; this.originalScrollTop = where.top;} else { this.originalScrollLeft = this.options.scroll.scrollLeft; this.originalScrollTop = this.options.scroll.scrollTop;}
}
Draggables.notify('onStart', this, event); if(this.options.starteffect) this.options.starteffect(this.element);}, updateDrag: function(event, pointer) { if(!this.dragging) this.startDrag(event); if(!this.options.quiet){ Position.prepare(); Droppables.show(pointer, this.element);}
Draggables.notify('onDrag', this, event); this.draw(pointer); if(this.options.change) this.options.change(this); if(this.options.scroll) { this.stopScrolling(); var p; if (this.options.scroll == window) { with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ];}
} else { p = Position.page(this.options.scroll); p[0] += this.options.scroll.scrollLeft + Position.deltaX; p[1] += this.options.scroll.scrollTop + Position.deltaY; p.push(p[0]+this.options.scroll.offsetWidth); p.push(p[1]+this.options.scroll.offsetHeight);}
var speed = [0,0]; if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); this.startScrolling(speed);}
if(Prototype.Browser.WebKit) window.scrollBy(0,0); Event.stop(event);}, finishDrag: function(event, success) { this.dragging = false; if(this.options.quiet){ Position.prepare(); var pointer = [Event.pointerX(event), Event.pointerY(event)]; Droppables.show(pointer, this.element);}
if(this.options.ghosting) { if (!this.element._originallyAbsolute)
Position.relativize(this.element); delete this.element._originallyAbsolute; Element.remove(this._clone); this._clone = null;}
var dropped = false; if(success) { dropped = Droppables.fire(event, this.element); if (!dropped) dropped = false;}
if(dropped && this.options.onDropped) this.options.onDropped(this.element); Draggables.notify('onEnd', this, event); var revert = this.options.revert; if(revert && Object.isFunction(revert)) revert = revert(this.element); var d = this.currentDelta(); if(revert && this.options.reverteffect) { if (dropped == 0 || revert != 'failure')
this.options.reverteffect(this.element, d[1]-this.delta[1], d[0]-this.delta[0]);} else { this.delta = d;}
if(this.options.zindex)
this.element.style.zIndex = this.originalZ; if(this.options.endeffect)
this.options.endeffect(this.element); Draggables.deactivate(this); Droppables.reset();}, keyPress: function(event) { if(event.keyCode!=Event.KEY_ESC) return; this.finishDrag(event, false); Event.stop(event);}, endDrag: function(event) { if(!this.dragging) return; this.stopScrolling(); this.finishDrag(event, true); Event.stop(event);}, draw: function(point) { var pos = Position.cumulativeOffset(this.element); if(this.options.ghosting) { var r = Position.realOffset(this.element); pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;}
var d = this.currentDelta(); pos[0] -= d[0]; pos[1] -= d[1]; if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;}
var p = [0,1].map(function(i){ return (point[i]-pos[i]-this.offset[i])
}.bind(this)); if(this.options.snap) { if(Object.isFunction(this.options.snap)) { p = this.options.snap(p[0],p[1],this);} else { if(Object.isArray(this.options.snap)) { p = p.map( function(v, i) { return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
} else { p = p.map( function(v) { return (v/this.options.snap).round()*this.options.snap }.bind(this))
}
}}
var style = this.element.style; if((!this.options.constraint) || (this.options.constraint=='horizontal'))
style.left = p[0] + "px"; if((!this.options.constraint) || (this.options.constraint=='vertical'))
style.top = p[1] + "px"; if(style.visibility=="hidden") style.visibility = "";}, stopScrolling: function() { if(this.scrollInterval) { clearInterval(this.scrollInterval); this.scrollInterval = null; Draggables._lastScrollPointer = null;}
}, startScrolling: function(speed) { if(!(speed[0] || speed[1])) return; this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; this.lastScrolled = new Date(); this.scrollInterval = setInterval(this.scroll.bind(this), 10);}, scroll: function() { var current = new Date(); var delta = current - this.lastScrolled; this.lastScrolled = current; if(this.options.scroll == window) { with (this._getWindowScroll(this.options.scroll)) { if (this.scrollSpeed[0] || this.scrollSpeed[1]) { var d = delta / 1000; this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );}
}
} else { this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;}
Position.prepare(); Droppables.show(Draggables._lastPointer, this.element); Draggables.notify('onDrag', this); if (this._isScrollChild) { Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; if (Draggables._lastScrollPointer[0] < 0)
Draggables._lastScrollPointer[0] = 0; if (Draggables._lastScrollPointer[1] < 0)
Draggables._lastScrollPointer[1] = 0; this.draw(Draggables._lastScrollPointer);}
if(this.options.change) this.options.change(this);}, _getWindowScroll: function(w) { var T, L, W, H; with (w.document) { if (w.document.documentElement && documentElement.scrollTop) { T = documentElement.scrollTop; L = documentElement.scrollLeft;} else if (w.document.body) { T = body.scrollTop; L = body.scrollLeft;}
if (w.innerWidth) { W = w.innerWidth; H = w.innerHeight;} else if (w.document.documentElement && documentElement.clientWidth) { W = documentElement.clientWidth; H = documentElement.clientHeight;} else { W = body.offsetWidth; H = body.offsetHeight
}
}
return { top: T, left: L, width: W, height: H };}
}); Draggable._dragging = { }; var SortableObserver = Class.create({ initialize: function(element, observer) { this.element = $(element); this.observer = observer; this.lastValue = Sortable.serialize(this.element);}, onStart: function() { this.lastValue = Sortable.serialize(this.element);}, onEnd: function() { Sortable.unmark(); if(this.lastValue != Sortable.serialize(this.element))
this.observer(this.element)
}
}); var Sortable = { SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, sortables: { }, _findRootElement: function(element) { while (element.tagName.toUpperCase() != "BODY") { if(element.id && Sortable.sortables[element.id]) return element; element = element.parentNode;}
}, options: function(element) { element = Sortable._findRootElement($(element)); if(!element) return; return Sortable.sortables[element.id];}, destroy: function(element){ var s = Sortable.options(element); if(s) { Draggables.removeObserver(s.element); s.droppables.each(function(d){ Droppables.remove(d) }); s.draggables.invoke('destroy'); delete Sortable.sortables[s.element.id];}
}, create: function(element) { element = $(element); var options = Object.extend({ element: element, tag: 'li', dropOnEmpty: false, tree: false, treeTag: 'ul', overlap: 'vertical', constraint: 'vertical', containment: element, handle: false, only: false, delay: 0, hoverclass: null, ghosting: false, quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, format: this.SERIALIZE_RULE, elements: false, handles: false, onChange: Prototype.emptyFunction, onUpdate: Prototype.emptyFunction
}, arguments[1] || { }); this.destroy(element); var options_for_draggable = { revert: true, quiet: options.quiet, scroll: options.scroll, scrollSpeed: options.scrollSpeed, scrollSensitivity: options.scrollSensitivity, delay: options.delay, ghosting: options.ghosting, constraint: options.constraint, handle: options.handle }; if(options.starteffect)
options_for_draggable.starteffect = options.starteffect; if(options.reverteffect)
options_for_draggable.reverteffect = options.reverteffect; else
if(options.ghosting) options_for_draggable.reverteffect = function(element) { element.style.top = 0; element.style.left = 0;}; if(options.endeffect)
options_for_draggable.endeffect = options.endeffect; if(options.zindex)
options_for_draggable.zindex = options.zindex; var options_for_droppable = { overlap: options.overlap, containment: options.containment, tree: options.tree, hoverclass: options.hoverclass, onHover: Sortable.onHover
}
var options_for_tree = { onHover: Sortable.onEmptyHover, overlap: options.overlap, containment: options.containment, hoverclass: options.hoverclass
}
Element.cleanWhitespace(element); options.draggables = []; options.droppables = []; if(options.dropOnEmpty || options.tree) { Droppables.add(element, options_for_tree); options.droppables.push(element);}
(options.elements || this.findElements(element, options) || []).each( function(e,i) { var handle = options.handles ? $(options.handles[i]) :
(options.handle ? $(e).select('.' + options.handle)[0] : e); options.draggables.push( new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); Droppables.add(e, options_for_droppable); if(options.tree) e.treeNode = element; options.droppables.push(e);}); if(options.tree) { (Sortable.findTreeElements(element, options) || []).each( function(e) { Droppables.add(e, options_for_tree); e.treeNode = element; options.droppables.push(e);});}
this.sortables[element.id] = options; Draggables.addObserver(new SortableObserver(element, options.onUpdate));}, findElements: function(element, options) { return Element.findChildren( element, options.only, options.tree ? true : false, options.tag);}, findTreeElements: function(element, options) { return Element.findChildren( element, options.only, options.tree ? true : false, options.treeTag);}, onHover: function(element, dropon, overlap) { if(Element.isParent(dropon, element)) return; if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { return;} else if(overlap>0.5) { Sortable.mark(dropon, 'before'); if(dropon.previousSibling != element) { var oldParentNode = element.parentNode; element.style.visibility = "hidden"; dropon.parentNode.insertBefore(element, dropon); if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element); Sortable.options(dropon.parentNode).onChange(element);}
} else { Sortable.mark(dropon, 'after'); var nextElement = dropon.nextSibling || null; if(nextElement != element) { var oldParentNode = element.parentNode; element.style.visibility = "hidden"; dropon.parentNode.insertBefore(element, nextElement); if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element); Sortable.options(dropon.parentNode).onChange(element);}
}
}, onEmptyHover: function(element, dropon, overlap) { var oldParentNode = element.parentNode; var droponOptions = Sortable.options(dropon); if(!Element.isParent(dropon, element)) { var index; var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); var child = null; if(children) { var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); for (index = 0; index < children.length; index += 1) { if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { offset -= Element.offsetSize (children[index], droponOptions.overlap);} else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { child = index + 1 < children.length ? children[index + 1] : null; break;} else { child = children[index]; break;}
}
}
dropon.insertBefore(element, child); Sortable.options(oldParentNode).onChange(element); droponOptions.onChange(element);}
}, unmark: function() { if(Sortable._marker) Sortable._marker.hide();}, mark: function(dropon, position) { var sortable = Sortable.options(dropon.parentNode); if(sortable && !sortable.ghosting) return; if(!Sortable._marker) { Sortable._marker = ($('dropmarker') || Element.extend(document.createElement('DIV'))).
hide().addClassName('dropmarker').setStyle({position:'absolute'}); document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);}
var offsets = Position.cumulativeOffset(dropon); Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); if(position=='after')
if(sortable.overlap == 'horizontal')
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); else
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); Sortable._marker.show();}, _tree: function(element, options, parent) { var children = Sortable.findElements(element, options) || []; for (var i = 0; i < children.length; ++i) { var match = children[i].id.match(options.format); if (!match) continue; var child = { id: encodeURIComponent(match ? match[1] : null), element: element, parent: parent, children: [], position: parent.children.length, container: $(children[i]).down(options.treeTag)
}
if (child.container)
this._tree(child.container, options, child)
parent.children.push (child);}
return parent;}, tree: function(element) { element = $(element); var sortableOptions = this.options(element); var options = Object.extend({ tag: sortableOptions.tag, treeTag: sortableOptions.treeTag, only: sortableOptions.only, name: element.id, format: sortableOptions.format
}, arguments[1] || { }); var root = { id: null, parent: null, children: [], container: element, position: 0
}
return Sortable._tree(element, options, root);}, _constructIndex: function(node) { var index = ''; do { if (node.id) index = '[' + node.position + ']' + index;} while ((node = node.parent) != null); return index;}, sequence: function(element) { element = $(element); var options = Object.extend(this.options(element), arguments[1] || { }); return $(this.findElements(element, options) || []).map( function(item) { return item.id.match(options.format) ? item.id.match(options.format)[1] : '';});}, setSequence: function(element, new_sequence) { element = $(element); var options = Object.extend(this.options(element), arguments[2] || { }); var nodeMap = { }; this.findElements(element, options).each( function(n) { if (n.id.match(options.format))
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; n.parentNode.removeChild(n);}); new_sequence.each(function(ident) { var n = nodeMap[ident]; if (n) { n[1].appendChild(n[0]); delete nodeMap[ident];}
});}, serialize: function(element) { element = $(element); var options = Object.extend(Sortable.options(element), arguments[1] || { }); var name = encodeURIComponent( (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); if (options.tree) { return Sortable.tree(element, arguments[1]).children.map( function (item) { return [name + Sortable._constructIndex(item) + "[id]=" + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));}).flatten().join('&');} else { return Sortable.sequence(element, arguments[1]).map( function(item) { return name + "[]=" + encodeURIComponent(item);}).join('&');}
}
}
Element.isParent = function(child, element) { if (!child.parentNode || child == element) return false; if (child.parentNode == element) return true; return Element.isParent(child.parentNode, element);}
Element.findChildren = function(element, only, recursive, tagName) { if(!element.hasChildNodes()) return null; tagName = tagName.toUpperCase(); if(only) only = [only].flatten(); var elements = []; $A(element.childNodes).each( function(e) { if(e.tagName && e.tagName.toUpperCase()==tagName &&
(!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
elements.push(e); if(recursive) { var grandchildren = Element.findChildren(e, only, recursive, tagName); if(grandchildren) elements.push(grandchildren);}
}); return (elements.length>0 ? elements.flatten() : []);}
Element.offsetSize = function (element, type) { return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];}
var Popup = Class.create(); Popup.zIndex = 1000; Popup.prototype = { initialize: function(popup, link) { var options = Object.extend({ modal: false, effect: 'fade', hidden: true, closebox: 'popup_closebox', draghandle: 'popup_draghandle'
}, arguments[2] || {}); options.position = options.position || (options.modal ? 'center' : 'auto'); options.trigger = options.trigger || (options.modal ? 'click' : 'mouseover'); options.duration = this.first_value(options.duration, Popup.duration, 0.5); options.show_duration = this.first_value(options.show_duration, options.duration); options.hide_duration = this.first_value(options.hide_duration, options.duration); options.opacity = this.first_value(options.opacity, Popup.opacity, 0.5); options.show_delay = this.first_value(options.show_delay, Popup.show_delay, 500); options.hide_delay = this.first_value(options.hide_delay, Popup.hide_delay, 200); options.cursor_margin = this.first_value(options.cursor_margin, Popup.cursor_margin, 5); this.options = options; if (link) { this.link = $(link);}
this.popup = $(popup); this.popup.popup = this; if (options.hidden) { this.popup.hide();}
if (options.closebox) { this.closeboxes = document.getElementsByClassName(options.closebox, this.popup); if (this.popup.hasClassName(options.closebox)) { this.closeboxes[this.closeboxes.length] = this.popup;}
}
else { this.closeboxes = [];}
if (options.draghandle) { var draghandles = document.getElementsByClassName(options.draghandle, this.popup); for (i = 0; i < draghandles.length; i++) { new Draggable(this.popup, { handle: draghandles[i] });}
if (this.popup.hasClassName(options.draghandle)) { new Draggable(this.popup, { handle: this.popup });}
}
this.register_events();}, register_events: function() { var trigger_function; if (this.is_auto_open()) { trigger_function = this.start_show_timer; if (this.link) { Event.observe(this.link, 'mouseout', this.stop_show_timer.bindAsEventListener(this));}
}
else { trigger_function = this.show;}
if (this.link) { Event.observe(this.link, this.options.trigger, trigger_function.bindAsEventListener(this));}
if (!this.options.modal) { Event.observe(this.popup, 'click', this.bring_to_front.bindAsEventListener(this));}
if (this.closeboxes.length > 0) { for (var i = 0; i < this.closeboxes.length; i++) { Event.observe(this.closeboxes[i], 'click', this.hide.bindAsEventListener(this));}
}
else { if (this.link) { Event.observe(this.link, 'mouseout', this.start_hide_timer.bindAsEventListener(this));}
Event.observe(this.popup, 'mouseover', this.stop_hide_timer.bindAsEventListener(this)); Event.observe(this.popup, 'mouseout', this.start_hide_timer.bindAsEventListener(this));}
}, bring_to_front: function(event) { if (Number(this.popup.style.zIndex) < Popup.zIndex - 1) { this.popup.style.zIndex = Popup.zIndex++;}
}, start_show_timer: function(event) { this.stop_show_timer(event); this.mouse_x = Event.pointerX(event); this.mouse_y = Event.pointerY(event); this.show_timer = setTimeout(this.show.bind(this, event), this.options.show_delay);}, stop_show_timer: function(event) { if (this.show_timer) { clearTimeout(this.show_timer); this.show_timer = null;}
}, start_hide_timer: function(event) { this.stop_hide_timer(event); this.hide_timer = setTimeout(this.hide.bind(this, event), this.options.hide_delay);}, stop_hide_timer: function(event) { if (this.hide_timer) { clearTimeout(this.hide_timer); this.hide_timer = null;}
}, show: function(event) { this.stop_show_timer(event); this.stop_hide_timer(event); if (this.is_open) { return;}
if (this.options.modal) { this.show_overlay();}
var pos; if (!event) { pos = this.get_popup_position();}
else if (this.is_auto_open()) { pos = this.get_popup_position(this.mouse_x, this.mouse_y);}
else { pos = this.get_popup_position(Event.pointerX(event), Event.pointerY(event));}
Element.setStyle(this.popup, { top: pos.y, left: pos.x, zIndex: Popup.zIndex++ }); this.is_open = true; switch (this.options.effect) { case 'slide':
Effect.SlideDown(this.popup, {duration: this.options.show_duration}); break; case 'grow':
Effect.Grow(this.popup, {duration: this.options.show_duration}); break; case 'blind':
Effect.BlindDown(this.popup, {duration: this.options.show_duration}); break; case 'fade':
default:
Effect.Appear(this.popup, {duration: this.options.show_duration}); break;}
}, hide: function(event){ this.is_open = false; switch (this.options.effect) { case 'slide':
Effect.SlideUp(this.popup, {duration: this.options.hide_duration}); break; case 'grow':
Effect.Shrink(this.popup, {duration: this.options.hide_duration}); break; case 'blind':
Effect.BlindUp(this.popup, {duration: this.options.hide_duration}); break; case 'fade':
default:
Effect.Fade(this.popup, {duration: this.options.hide_duration}); break;}
if (this.options.modal) { this.hide_overlay();}
}, first_value: function() { for (var i = 0; i < arguments.length; i++) { if (arguments[i] !== undefined) { return arguments[i];}
}
return undefined;}, is_auto_open: function() { return this.options.trigger == 'mouseover';}, show_overlay: function() { if (!Popup.overlay) { var overlay = document.createElement('div'); overlay.setAttribute('id','popup_overlay'); overlay.style.display = 'none'; document.body.appendChild(overlay); Popup.overlay = overlay; Popup.overlay_levels = [];}
Popup.overlay.style.height = this.get_page_dimensions().height + 'px'; var z = Popup.zIndex++; Popup.overlay.style.zIndex = z; Popup.overlay_levels.push(z); if ( Popup.overlay_levels.length == 1) { new Effect.Appear(Popup.overlay, { duration: this.options.show_duration, to: this.options.opacity, queue: {position: 'end', scope: 'popup_overlay'}
});}
else { Popup.overlay.style.zIndex = z;}
}, hide_overlay: function() { Popup.overlay_levels.pop(); var z = Popup.overlay_levels.pop(); if (z) { Popup.overlay_levels.push(z); Popup.overlay.style.zIndex = z;}
else { new Effect.Fade(Popup.overlay, { duration: this.options.hide_duration, queue: {position: 'end', scope: 'popup_overlay'}
});}
}, get_popup_position: function(mouse_x, mouse_y) { var pos; switch (this.options.position) { case 'auto':
pos = this.get_auto_position(mouse_x, mouse_y); break; case 'center':
pos = this.get_center_position(); break; case 'below':
pos = this.get_below_position(); break; default:
if (mo = this.options.position.match(/^\s*([^\s,]+)\s*,\s*([^\s,]+)\s*$/)) { pos = {x: mo[1], y: mo[2]}; pos.x = Number(pos.x) || pos.x; pos.y = Number(pos.y) || pos.y;}
else { pos = {x: 0, y: 0};}
break;}
if (typeof pos.x == 'number') { pos.x += 'px';}
if (typeof pos.y == 'number') { pos.y += 'px';}
return pos;}, get_below_position: function() { var pos = Position.cumulativeOffset(this.link); return {x: pos[0], y: pos[1] + Element.getHeight(this.link)};}, get_center_position: function() { dim = Element.getDimensions(this.popup); var popup_width = dim.width; var popup_height = dim.height; dim = this.get_viewport_dimensions(); var viewport_width = dim.width; var viewport_height = dim.height; var x; if (popup_width >= viewport_width) { x = 0;}
else { x = (viewport_width - popup_width)/2;}
var y; if (popup_height >= viewport_height) { y = 0;}
else { y = (viewport_height - popup_height)/2;}
return {x: x, y: y};}, get_auto_position: function(mouse_x, mouse_y) { dim = Element.getDimensions(this.popup); var popup_width = dim.width; var popup_height = dim.height; dim = this.get_viewport_dimensions(); var viewport_width = dim.width; var viewport_height = dim.height; var available_right = viewport_width - (mouse_x + this.options.cursor_margin); var available_left = mouse_x - this.options.cursor_margin; var available_top = mouse_y - this.options.cursor_margin; var available_bottom = viewport_height - (mouse_x + this.options.cursor_margin); var offset = this.options.cursor_margin; var x = mouse_x; var y = mouse_y; if (popup_width >= viewport_width) { x = 0;}
else if (popup_width <= available_right) { x += offset;}
else if (popup_width <= available_left) { x -= popup_width + offset;}
else if (available_right >= available_left) { x = viewport_width - popup_width;}
else { x = 0;}
if (popup_height >= viewport_height) { y = 0;}
else if (popup_height <= available_bottom) { y += offset;}
else if (popup_height <= available_top) { y -= popup_height + offset;}
else if (available_bottom >= available_top) { y = viewport_height - popup_height;}
else { y = 0;}
return {x: x, y: y};}, get_viewport_dimensions: function() { var dim = this.getPageSize(); return {width: dim[2], height: dim[3]};}, get_page_dimensions: function() { var dim = this.getPageSize(); return {width: dim[0], height: dim[1]};}, getPageSize: function() { var xScroll, yScroll; if (window.innerHeight && window.scrollMaxY) { xScroll = document.body.scrollWidth; yScroll = window.innerHeight + window.scrollMaxY;} else if (document.body.scrollHeight > document.body.offsetHeight){ xScroll = document.body.scrollWidth; yScroll = document.body.scrollHeight;} else { xScroll = document.body.offsetWidth; yScroll = document.body.offsetHeight;}
var windowWidth, windowHeight; if (self.innerHeight) { windowWidth = self.innerWidth; windowHeight = self.innerHeight;} else if (document.documentElement && document.documentElement.clientHeight) { windowWidth = document.documentElement.clientWidth; windowHeight = document.documentElement.clientHeight;} else if (document.body) { windowWidth = document.body.clientWidth; windowHeight = document.body.clientHeight;}
if(yScroll < windowHeight){ pageHeight = windowHeight;} else { pageHeight = yScroll;}
if(xScroll < windowWidth){ pageWidth = windowWidth;} else { pageWidth = xScroll;}
arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight); return arrayPageSize;}
}