/*****************************************************************************
It is adviced to place the sIFR JavaScript calls in this file, keeping it
separate from the `sifr.js` file. That way, you can easily swap the `sifr.js`
file for a new version, while keeping the configuration.

You must load this file *after* loading `sifr.js`.

That said, you're of course free to merge the JavaScript files. Just make sure
the copyright statement in `sifr.js` is kept intact.
*****************************************************************************/

// Make an object pointing to the location of the Flash movie on your web server.
// Try using the font name as the variable name, makes it easy to remember which
// object you're using. As an example in this file, we'll use Futura.
//var futura = { src: '/path/to/futura.swf' };
var neutra_tf_bold = { src: '/js/sifr3/flash/neutra_text_tf_bold.swf' }

// Now you can set some configuration settings.
// See also <http://wiki.novemberborn.net/sifr3/JavaScript+Configuration>.
// One setting you probably want to use is `sIFR.useStyleCheck`. Before you do that,
// read <http://wiki.novemberborn.net/sifr3/DetectingCSSLoad>.

// sIFR.useStyleCheck = true;

// Next, activate sIFR:
sIFR.activate(neutra_tf_bold);

// If you want, you can use multiple movies, like so:
//
// var futura = { src: '/path/to/futura.swf' };
// var garamond = { src '/path/to/garamond.swf' };
// var rockwell = { src: '/path/to/rockwell.swf' };
// 
// sIFR.activate(futura, garamond, rockwell);
//
// Remember, there must be *only one* `sIFR.activate()`!

// Now we can do the replacements. You can do as many as you like, but just
// as an example, we'll replace all `<h1>` elements with the Futura movie.
// 
// The first argument to `sIFR.replace` is the `futura` object we created earlier.
// The second argument is another object, on which you can specify a number of
// parameters or "keyword arguemnts". For the full list, see "Keyword arguments"
// under `replace(kwargs, mergeKwargs)` at 
// <http://wiki.novemberborn.net/sifr3/JavaScript+Methods>.
// 
// The first argument you see here is `selector`, which is a normal CSS selector.
// That means you can also do things like '#content h1' or 'h1.title'.
//
// The second argument determines what the Flash text looks like. The main text
// is styled via the `.sIFR-root` class. Here we've specified `background-color`
// of the entire Flash movie to be a light grey, and the `color` of the text to
// be red. Read more about styling at <http://wiki.novemberborn.net/sifr3/Styling>.
sIFR.replace(neutra_tf_bold, {
 selector: '.sifr_h2',
 css: '.sIFR-root { color: #A4141F; background-color:#000000; font-size:30px; text-transform:uppercase }, a:link{ color:#CAD5E7 }, a:hover{ color:#657FAD }, a:visited{ color:#657FAD }',
 tuneWidth: 0,
 tuneHeight: 0,
 wmode: 'transparent'
});

sIFR.replace(neutra_tf_bold, {
 selector: '#home_vault_body h3',
 css: '.sIFR-root { color: #333333; background-color:#000000; font-size:22px; text-transform:uppercase }, a:link{ color:#CAD5E7 }, a:hover{ color:#657FAD }, a:visited{ color:#657FAD }',
 tuneWidth: 0,
 tuneHeight: 0,
 wmode: 'transparent'
});


/**
 * jQuery lightBox plugin
 * This jQuery plugin was inspired and based on Lightbox 2 by Lokesh Dhakar (http://www.huddletogether.com/projects/lightbox2/)
 * and adapted to me for use like a plugin from jQuery.
 * @name jquery-lightbox-0.5.js
 * @author Leandro Vieira Pinho - http://leandrovieira.com
 * @version 0.5
 * @date April 11, 2008
 * @category jQuery plugin
 * @copyright (c) 2008 Leandro Vieira Pinho (leandrovieira.com)
 * @license CC Attribution-No Derivative Works 2.5 Brazil - http://creativecommons.org/licenses/by-nd/2.5/br/deed.en_US
 * @example Visit http://leandrovieira.com/projects/jquery/lightbox/ for more informations about this jQuery plugin
 */
(function($){$.fn.lightBox=function(settings){settings=jQuery.extend({overlayBgColor:'#000',overlayOpacity:0.8,fixedNavigation:false,imageLoading:'/js/jquery.lightbox/images/lightbox-ico-loading.gif',imageBtnPrev:'/js/jquery.lightbox/images/lightbox-btn-prev.gif',imageBtnNext:'/js/jquery.lightbox/images/lightbox-btn-next.gif',imageBtnClose:'/js/jquery.lightbox/images/lightbox-btn-close.gif',imageBlank:'/js/jquery.lightbox/images/lightbox-blank.gif',containerBorderSize:10,containerResizeSpeed:400,txtImage:'Image',txtOf:'of',keyToClose:'c',keyToPrev:'p',keyToNext:'n',imageArray:[],activeImage:0},settings);var jQueryMatchedObj=this;function _initialize(){_start(this,jQueryMatchedObj);return false;}
function _start(objClicked,jQueryMatchedObj){$('embed, object, select').css({'visibility':'hidden'});_set_interface();settings.imageArray.length=0;settings.activeImage=0;if(jQueryMatchedObj.length==1){settings.imageArray.push(new Array(objClicked.getAttribute('href'),objClicked.getAttribute('title')));}else{for(var i=0;i<jQueryMatchedObj.length;i++){settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'),jQueryMatchedObj[i].getAttribute('title')));}}
while(settings.imageArray[settings.activeImage][0]!=objClicked.getAttribute('href')){settings.activeImage++;}
_set_image_to_view();}
function _set_interface(){$('body').append('<div id="jquery-overlay"></div><div id="jquery-lightbox"><div id="lightbox-container-image-box"><div id="lightbox-container-image"><img id="lightbox-image"><div style="" id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="'+settings.imageLoading+'"></a></div></div></div><div id="lightbox-container-image-data-box"><div id="lightbox-container-image-data"><div id="lightbox-image-details"><span id="lightbox-image-details-caption"></span><span id="lightbox-image-details-currentNumber"></span></div><div id="lightbox-secNav"><a href="#" id="lightbox-secNav-btnClose"><img src="'+settings.imageBtnClose+'"></a></div></div></div></div>');var arrPageSizes=___getPageSize();$('#jquery-overlay').css({backgroundColor:settings.overlayBgColor,opacity:settings.overlayOpacity,width:arrPageSizes[0],height:arrPageSizes[1]}).fadeIn();var arrPageScroll=___getPageScroll();$('#jquery-lightbox').css({top:arrPageScroll[1]+(arrPageSizes[3]/10),left:arrPageScroll[0]}).show();$('#jquery-overlay,#jquery-lightbox').click(function(){_finish();});$('#lightbox-loading-link,#lightbox-secNav-btnClose').click(function(){_finish();return false;});$(window).resize(function(){var arrPageSizes=___getPageSize();$('#jquery-overlay').css({width:arrPageSizes[0],height:arrPageSizes[1]});var arrPageScroll=___getPageScroll();$('#jquery-lightbox').css({top:arrPageScroll[1]+(arrPageSizes[3]/10),left:arrPageScroll[0]});});}
function _set_image_to_view(){$('#lightbox-loading').show();if(settings.fixedNavigation){$('#lightbox-image,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();}else{$('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();}
var objImagePreloader=new Image();objImagePreloader.onload=function(){$('#lightbox-image').attr('src',settings.imageArray[settings.activeImage][0]);_resize_container_image_box(objImagePreloader.width,objImagePreloader.height);objImagePreloader.onload=function(){};};objImagePreloader.src=settings.imageArray[settings.activeImage][0];};function _resize_container_image_box(intImageWidth,intImageHeight){var intCurrentWidth=$('#lightbox-container-image-box').width();var intCurrentHeight=$('#lightbox-container-image-box').height();var intWidth=(intImageWidth+(settings.containerBorderSize*2));var intHeight=(intImageHeight+(settings.containerBorderSize*2));var intDiffW=intCurrentWidth-intWidth;var intDiffH=intCurrentHeight-intHeight;$('#lightbox-container-image-box').animate({width:intWidth,height:intHeight},settings.containerResizeSpeed,function(){_show_image();});if((intDiffW==0)&&(intDiffH==0)){if($.browser.msie){___pause(250);}else{___pause(100);}}
$('#lightbox-container-image-data-box').css({width:intImageWidth});$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({height:intImageHeight+(settings.containerBorderSize*2)});};function _show_image(){$('#lightbox-loading').hide();$('#lightbox-image').fadeIn(function(){_show_image_data();_set_navigation();});_preload_neighbor_images();};function _show_image_data(){$('#lightbox-container-image-data-box').slideDown('fast');$('#lightbox-image-details-caption').hide();if(settings.imageArray[settings.activeImage][1]){$('#lightbox-image-details-caption').html(settings.imageArray[settings.activeImage][1]).show();}
if(settings.imageArray.length>1){$('#lightbox-image-details-currentNumber').html(settings.txtImage+' '+(settings.activeImage+1)+' '+settings.txtOf+' '+settings.imageArray.length).show();}}
function _set_navigation(){$('#lightbox-nav').show();$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({'background':'transparent url('+settings.imageBlank+') no-repeat'});if(settings.activeImage!=0){if(settings.fixedNavigation){$('#lightbox-nav-btnPrev').css({'background':'url('+settings.imageBtnPrev+') left 15% no-repeat'}).unbind().bind('click',function(){settings.activeImage=settings.activeImage-1;_set_image_to_view();return false;});}else{$('#lightbox-nav-btnPrev').unbind().hover(function(){$(this).css({'background':'url('+settings.imageBtnPrev+') left 15% no-repeat'});},function(){$(this).css({'background':'transparent url('+settings.imageBlank+') no-repeat'});}).show().bind('click',function(){settings.activeImage=settings.activeImage-1;_set_image_to_view();return false;});}}
if(settings.activeImage!=(settings.imageArray.length-1)){if(settings.fixedNavigation){$('#lightbox-nav-btnNext').css({'background':'url('+settings.imageBtnNext+') right 15% no-repeat'}).unbind().bind('click',function(){settings.activeImage=settings.activeImage+1;_set_image_to_view();return false;});}else{$('#lightbox-nav-btnNext').unbind().hover(function(){$(this).css({'background':'url('+settings.imageBtnNext+') right 15% no-repeat'});},function(){$(this).css({'background':'transparent url('+settings.imageBlank+') no-repeat'});}).show().bind('click',function(){settings.activeImage=settings.activeImage+1;_set_image_to_view();return false;});}}
_enable_keyboard_navigation();}
function _enable_keyboard_navigation(){$(document).keydown(function(objEvent){_keyboard_action(objEvent);});}
function _disable_keyboard_navigation(){$(document).unbind();}
function _keyboard_action(objEvent){if(objEvent==null){keycode=event.keyCode;escapeKey=27;}else{keycode=objEvent.keyCode;escapeKey=objEvent.DOM_VK_ESCAPE;}
key=String.fromCharCode(keycode).toLowerCase();if((key==settings.keyToClose)||(key=='x')||(keycode==escapeKey)){_finish();}
if((key==settings.keyToPrev)||(keycode==37)){if(settings.activeImage!=0){settings.activeImage=settings.activeImage-1;_set_image_to_view();_disable_keyboard_navigation();}}
if((key==settings.keyToNext)||(keycode==39)){if(settings.activeImage!=(settings.imageArray.length-1)){settings.activeImage=settings.activeImage+1;_set_image_to_view();_disable_keyboard_navigation();}}}
function _preload_neighbor_images(){if((settings.imageArray.length-1)>settings.activeImage){objNext=new Image();objNext.src=settings.imageArray[settings.activeImage+1][0];}
if(settings.activeImage>0){objPrev=new Image();objPrev.src=settings.imageArray[settings.activeImage-1][0];}}
function _finish(){$('#jquery-lightbox').remove();$('#jquery-overlay').fadeOut(function(){$('#jquery-overlay').remove();});$('embed, object, select').css({'visibility':'visible'});}
function ___getPageSize(){var xScroll,yScroll;if(window.innerHeight&&window.scrollMaxY){xScroll=window.innerWidth+window.scrollMaxX;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){if(document.documentElement.clientWidth){windowWidth=document.documentElement.clientWidth;}else{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=xScroll;}else{pageWidth=windowWidth;}
arrayPageSize=new Array(pageWidth,pageHeight,windowWidth,windowHeight);return arrayPageSize;};function ___getPageScroll(){var xScroll,yScroll;if(self.pageYOffset){yScroll=self.pageYOffset;xScroll=self.pageXOffset;}else if(document.documentElement&&document.documentElement.scrollTop){yScroll=document.documentElement.scrollTop;xScroll=document.documentElement.scrollLeft;}else if(document.body){yScroll=document.body.scrollTop;xScroll=document.body.scrollLeft;}
arrayPageScroll=new Array(xScroll,yScroll);return arrayPageScroll;};function ___pause(ms){var date=new Date();curDate=null;do{var curDate=new Date();}
while(curDate-date<ms);};return this.unbind('click').click(_initialize);};})(jQuery);
/**
 * @author kasey
 */
var $j = jQuery.noConflict(); 

$j(document).ready(function(){
 $j('#tweet_wrap').jScrollPane({showArrows:true,scrollbarWidth:17,dragMaxHeight:50,dragMinHeight:50});
 $j('#tgalaxy_university_article_wrap').jScrollPane({showArrows:true,scrollbarWidth:17,dragMaxHeight:50,dragMinHeight:50});
 $j(".product_slider ul").jcarousel({scroll:1,wrap:'both',auto:7.5,easing:'swing'});
 $j("#vault-slider").jcarousel({scroll:6,animation:2000,wrap:'both',auto:10,easing:'swing'});
 $j("#vault-slider a").lightBox();
});

/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE_AFL.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
 * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
 */
if(typeof Product=='undefined') {
 var Product = {};
}

/********************* IMAGE ZOOMER ***********************/

Product.Zoom = Class.create();
/**
 * Image zoom control
 *
 * @author Magento Core Team <core@magentocommerce.com>
 */
Product.Zoom.prototype = {
 initialize: function(imageEl, trackEl, handleEl, zoomInEl, zoomOutEl, hintEl){
 this.containerEl = $(imageEl).parentNode;
 this.imageEl = $(imageEl);
 this.handleEl = $(handleEl);
 this.trackEl = $(trackEl);
 this.hintEl = $(hintEl);

 this.containerDim = Element.getDimensions(this.containerEl);
 this.imageDim = Element.getDimensions(this.imageEl);

 this.imageDim.ratio = this.imageDim.width/this.imageDim.height;

 this.floorZoom = 1;

 if (this.imageDim.width > this.imageDim.height) {
 this.ceilingZoom = this.imageDim.width / this.containerDim.width;
 } else {
 this.ceilingZoom = this.imageDim.height / this.containerDim.height;
 }

 if (this.imageDim.width <= this.containerDim.width
 && this.imageDim.height <= this.containerDim.height) {
 this.trackEl.up().hide();
 this.hintEl.hide();
 this.containerEl.removeClassName('product-image-zoom');
 return;
 }

 this.imageX = 0;
 this.imageY = 0;
 this.imageZoom = 1;

 this.sliderSpeed = 0;
 this.sliderAccel = 0;
 this.zoomBtnPressed = false;

 this.showFull = false;

 this.selects = document.getElementsByTagName('select');

 this.draggable = new Draggable(imageEl, {
 starteffect:false,
 reverteffect:false,
 endeffect:false,
 snap:this.contain.bind(this)
 });

 this.slider = new Control.Slider(handleEl, trackEl, {
 axis:'horizontal',
 minimum:0,
 maximum:Element.getDimensions(this.trackEl).width,
 alignX:0,
 increment:1,
 sliderValue:0,
 onSlide:this.scale.bind(this),
 onChange:this.scale.bind(this)
 });

 this.scale(0);

 Event.observe(this.imageEl, 'dblclick', this.toggleFull.bind(this));

 Event.observe($(zoomInEl), 'mousedown', this.startZoomIn.bind(this));
 Event.observe($(zoomInEl), 'mouseup', this.stopZooming.bind(this));
 Event.observe($(zoomInEl), 'mouseout', this.stopZooming.bind(this));

 Event.observe($(zoomOutEl), 'mousedown', this.startZoomOut.bind(this));
 Event.observe($(zoomOutEl), 'mouseup', this.stopZooming.bind(this));
 Event.observe($(zoomOutEl), 'mouseout', this.stopZooming.bind(this));
 },

 toggleFull: function () {
 this.showFull = !this.showFull;
 //TODO: hide selects for IE only

 for (i=0; i<this.selects.length; i++) {
 this.selects[i].style.visibility = this.showFull ? 'hidden' : 'visible';
 }
 val_scale = !this.showFull ? this.slider.value : 1;
 this.scale(val_scale);

 this.trackEl.style.visibility = this.showFull ? 'hidden' : 'visible';
 this.containerEl.style.overflow = this.showFull ? 'visible' : 'hidden';
 this.containerEl.style.zIndex = this.showFull ? '1000' : '9';

 return this;
 },

 scale: function (v) {

 var centerX = (this.containerDim.width*(1-this.imageZoom)/2-this.imageX)/this.imageZoom;
 var centerY = (this.containerDim.height*(1-this.imageZoom)/2-this.imageY)/this.imageZoom;

 this.imageZoom = this.floorZoom+(v*(this.ceilingZoom-this.floorZoom));

 this.imageEl.style.width = (this.imageZoom*this.containerDim.width)+'px';
 if(this.containerDim.ratio){
 this.imageEl.style.height = (this.imageZoom*this.containerDim.width*this.containerDim.ratio)+'px'; // for safari
 }

 this.imageX = this.containerDim.width*(1-this.imageZoom)/2-centerX*this.imageZoom;
 this.imageY = this.containerDim.height*(1-this.imageZoom)/2-centerY*this.imageZoom;

 this.contain(this.imageX, this.imageY, this.draggable);

 return true;
 },

 startZoomIn: function()
 {
 this.zoomBtnPressed = true;
 this.sliderAccel = .002;
 this.periodicalZoom();
 this.zoomer = new PeriodicalExecuter(this.periodicalZoom.bind(this), .05);
 return this;
 },

 startZoomOut: function()
 {
 this.zoomBtnPressed = true;
 this.sliderAccel = -.002;
 this.periodicalZoom();
 this.zoomer = new PeriodicalExecuter(this.periodicalZoom.bind(this), .05);
 return this;
 },

 stopZooming: function()
 {
 if (!this.zoomer || this.sliderSpeed==0) {
 return;
 }
 this.zoomBtnPressed = false;
 this.sliderAccel = 0;
 },

 periodicalZoom: function()
 {
 if (!this.zoomer) {
 return this;
 }

 if (this.zoomBtnPressed) {
 this.sliderSpeed += this.sliderAccel;
 } else {
 this.sliderSpeed /= 1.5;
 if (Math.abs(this.sliderSpeed)<.001) {
 this.sliderSpeed = 0;
 this.zoomer.stop();
 this.zoomer = null;
 }
 }
 this.slider.value += this.sliderSpeed;

 this.slider.setValue(this.slider.value);
 this.scale(this.slider.value);

 return this;
 },

 contain: function (x,y,draggable) {

 var dim = Element.getDimensions(draggable.element);

 var xMin = 0, xMax = this.containerDim.width-dim.width;
 var yMin = 0, yMax = this.containerDim.height-dim.height;

 x = x>xMin ? xMin : x;
 x = x<xMax ? xMax : x;
 y = y>yMin ? yMin : y;
 y = y<yMax ? yMax : y;

 this.imageX = x;
 this.imageY = y;

 this.imageEl.style.left = this.imageX+'px';
 this.imageEl.style.top = this.imageY+'px';

 return [x,y];
 }
}

/**************************** CONFIGURABLE PRODUCT **************************/
Product.Config = Class.create();
Product.Config.prototype = {
 initialize: function(config){
 this.config = config;
 this.taxConfig = this.config.taxConfig;
 this.settings = $$('.super-attribute-select');
 this.state = new Hash();
 this.priceTemplate = new Template(this.config.template);
 this.prices = config.prices;

 this.settings.each(function(element){
 Event.observe(element, 'change', this.configure.bind(this))
 }.bind(this));

 // fill state
 this.settings.each(function(element){
 var attributeId = element.id.replace(/[a-z]*/, '');
 if(attributeId && this.config.attributes[attributeId]) {
 element.config = this.config.attributes[attributeId];
 element.attributeId = attributeId;
 this.state[attributeId] = false;
 }
 }.bind(this))

 // Init settings dropdown
 var childSettings = [];
 for(var i=this.settings.length-1;i>=0;i--){
 var prevSetting = this.settings[i-1] ? this.settings[i-1] : false;
 var nextSetting = this.settings[i+1] ? this.settings[i+1] : false;
 if(i==0){
 this.fillSelect(this.settings[i])
 }
 else {
 this.settings[i].disabled=true;
 }
 $(this.settings[i]).childSettings = childSettings.clone();
 $(this.settings[i]).prevSetting = prevSetting;
 $(this.settings[i]).nextSetting = nextSetting;
 childSettings.push(this.settings[i]);
 }

 // try retireve options from url
 var separatorIndex = window.location.href.indexOf('#');
 if (separatorIndex!=-1) {
 var paramsStr = window.location.href.substr(separatorIndex+1);
 this.values = paramsStr.toQueryParams();
 this.settings.each(function(element){
 var attributeId = element.attributeId;
 element.value = this.values[attributeId];
 this.configureElement(element);
 }.bind(this));
 }
 },

 configure: function(event){
 var element = Event.element(event);
 this.configureElement(element);
 },

 configureElement : function(element) {
 this.reloadOptionLabels(element);
 if(element.value){
 this.state[element.config.id] = element.value;
 if(element.nextSetting){
 element.nextSetting.disabled = false;
 this.fillSelect(element.nextSetting);
 this.resetChildren(element.nextSetting);
 }
 }
 else {
 this.resetChildren(element);
 }
 this.reloadPrice();
// Calculator.updatePrice();
 },

 reloadOptionLabels: function(element){
 var selectedPrice;
 if(element.options[element.selectedIndex].config){
 selectedPrice = parseFloat(element.options[element.selectedIndex].config.price)
 }
 else{
 selectedPrice = 0;
 }
 for(var i=0;i<element.options.length;i++){
 if(element.options[i].config){
 element.options[i].text = this.getOptionLabel(element.options[i].config, element.options[i].config.price-selectedPrice);
 }
 }
 },

 resetChildren : function(element){
 if(element.childSettings) {
 for(var i=0;i<element.childSettings.length;i++){
 element.childSettings[i].selectedIndex = 0;
 element.childSettings[i].disabled = true;
 if(element.config){
 this.state[element.config.id] = false;
 }
 }
 }
 },

 fillSelect: function(element){
 var attributeId = element.id.replace(/[a-z]*/, '');
 var options = this.getAttributeOptions(attributeId);
 this.clearSelect(element);
 element.options[0] = new Option(this.config.chooseText, '');

 var prevConfig = false;
 if(element.prevSetting){
 prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];
 }

 if(options) {
 var index = 1;
 for(var i=0;i<options.length;i++){
 var allowedProducts = [];
 if(prevConfig) {
 for(var j=0;j<options[i].products.length;j++){
 if(prevConfig.config.allowedProducts
 && prevConfig.config.allowedProducts.indexOf(options[i].products[j])>-1){
 allowedProducts.push(options[i].products[j]);
 }
 }
 } else {
 allowedProducts = options[i].products.clone();
 }

 if(allowedProducts.size()>0){
 options[i].allowedProducts = allowedProducts;
 element.options[index] = new Option(this.getOptionLabel(options[i], options[i].price), options[i].id);
 element.options[index].config = options[i];
 index++;
 }
 }
 }
 },

 getOptionLabel: function(option, price){
 var price = parseFloat(price);
 if (this.taxConfig.includeTax) {
 var tax = price / (100 + this.taxConfig.defaultTax) * this.taxConfig.defaultTax;
 var excl = price - tax;
 var incl = excl*(1+(this.taxConfig.currentTax/100));
 } else {
 var tax = price * (this.taxConfig.currentTax / 100);
 var excl = price;
 var incl = excl + tax;
 }

 if (this.taxConfig.showIncludeTax || this.taxConfig.showBothPrices) {
 price = incl;
 } else {
 price = excl;
 }

 var str = option.label;
 if(price){
 if (this.taxConfig.showBothPrices) {
 str+= ' ' + this.formatPrice(excl, true) + ' (' + this.formatPrice(price, true) + ' ' + this.taxConfig.inclTaxTitle + ')';
 } else {
 str+= ' ' + this.formatPrice(price, true);
 }
 }
 return str;
 },

 formatPrice: function(price, showSign){
 var str = '';
 price = parseFloat(price);
 if(showSign){
 if(price<0){
 str+= '-';
 price = -price;
 }
 else{
 str+= '+';
 }
 }

 var roundedPrice = (Math.round(price*100)/100).toString();

 if (this.prices && this.prices[roundedPrice]) {
 str+= this.prices[roundedPrice];
 }
 else {
 str+= this.priceTemplate.evaluate({price:price.toFixed(2)});
 }
 return str;
 },

 clearSelect: function(element){
 for(var i=element.options.length-1;i>=0;i--){
 element.remove(i);
 }
 },

 getAttributeOptions: function(attributeId){
 if(this.config.attributes[attributeId]){
 return this.config.attributes[attributeId].options;
 }
 },

 reloadPrice: function(){
 var price = 0;
 for(var i=this.settings.length-1;i>=0;i--){
 var selected = this.settings[i].options[this.settings[i].selectedIndex];
 if(selected.config){
 price += parseFloat(selected.config.price);
 }
 }

 optionsPrice.changePrice('config', price);
 optionsPrice.reload();

 return price;

 if($('product-price-'+this.config.productId)){
 $('product-price-'+this.config.productId).innerHTML = price;
 }
 this.reloadOldPrice();
 },

 reloadOldPrice: function(){
 if ($('old-price-'+this.config.productId)) {

 var price = parseFloat(this.config.oldPrice);
 for(var i=this.settings.length-1;i>=0;i--){
 var selected = this.settings[i].options[this.settings[i].selectedIndex];
 if(selected.config){
 price+= parseFloat(selected.config.price);
 }
 }
 if (price < 0)
 price = 0;
 price = this.formatPrice(price);

 if($('old-price-'+this.config.productId)){
 $('old-price-'+this.config.productId).innerHTML = price;
 }

 }
 }
}


/**************************** SUPER PRODUCTS ********************************/

Product.Super = {};
Product.Super.Configurable = Class.create();

Product.Super.Configurable.prototype = {
 initialize: function(container, observeCss, updateUrl, updatePriceUrl, priceContainerId) {
 this.container = $(container);
 this.observeCss = observeCss;
 this.updateUrl = updateUrl;
 this.updatePriceUrl = updatePriceUrl;
 this.priceContainerId = priceContainerId;
 this.registerObservers();
 },
 registerObservers: function() {
 var elements = this.container.getElementsByClassName(this.observeCss);
 elements.each(function(element){
 Event.observe(element, 'change', this.update.bindAsEventListener(this));
 }.bind(this));
 return this;
 },
 update: function(event) {
 var elements = this.container.getElementsByClassName(this.observeCss);
 var parameters = Form.serializeElements(elements, true);

 new Ajax.Updater(this.container, this.updateUrl + '?ajax=1', {
 parameters:parameters,
 onComplete:this.registerObservers.bind(this)
 });
 var priceContainer = $(this.priceContainerId);
 if(priceContainer) {
 new Ajax.Updater(priceContainer, this.updatePriceUrl + '?ajax=1', {
 parameters:parameters
 });
 }
 }
}

/**************************** PRICE RELOADER ********************************/
Product.OptionsPrice = Class.create();
Product.OptionsPrice.prototype = {
 initialize: function(config) {
 this.productId = config.productId;
 this.priceFormat = config.priceFormat;
 this.includeTax = config.includeTax;
 this.defaultTax = config.defaultTax;
 this.currentTax = config.currentTax;
 this.productPrice = config.productPrice;
 this.showIncludeTax = config.showIncludeTax;
 this.showBothPrices = config.showBothPrices;
 this.productPrice = config.productPrice;
 this.productOldPrice = config.productOldPrice;
 this.skipCalculate = config.skipCalculate;
 this.duplicateIdSuffix = config.idSuffix;

 this.oldPlusDisposition = config.oldPlusDisposition;
 this.plusDisposition = config.plusDisposition;

 this.oldMinusDisposition = config.oldMinusDisposition;
 this.minusDisposition = config.minusDisposition;

 this.optionPrices = {};
 this.containers = {};

 this.displayZeroPrice = true;

 this.initPrices();
 },

 setDuplicateIdSuffix: function(idSuffix) {
 this.duplicateIdSuffix = idSuffix;
 },

 initPrices: function() {
 this.containers[0] = 'product-price-' + this.productId;
 this.containers[1] = 'bundle-price-' + this.productId;
 this.containers[2] = 'price-including-tax-' + this.productId;
 this.containers[3] = 'price-excluding-tax-' + this.productId;
 this.containers[4] = 'old-price-' + this.productId;
 },

 changePrice: function(key, price) {
 this.optionPrices[key] = parseFloat(price);
 },

 getOptionPrices: function() {
 var result = 0;
 var nonTaxable = 0;
 $H(this.optionPrices).each(function(pair) {
 if (pair.key == 'nontaxable') {
 nonTaxable = pair.value;
 } else {
 result += pair.value;
 }
 });
 var r = new Array(result, nonTaxable);
 return r;
 },

 reload: function() {
 var price;
 var formattedPrice;
 var optionPrices = this.getOptionPrices();
 var nonTaxable = optionPrices[1];
 optionPrices = optionPrices[0];
 $H(this.containers).each(function(pair) {
 var _productPrice;
 var _plusDisposition;
 var _minusDisposition;
 if ($(pair.value)) {
 if (pair.value == 'old-price-'+this.productId && this.productOldPrice != this.productPrice) {
 _productPrice = this.productOldPrice;
 _plusDisposition = this.oldPlusDisposition;
 _minusDisposition = this.oldMinusDisposition;
 } else {
 _productPrice = this.productPrice;
 _plusDisposition = this.plusDisposition;
 _minusDisposition = this.minusDisposition;
 }

 var price = optionPrices+parseFloat(_productPrice)
 if (this.includeTax == 'true') {
 // tax = tax included into product price by admin
 var tax = price / (100 + this.defaultTax) * this.defaultTax;
 var excl = price - tax;
 var incl = excl*(1+(this.currentTax/100));
 } else {
 var tax = price * (this.currentTax / 100);
 var excl = price;
 var incl = excl + tax;
 }

 excl += parseFloat(_plusDisposition);
 incl += parseFloat(_plusDisposition);
 excl -= parseFloat(_minusDisposition);
 incl -= parseFloat(_minusDisposition);

 //adding nontaxlable part of options
 excl += parseFloat(nonTaxable);
 incl += parseFloat(nonTaxable);

 if (pair.value == 'price-including-tax-'+this.productId) {
 price = incl;
 } else if (pair.value == 'old-price-'+this.productId) {
 if (this.showIncludeTax || this.showBothPrices) {
 price = incl;
 } else {
 price = excl;
 }
 } else {
 if (this.showIncludeTax) {
 price = incl;
 } else {
 if (!this.skipCalculate || _productPrice == 0) {
 price = excl;
 } else {
 price = optionPrices+parseFloat(_productPrice);
 }
 }
 }

 if (price < 0) price = 0;

 if (price > 0 || this.displayZeroPrice) {
 formattedPrice = this.formatPrice(price);
 } else {
 formattedPrice = '';
 }

 if ($(pair.value).select('.price')[0]) {
 $(pair.value).select('.price')[0].innerHTML = formattedPrice;
 if ($(pair.value+this.duplicateIdSuffix) && $(pair.value+this.duplicateIdSuffix).select('.price')[0]) {
 $(pair.value+this.duplicateIdSuffix).select('.price')[0].innerHTML = formattedPrice;
 }
 } else {
 $(pair.value).innerHTML = formattedPrice;
 if ($(pair.value+this.duplicateIdSuffix)) {
 $(pair.value+this.duplicateIdSuffix).innerHTML = formattedPrice;
 }
 }
 };
 }.bind(this));
 },
 formatPrice: function(price) {
 return formatCurrency(price, this.priceFormat);
 }
}

/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo
 * -----------------------------------------------------------
 *
 * The DHTML Calendar, version 1.0 "It is happening again"
 *
 * Details and latest version at:
 * www.dynarch.com/projects/calendar
 *
 * This script is developed by Dynarch.com. Visit us at www.dynarch.com.
 *
 * This script is distributed under the GNU Lesser General Public License.
 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
 */

// $Id: calendar.js,v 1.51 2005/03/07 16:44:31 mishoo Exp $

/** The Calendar object constructor. */
Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {
 // member variables
 this.activeDiv = null;
 this.currentDateEl = null;
 this.getDateStatus = null;
 this.getDateToolTip = null;
 this.getDateText = null;
 this.timeout = null;
 this.onSelected = onSelected || null;
 this.onClose = onClose || null;
 this.dragging = false;
 this.hidden = false;
 this.minYear = 1970;
 this.maxYear = 2050;
 this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
 this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
 this.isPopup = true;
 this.weekNumbers = true;
 this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
 this.showsOtherMonths = false;
 this.dateStr = dateStr;
 this.ar_days = null;
 this.showsTime = false;
 this.time24 = true;
 this.yearStep = 2;
 this.hiliteToday = true;
 this.multiple = null;
 // HTML elements
 this.table = null;
 this.element = null;
 this.tbody = null;
 this.firstdayname = null;
 // Combo boxes
 this.monthsCombo = null;
 this.yearsCombo = null;
 this.hilitedMonth = null;
 this.activeMonth = null;
 this.hilitedYear = null;
 this.activeYear = null;
 // Information
 this.dateClicked = false;

 // one-time initializations
 if (typeof Calendar._SDN == "undefined") {
 // table of short day names
 if (typeof Calendar._SDN_len == "undefined")
 Calendar._SDN_len = 3;
 var ar = new Array();
 for (var i = 8; i > 0;) {
 ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
 }
 Calendar._SDN = ar;
 // table of short month names
 if (typeof Calendar._SMN_len == "undefined")
 Calendar._SMN_len = 3;
 ar = new Array();
 for (var i = 12; i > 0;) {
 ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
 }
 Calendar._SMN = ar;
 }
};

// ** constants

/// "static", needed for event handlers.
Calendar._C = null;

/// detect a special case of "web browser"
Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
 !/opera/i.test(navigator.userAgent) );

Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );

/// detect Opera browser
Calendar.is_opera = /opera/i.test(navigator.userAgent);

/// detect KHTML-based browsers
Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);

/// detect Gecko browsers
Calendar.is_gecko = navigator.userAgent.match(/gecko/i);

// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
// library, at some point.

// Returns CSS property for element
Calendar.getStyle = function(element, style) {
 if (element.currentStyle) {
 var y = element.currentStyle[style];
 } else if (window.getComputedStyle) {
 var y = document.defaultView.getComputedStyle(element,null).getPropertyValue(style);
 }

 return y;
};

/*
 * Different ways to find element's absolute position
 */
Calendar.getAbsolutePos = function(element) {

 var res = new Object();
 res.x = 0; res.y = 0;

 // variant 1 (working best, copy-paste from prototype library)
 do {
 res.x += element.offsetLeft || 0;
 res.y += element.offsetTop || 0;
 element = element.offsetParent;
 if (element) {
 if (element.tagName.toUpperCase() == 'BODY') break;
 var p = Calendar.getStyle(element, 'position');
 if (p !== 'static') break;
 }
 } while (element);

 return res;

 // variant 2 (good solution, but lost in IE8)
 if (element !== null) {
 res.x = element.offsetLeft;
 res.y = element.offsetTop;

 var offsetParent = element.offsetParent;
 var parentNode = element.parentNode;

 while (offsetParent !== null) {
 res.x += offsetParent.offsetLeft;
 res.y += offsetParent.offsetTop;

 if (offsetParent != document.body && offsetParent != document.documentElement) {
 res.x -= offsetParent.scrollLeft;
 res.y -= offsetParent.scrollTop;
 }
 //next lines are necessary to support FireFox problem with offsetParent
 if (Calendar.is_gecko) {
 while (offsetParent != parentNode && parentNode !== null) {
 res.x -= parentNode.scrollLeft;
 res.y -= parentNode.scrollTop;
 parentNode = parentNode.parentNode;
 }
 }
 parentNode = offsetParent.parentNode;
 offsetParent = offsetParent.offsetParent;
 }
 }
 return res;

 // variant 2 (not working)

// var SL = 0, ST = 0;
// var is_div = /^div$/i.test(el.tagName);
// if (is_div && el.scrollLeft)
// SL = el.scrollLeft;
// if (is_div && el.scrollTop)
// ST = el.scrollTop;
// var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
// if (el.offsetParent) {
// var tmp = this.getAbsolutePos(el.offsetParent);
// r.x += tmp.x;
// r.y += tmp.y;
// }
// return r;
};

Calendar.isRelated = function (el, evt) {
 var related = evt.relatedTarget;
 if (!related) {
 var type = evt.type;
 if (type == "mouseover") {
 related = evt.fromElement;
 } else if (type == "mouseout") {
 related = evt.toElement;
 }
 }
 while (related) {
 if (related == el) {
 return true;
 }
 related = related.parentNode;
 }
 return false;
};

Calendar.removeClass = function(el, className) {
 if (!(el && el.className)) {
 return;
 }
 var cls = el.className.split(" ");
 var ar = new Array();
 for (var i = cls.length; i > 0;) {
 if (cls[--i] != className) {
 ar[ar.length] = cls[i];
 }
 }
 el.className = ar.join(" ");
};

Calendar.addClass = function(el, className) {
 Calendar.removeClass(el, className);
 el.className += " " + className;
};

// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
Calendar.getElement = function(ev) {
 var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
 while (f.nodeType != 1 || /^div$/i.test(f.tagName))
 f = f.parentNode;
 return f;
};

Calendar.getTargetElement = function(ev) {
 var f = Calendar.is_ie ? window.event.srcElement : ev.target;
 while (f.nodeType != 1)
 f = f.parentNode;
 return f;
};

Calendar.stopEvent = function(ev) {
 ev || (ev = window.event);
 if (Calendar.is_ie) {
 ev.cancelBubble = true;
 ev.returnValue = false;
 } else {
 ev.preventDefault();
 ev.stopPropagation();
 }
 return false;
};

Calendar.addEvent = function(el, evname, func) {
 if (el.attachEvent) { // IE
 el.attachEvent("on" + evname, func);
 } else if (el.addEventListener) { // Gecko / W3C
 el.addEventListener(evname, func, true);
 } else {
 el["on" + evname] = func;
 }
};

Calendar.removeEvent = function(el, evname, func) {
 if (el.detachEvent) { // IE
 el.detachEvent("on" + evname, func);
 } else if (el.removeEventListener) { // Gecko / W3C
 el.removeEventListener(evname, func, true);
 } else {
 el["on" + evname] = null;
 }
};

Calendar.createElement = function(type, parent) {
 var el = null;
 if (document.createElementNS) {
 // use the XHTML namespace; IE won't normally get here unless
 // _they_ "fix" the DOM2 implementation.
 el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
 } else {
 el = document.createElement(type);
 }
 if (typeof parent != "undefined") {
 parent.appendChild(el);
 }
 return el;
};

// END: UTILITY FUNCTIONS

// BEGIN: CALENDAR STATIC FUNCTIONS

/** Internal -- adds a set of events to make some element behave like a button. */
Calendar._add_evs = function(el) {
 with (Calendar) {
 addEvent(el, "mouseover", dayMouseOver);
 addEvent(el, "mousedown", dayMouseDown);
 addEvent(el, "mouseout", dayMouseOut);
 if (is_ie) {
 addEvent(el, "dblclick", dayMouseDblClick);
 el.setAttribute("unselectable", true);
 }
 }
};

Calendar.findMonth = function(el) {
 if (typeof el.month != "undefined") {
 return el;
 } else if (typeof el.parentNode.month != "undefined") {
 return el.parentNode;
 }
 return null;
};

Calendar.findYear = function(el) {
 if (typeof el.year != "undefined") {
 return el;
 } else if (typeof el.parentNode.year != "undefined") {
 return el.parentNode;
 }
 return null;
};

Calendar.showMonthsCombo = function () {
 var cal = Calendar._C;
 if (!cal) {
 return false;
 }
 var cal = cal;
 var cd = cal.activeDiv;
 var mc = cal.monthsCombo;
 if (cal.hilitedMonth) {
 Calendar.removeClass(cal.hilitedMonth, "hilite");
 }
 if (cal.activeMonth) {
 Calendar.removeClass(cal.activeMonth, "active");
 }
 var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
 Calendar.addClass(mon, "active");
 cal.activeMonth = mon;
 var s = mc.style;
 s.display = "block";
 if (cd.navtype < 0)
 s.left = cd.offsetLeft + "px";
 else {
 var mcw = mc.offsetWidth;
 if (typeof mcw == "undefined")
 // Konqueror brain-dead techniques
 mcw = 50;
 s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
 }
 s.top = (cd.offsetTop + cd.offsetHeight) + "px";
};

Calendar.showYearsCombo = function (fwd) {
 var cal = Calendar._C;
 if (!cal) {
 return false;
 }
 var cal = cal;
 var cd = cal.activeDiv;
 var yc = cal.yearsCombo;
 if (cal.hilitedYear) {
 Calendar.removeClass(cal.hilitedYear, "hilite");
 }
 if (cal.activeYear) {
 Calendar.removeClass(cal.activeYear, "active");
 }
 cal.activeYear = null;
 var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
 var yr = yc.firstChild;
 var show = false;
 for (var i = 12; i > 0; --i) {
 if (Y >= cal.minYear && Y <= cal.maxYear) {
 yr.innerHTML = Y;
 yr.year = Y;
 yr.style.display = "block";
 show = true;
 } else {
 yr.style.display = "none";
 }
 yr = yr.nextSibling;
 Y += fwd ? cal.yearStep : -cal.yearStep;
 }
 if (show) {
 var s = yc.style;
 s.display = "block";
 if (cd.navtype < 0)
 s.left = cd.offsetLeft + "px";
 else {
 var ycw = yc.offsetWidth;
 if (typeof ycw == "undefined")
 // Konqueror brain-dead techniques
 ycw = 50;
 s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
 }
 s.top = (cd.offsetTop + cd.offsetHeight) + "px";
 }
};

// event handlers

Calendar.tableMouseUp = function(ev) {
 var cal = Calendar._C;
 if (!cal) {
 return false;
 }
 if (cal.timeout) {
 clearTimeout(cal.timeout);
 }
 var el = cal.activeDiv;
 if (!el) {
 return false;
 }
 var target = Calendar.getTargetElement(ev);
 ev || (ev = window.event);
 Calendar.removeClass(el, "active");
 if (target == el || target.parentNode == el) {
 Calendar.cellClick(el, ev);
 }
 var mon = Calendar.findMonth(target);
 var date = null;
 if (mon) {
 date = new CalendarDateObject(cal.date);
 if (mon.month != date.getMonth()) {
 date.setMonth(mon.month);
 cal.setDate(date);
 cal.dateClicked = false;
 cal.callHandler();
 }
 } else {
 var year = Calendar.findYear(target);
 if (year) {
 date = new CalendarDateObject(cal.date);
 if (year.year != date.getFullYear()) {
 date.setFullYear(year.year);
 cal.setDate(date);
 cal.dateClicked = false;
 cal.callHandler();
 }
 }
 }
 with (Calendar) {
 removeEvent(document, "mouseup", tableMouseUp);
 removeEvent(document, "mouseover", tableMouseOver);
 removeEvent(document, "mousemove", tableMouseOver);
 cal._hideCombos();
 _C = null;
 return stopEvent(ev);
 }
};

Calendar.tableMouseOver = function (ev) {
 var cal = Calendar._C;
 if (!cal) {
 return;
 }
 var el = cal.activeDiv;
 var target = Calendar.getTargetElement(ev);
 if (target == el || target.parentNode == el) {
 Calendar.addClass(el, "hilite active");
 Calendar.addClass(el.parentNode, "rowhilite");
 } else {
 if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
 Calendar.removeClass(el, "active");
 Calendar.removeClass(el, "hilite");
 Calendar.removeClass(el.parentNode, "rowhilite");
 }
 ev || (ev = window.event);
 if (el.navtype == 50 && target != el) {
 var pos = Calendar.getAbsolutePos(el);
 var w = el.offsetWidth;
 var x = ev.clientX;
 var dx;
 var decrease = true;
 if (x > pos.x + w) {
 dx = x - pos.x - w;
 decrease = false;
 } else
 dx = pos.x - x;

 if (dx < 0) dx = 0;
 var range = el._range;
 var current = el._current;
 var count = Math.floor(dx / 10) % range.length;
 for (var i = range.length; --i >= 0;)
 if (range[i] == current)
 break;
 while (count-- > 0)
 if (decrease) {
 if (--i < 0)
 i = range.length - 1;
 } else if ( ++i >= range.length )
 i = 0;
 var newval = range[i];
 el.innerHTML = newval;

 cal.onUpdateTime();
 }
 var mon = Calendar.findMonth(target);
 if (mon) {
 if (mon.month != cal.date.getMonth()) {
 if (cal.hilitedMonth) {
 Calendar.removeClass(cal.hilitedMonth, "hilite");
 }
 Calendar.addClass(mon, "hilite");
 cal.hilitedMonth = mon;
 } else if (cal.hilitedMonth) {
 Calendar.removeClass(cal.hilitedMonth, "hilite");
 }
 } else {
 if (cal.hilitedMonth) {
 Calendar.removeClass(cal.hilitedMonth, "hilite");
 }
 var year = Calendar.findYear(target);
 if (year) {
 if (year.year != cal.date.getFullYear()) {
 if (cal.hilitedYear) {
 Calendar.removeClass(cal.hilitedYear, "hilite");
 }
 Calendar.addClass(year, "hilite");
 cal.hilitedYear = year;
 } else if (cal.hilitedYear) {
 Calendar.removeClass(cal.hilitedYear, "hilite");
 }
 } else if (cal.hilitedYear) {
 Calendar.removeClass(cal.hilitedYear, "hilite");
 }
 }
 return Calendar.stopEvent(ev);
};

Calendar.tableMouseDown = function (ev) {
 if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
 return Calendar.stopEvent(ev);
 }
};

Calendar.calDragIt = function (ev) {
 var cal = Calendar._C;
 if (!(cal && cal.dragging)) {
 return false;
 }
 var posX;
 var posY;
 if (Calendar.is_ie) {
 posY = window.event.clientY + document.body.scrollTop;
 posX = window.event.clientX + document.body.scrollLeft;
 } else {
 posX = ev.pageX;
 posY = ev.pageY;
 }
 cal.hideShowCovered();
 var st = cal.element.style;
 st.left = (posX - cal.xOffs) + "px";
 st.top = (posY - cal.yOffs) + "px";
 return Calendar.stopEvent(ev);
};

Calendar.calDragEnd = function (ev) {
 var cal = Calendar._C;
 if (!cal) {
 return false;
 }
 cal.dragging = false;
 with (Calendar) {
 removeEvent(document, "mousemove", calDragIt);
 removeEvent(document, "mouseup", calDragEnd);
 tableMouseUp(ev);
 }
 cal.hideShowCovered();
};

Calendar.dayMouseDown = function(ev) {
 var el = Calendar.getElement(ev);
 if (el.disabled) {
 return false;
 }
 var cal = el.calendar;
 cal.activeDiv = el;
 Calendar._C = cal;
 if (el.navtype != 300) with (Calendar) {
 if (el.navtype == 50) {
 el._current = el.innerHTML;
 addEvent(document, "mousemove", tableMouseOver);
 } else
 addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
 addClass(el, "hilite active");
 addEvent(document, "mouseup", tableMouseUp);
 } else if (cal.isPopup) {
 cal._dragStart(ev);
 }
 if (el.navtype == -1 || el.navtype == 1) {
 if (cal.timeout) clearTimeout(cal.timeout);
 cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
 } else if (el.navtype == -2 || el.navtype == 2) {
 if (cal.timeout) clearTimeout(cal.timeout);
 cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
 } else {
 cal.timeout = null;
 }
 return Calendar.stopEvent(ev);
};

Calendar.dayMouseDblClick = function(ev) {
 Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
 if (Calendar.is_ie) {
 document.selection.empty();
 }
};

Calendar.dayMouseOver = function(ev) {
 var el = Calendar.getElement(ev);
 if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
 return false;
 }
 if (el.ttip) {
 if (el.ttip.substr(0, 1) == "_") {
 el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
 }
 el.calendar.tooltips.innerHTML = el.ttip;
 }
 if (el.navtype != 300) {
 Calendar.addClass(el, "hilite");
 if (el.caldate) {
 Calendar.addClass(el.parentNode, "rowhilite");
 }
 }
 return Calendar.stopEvent(ev);
};

Calendar.dayMouseOut = function(ev) {
 with (Calendar) {
 var el = getElement(ev);
 if (isRelated(el, ev) || _C || el.disabled)
 return false;
 removeClass(el, "hilite");
 if (el.caldate)
 removeClass(el.parentNode, "rowhilite");
 if (el.calendar)
 el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
 return stopEvent(ev);
 }
};

/**
 * A generic "click" handler :) handles all types of buttons defined in this
 * calendar.
 */
Calendar.cellClick = function(el, ev) {
 var cal = el.calendar;
 var closing = false;
 var newdate = false;
 var date = null;
 if (typeof el.navtype == "undefined") {
 if (cal.currentDateEl) {
 Calendar.removeClass(cal.currentDateEl, "selected");
 Calendar.addClass(el, "selected");
 closing = (cal.currentDateEl == el);
 if (!closing) {
 cal.currentDateEl = el;
 }
 }
 cal.date.setDateOnly(el.caldate);
 date = cal.date;
 var other_month = !(cal.dateClicked = !el.otherMonth);
 if (!other_month && !cal.currentDateEl)
 cal._toggleMultipleDate(new CalendarDateObject(date));
 else
 newdate = !el.disabled;
 // a date was clicked
 if (other_month)
 cal._init(cal.firstDayOfWeek, date);
 } else {
 if (el.navtype == 200) {
 Calendar.removeClass(el, "hilite");
 cal.callCloseHandler();
 return;
 }
 date = new CalendarDateObject(cal.date);
 if (el.navtype == 0)
 date.setDateOnly(new CalendarDateObject()); // TODAY
 // unless "today" was clicked, we assume no date was clicked so
 // the selected handler will know not to close the calenar when
 // in single-click mode.
 // cal.dateClicked = (el.navtype == 0);
 cal.dateClicked = false;
 var year = date.getFullYear();
 var mon = date.getMonth();
 function setMonth(m) {
 var day = date.getDate();
 var max = date.getMonthDays(m);
 if (day > max) {
 date.setDate(max);
 }
 date.setMonth(m);
 };
 switch (el.navtype) {
 case 400:
 Calendar.removeClass(el, "hilite");
 var text = Calendar._TT["ABOUT"];
 if (typeof text != "undefined") {
 text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
 } else {
 // FIXME: this should be removed as soon as lang files get updated!
 text = "Help and about box text is not translated into this language.\n" +
 "If you know this language and you feel generous please update\n" +
 "the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
 "and send it back to <mihai_bazon@yahoo.com> to get it into the distribution ;-)\n\n" +
 "Thank you!\n" +
 "http://dynarch.com/mishoo/calendar.epl\n";
 }
 alert(text);
 return;
 case -2:
 if (year > cal.minYear) {
 date.setFullYear(year - 1);
 }
 break;
 case -1:
 if (mon > 0) {
 setMonth(mon - 1);
 } else if (year-- > cal.minYear) {
 date.setFullYear(year);
 setMonth(11);
 }
 break;
 case 1:
 if (mon < 11) {
 setMonth(mon + 1);
 } else if (year < cal.maxYear) {
 date.setFullYear(year + 1);
 setMonth(0);
 }
 break;
 case 2:
 if (year < cal.maxYear) {
 date.setFullYear(year + 1);
 }
 break;
 case 100:
 cal.setFirstDayOfWeek(el.fdow);
 return;
 case 50:
 var range = el._range;
 var current = el.innerHTML;
 for (var i = range.length; --i >= 0;)
 if (range[i] == current)
 break;
 if (ev && ev.shiftKey) {
 if (--i < 0)
 i = range.length - 1;
 } else if ( ++i >= range.length )
 i = 0;
 var newval = range[i];
 el.innerHTML = newval;
 cal.onUpdateTime();
 return;
 case 0:
 // TODAY will bring us here
 if ((typeof cal.getDateStatus == "function") &&
 cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
 return false;
 }
 break;
 }
 if (!date.equalsTo(cal.date)) {
 cal.setDate(date);
 newdate = true;
 } else if (el.navtype == 0)
 newdate = closing = true;
 }
 if (newdate) {
 ev && cal.callHandler();
 }
 if (closing) {
 Calendar.removeClass(el, "hilite");
 ev && cal.callCloseHandler();
 }
};

// END: CALENDAR STATIC FUNCTIONS

// BEGIN: CALENDAR OBJECT FUNCTIONS

/**
 * This function creates the calendar inside the given parent. If _par is
 * null than it creates a popup calendar inside the BODY element. If _par is
 * an element, be it BODY, then it creates a non-popup calendar (still
 * hidden). Some properties need to be set before calling this function.
 */
Calendar.prototype.create = function (_par) {
 var parent = null;
 if (! _par) {
 // default parent is the document body, in which case we create
 // a popup calendar.
 parent = document.getElementsByTagName("body")[0];
 this.isPopup = true;
 } else {
 parent = _par;
 this.isPopup = false;
 }
 this.date = this.dateStr ? new CalendarDateObject(this.dateStr) : new CalendarDateObject();

 var table = Calendar.createElement("table");
 this.table = table;
 table.cellSpacing = 0;
 table.cellPadding = 0;
 table.calendar = this;
 Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);

 var div = Calendar.createElement("div");
 this.element = div;
 div.className = "calendar";
 if (this.isPopup) {
 div.style.position = "absolute";
 div.style.display = "none";
 }
 div.appendChild(table);

 var thead = Calendar.createElement("thead", table);
 var cell = null;
 var row = null;

 var cal = this;
 var hh = function (text, cs, navtype) {
 cell = Calendar.createElement("td", row);
 cell.colSpan = cs;
 cell.className = "button";
 if (navtype != 0 && Math.abs(navtype) <= 2)
 cell.className += " nav";
 Calendar._add_evs(cell);
 cell.calendar = cal;
 cell.navtype = navtype;
 cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
 return cell;
 };

 row = Calendar.createElement("tr", thead);
 var title_length = 6;
 (this.isPopup) && --title_length;
 (this.weekNumbers) && ++title_length;

 hh("?", 1, 400).ttip = Calendar._TT["INFO"];
 this.title = hh("", title_length, 300);
 this.title.className = "title";
 if (this.isPopup) {
 this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
 this.title.style.cursor = "move";
 hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
 }

 row = Calendar.createElement("tr", thead);
 row.className = "headrow";

 this._nav_py = hh("&#x00ab;", 1, -2);
 this._nav_py.ttip = Calendar._TT["PREV_YEAR"];

 this._nav_pm = hh("&#x2039;", 1, -1);
 this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];

 this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
 this._nav_now.ttip = Calendar._TT["GO_TODAY"];

 this._nav_nm = hh("&#x203a;", 1, 1);
 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];

 this._nav_ny = hh("&#x00bb;", 1, 2);
 this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];

 // day names
 row = Calendar.createElement("tr", thead);
 row.className = "daynames";
 if (this.weekNumbers) {
 cell = Calendar.createElement("td", row);
 cell.className = "name wn";
 cell.innerHTML = Calendar._TT["WK"];
 }
 for (var i = 7; i > 0; --i) {
 cell = Calendar.createElement("td", row);
 if (!i) {
 cell.navtype = 100;
 cell.calendar = this;
 Calendar._add_evs(cell);
 }
 }
 this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
 this._displayWeekdays();

 var tbody = Calendar.createElement("tbody", table);
 this.tbody = tbody;

 for (i = 6; i > 0; --i) {
 row = Calendar.createElement("tr", tbody);
 if (this.weekNumbers) {
 cell = Calendar.createElement("td", row);
 }
 for (var j = 7; j > 0; --j) {
 cell = Calendar.createElement("td", row);
 cell.calendar = this;
 Calendar._add_evs(cell);
 }
 }

 if (this.showsTime) {
 row = Calendar.createElement("tr", tbody);
 row.className = "time";

 cell = Calendar.createElement("td", row);
 cell.className = "time";
 cell.colSpan = 2;
 cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";

 cell = Calendar.createElement("td", row);
 cell.className = "time";
 cell.colSpan = this.weekNumbers ? 4 : 3;

 (function(){
 function makeTimePart(className, init, range_start, range_end) {
 var part = Calendar.createElement("span", cell);
 part.className = className;
 part.innerHTML = init;
 part.calendar = cal;
 part.ttip = Calendar._TT["TIME_PART"];
 part.navtype = 50;
 part._range = [];
 if (typeof range_start != "number")
 part._range = range_start;
 else {
 for (var i = range_start; i <= range_end; ++i) {
 var txt;
 if (i < 10 && range_end >= 10) txt = '0' + i;
 else txt = '' + i;
 part._range[part._range.length] = txt;
 }
 }
 Calendar._add_evs(part);
 return part;
 };
 var hrs = cal.date.getHours();
 var mins = cal.date.getMinutes();
 var t12 = !cal.time24;
 var pm = (hrs > 12);
 if (t12 && pm) hrs -= 12;
 var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
 var span = Calendar.createElement("span", cell);
 span.innerHTML = ":";
 span.className = "colon";
 var M = makeTimePart("minute", mins, 0, 59);
 var AP = null;
 cell = Calendar.createElement("td", row);
 cell.className = "time";
 cell.colSpan = 2;
 if (t12)
 AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
 else
 cell.innerHTML = "&nbsp;";

 cal.onSetTime = function() {
 var pm, hrs = this.date.getHours(),
 mins = this.date.getMinutes();
 if (t12) {
 pm = (hrs >= 12);
 if (pm) hrs -= 12;
 if (hrs == 0) hrs = 12;
 AP.innerHTML = pm ? "pm" : "am";
 }
 H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
 M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
 };

 cal.onUpdateTime = function() {
 var date = this.date;
 var h = parseInt(H.innerHTML, 10);
 if (t12) {
 if (/pm/i.test(AP.innerHTML) && h < 12)
 h += 12;
 else if (/am/i.test(AP.innerHTML) && h == 12)
 h = 0;
 }
 var d = date.getDate();
 var m = date.getMonth();
 var y = date.getFullYear();
 date.setHours(h);
 date.setMinutes(parseInt(M.innerHTML, 10));
 date.setFullYear(y);
 date.setMonth(m);
 date.setDate(d);
 this.dateClicked = false;
 this.callHandler();
 };
 })();
 } else {
 this.onSetTime = this.onUpdateTime = function() {};
 }

 var tfoot = Calendar.createElement("tfoot", table);

 row = Calendar.createElement("tr", tfoot);
 row.className = "footrow";

 cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
 cell.className = "ttip";
 if (this.isPopup) {
 cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
 cell.style.cursor = "move";
 }
 this.tooltips = cell;

 div = Calendar.createElement("div", this.element);
 this.monthsCombo = div;
 div.className = "combo";
 for (i = 0; i < Calendar._MN.length; ++i) {
 var mn = Calendar.createElement("div");
 mn.className = Calendar.is_ie ? "label-IEfix" : "label";
 mn.month = i;
 mn.innerHTML = Calendar._SMN[i];
 div.appendChild(mn);
 }

 div = Calendar.createElement("div", this.element);
 this.yearsCombo = div;
 div.className = "combo";
 for (i = 12; i > 0; --i) {
 var yr = Calendar.createElement("div");
 yr.className = Calendar.is_ie ? "label-IEfix" : "label";
 div.appendChild(yr);
 }

 this._init(this.firstDayOfWeek, this.date);
 parent.appendChild(this.element);
};

/** keyboard navigation, only for popup calendars */
Calendar._keyEvent = function(ev) {
 var cal = window._dynarch_popupCalendar;
 if (!cal || cal.multiple)
 return false;
 (Calendar.is_ie) && (ev = window.event);
 var act = (Calendar.is_ie || ev.type == "keypress"),
 K = ev.keyCode;
 if (ev.ctrlKey) {
 switch (K) {
 case 37: // KEY left
 act && Calendar.cellClick(cal._nav_pm);
 break;
 case 38: // KEY up
 act && Calendar.cellClick(cal._nav_py);
 break;
 case 39: // KEY right
 act && Calendar.cellClick(cal._nav_nm);
 break;
 case 40: // KEY down
 act && Calendar.cellClick(cal._nav_ny);
 break;
 default:
 return false;
 }
 } else switch (K) {
 case 32: // KEY space (now)
 Calendar.cellClick(cal._nav_now);
 break;
 case 27: // KEY esc
 act && cal.callCloseHandler();
 break;
 case 37: // KEY left
 case 38: // KEY up
 case 39: // KEY right
 case 40: // KEY down
 if (act) {
 var prev, x, y, ne, el, step;
 prev = K == 37 || K == 38;
 step = (K == 37 || K == 39) ? 1 : 7;
 function setVars() {
 el = cal.currentDateEl;
 var p = el.pos;
 x = p & 15;
 y = p >> 4;
 ne = cal.ar_days[y][x];
 };setVars();
 function prevMonth() {
 var date = new CalendarDateObject(cal.date);
 date.setDate(date.getDate() - step);
 cal.setDate(date);
 };
 function nextMonth() {
 var date = new CalendarDateObject(cal.date);
 date.setDate(date.getDate() + step);
 cal.setDate(date);
 };
 while (1) {
 switch (K) {
 case 37: // KEY left
 if (--x >= 0)
 ne = cal.ar_days[y][x];
 else {
 x = 6;
 K = 38;
 continue;
 }
 break;
 case 38: // KEY up
 if (--y >= 0)
 ne = cal.ar_days[y][x];
 else {
 prevMonth();
 setVars();
 }
 break;
 case 39: // KEY right
 if (++x < 7)
 ne = cal.ar_days[y][x];
 else {
 x = 0;
 K = 40;
 continue;
 }
 break;
 case 40: // KEY down
 if (++y < cal.ar_days.length)
 ne = cal.ar_days[y][x];
 else {
 nextMonth();
 setVars();
 }
 break;
 }
 break;
 }
 if (ne) {
 if (!ne.disabled)
 Calendar.cellClick(ne);
 else if (prev)
 prevMonth();
 else
 nextMonth();
 }
 }
 break;
 case 13: // KEY enter
 if (act)
 Calendar.cellClick(cal.currentDateEl, ev);
 break;
 default:
 return false;
 }
 return Calendar.stopEvent(ev);
};

/**
 * (RE)Initializes the calendar to the given date and firstDayOfWeek
 */
Calendar.prototype._init = function (firstDayOfWeek, date) {
 var today = new CalendarDateObject(),
 TY = today.getFullYear(),
 TM = today.getMonth(),
 TD = today.getDate();
 this.table.style.visibility = "hidden";
 var year = date.getFullYear();
 if (year < this.minYear) {
 year = this.minYear;
 date.setFullYear(year);
 } else if (year > this.maxYear) {
 year = this.maxYear;
 date.setFullYear(year);
 }
 this.firstDayOfWeek = firstDayOfWeek;
 this.date = new CalendarDateObject(date);
 var month = date.getMonth();
 var mday = date.getDate();
 var no_days = date.getMonthDays();

 // calendar voodoo for computing the first day that would actually be
 // displayed in the calendar, even if it's from the previous month.
 // WARNING: this is magic. ;-)
 date.setDate(1);
 var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
 if (day1 < 0)
 day1 += 7;
 date.setDate(-day1);
 date.setDate(date.getDate() + 1);

 var row = this.tbody.firstChild;
 var MN = Calendar._SMN[month];
 var ar_days = this.ar_days = new Array();
 var weekend = Calendar._TT["WEEKEND"];
 var dates = this.multiple ? (this.datesCells = {}) : null;
 for (var i = 0; i < 6; ++i, row = row.nextSibling) {
 var cell = row.firstChild;
 if (this.weekNumbers) {
 cell.className = "day wn";
 cell.innerHTML = date.getWeekNumber();
 cell = cell.nextSibling;
 }
 row.className = "daysrow";
 var hasdays = false, iday, dpos = ar_days[i] = [];
 for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
 iday = date.getDate();
 var wday = date.getDay();
 cell.className = "day";
 cell.pos = i << 4 | j;
 dpos[j] = cell;
 var current_month = (date.getMonth() == month);
 if (!current_month) {
 if (this.showsOtherMonths) {
 cell.className += " othermonth";
 cell.otherMonth = true;
 } else {
 cell.className = "emptycell";
 cell.innerHTML = "&nbsp;";
 cell.disabled = true;
 continue;
 }
 } else {
 cell.otherMonth = false;
 hasdays = true;
 }
 cell.disabled = false;
 cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
 if (dates)
 dates[date.print("%Y%m%d")] = cell;
 if (this.getDateStatus) {
 var status = this.getDateStatus(date, year, month, iday);
 if (this.getDateToolTip) {
 var toolTip = this.getDateToolTip(date, year, month, iday);
 if (toolTip)
 cell.title = toolTip;
 }
 if (status === true) {
 cell.className += " disabled";
 cell.disabled = true;
 } else {
 if (/disabled/i.test(status))
 cell.disabled = true;
 cell.className += " " + status;
 }
 }
 if (!cell.disabled) {
 cell.caldate = new CalendarDateObject(date);
 cell.ttip = "_";
 if (!this.multiple && current_month
 && iday == mday && this.hiliteToday) {
 cell.className += " selected";
 this.currentDateEl = cell;
 }
 if (date.getFullYear() == TY &&
 date.getMonth() == TM &&
 iday == TD) {
 cell.className += " today";
 cell.ttip += Calendar._TT["PART_TODAY"];
 }
 if (weekend.indexOf(wday.toString()) != -1)
 cell.className += cell.otherMonth ? " oweekend" : " weekend";
 }
 }
 if (!(hasdays || this.showsOtherMonths))
 row.className = "emptyrow";
 }
 this.title.innerHTML = Calendar._MN[month] + ", " + year;
 this.onSetTime();
 this.table.style.visibility = "visible";
 this._initMultipleDates();
 // PROFILE
 // this.tooltips.innerHTML = "Generated in " + ((new CalendarDateObject()) - today) + " ms";
};

Calendar.prototype._initMultipleDates = function() {
 if (this.multiple) {
 for (var i in this.multiple) {
 var cell = this.datesCells[i];
 var d = this.multiple[i];
 if (!d)
 continue;
 if (cell)
 cell.className += " selected";
 }
 }
};

Calendar.prototype._toggleMultipleDate = function(date) {
 if (this.multiple) {
 var ds = date.print("%Y%m%d");
 var cell = this.datesCells[ds];
 if (cell) {
 var d = this.multiple[ds];
 if (!d) {
 Calendar.addClass(cell, "selected");
 this.multiple[ds] = date;
 } else {
 Calendar.removeClass(cell, "selected");
 delete this.multiple[ds];
 }
 }
 }
};

Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
 this.getDateToolTip = unaryFunction;
};

/**
 * Calls _init function above for going to a certain date (but only if the
 * date is different than the currently selected one).
 */
Calendar.prototype.setDate = function (date) {
 if (!date.equalsTo(this.date)) {
 this._init(this.firstDayOfWeek, date);
 }
};

/**
 * Refreshes the calendar. Useful if the "disabledHandler" function is
 * dynamic, meaning that the list of disabled date can change at runtime.
 * Just * call this function if you think that the list of disabled dates
 * should * change.
 */
Calendar.prototype.refresh = function () {
 this._init(this.firstDayOfWeek, this.date);
};

/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
 this._init(firstDayOfWeek, this.date);
 this._displayWeekdays();
};

/**
 * Allows customization of what dates are enabled. The "unaryFunction"
 * parameter must be a function object that receives the date (as a JS Date
 * object) and returns a boolean value. If the returned value is true then
 * the passed date will be marked as disabled.
 */
Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
 this.getDateStatus = unaryFunction;
};

/** Customization of allowed year range for the calendar. */
Calendar.prototype.setRange = function (a, z) {
 this.minYear = a;
 this.maxYear = z;
};

/** Calls the first user handler (selectedHandler). */
Calendar.prototype.callHandler = function () {
 if (this.onSelected) {
 this.onSelected(this, this.date.print(this.dateFormat));
 }
};

/** Calls the second user handler (closeHandler). */
Calendar.prototype.callCloseHandler = function () {
 if (this.onClose) {
 this.onClose(this);
 }
 this.hideShowCovered();
};

/** Removes the calendar object from the DOM tree and destroys it. */
Calendar.prototype.destroy = function () {
 var el = this.element.parentNode;
 el.removeChild(this.element);
 Calendar._C = null;
 window._dynarch_popupCalendar = null;
};

/**
 * Moves the calendar element to a different section in the DOM tree (changes
 * its parent).
 */
Calendar.prototype.reparent = function (new_parent) {
 var el = this.element;
 el.parentNode.removeChild(el);
 new_parent.appendChild(el);
};

// This gets called when the user presses a mouse button anywhere in the
// document, if the calendar is shown. If the click was outside the open
// calendar this function closes it.
Calendar._checkCalendar = function(ev) {
 var calendar = window._dynarch_popupCalendar;
 if (!calendar) {
 return false;
 }
 var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
 for (; el != null && el != calendar.element; el = el.parentNode);
 if (el == null) {
 // calls closeHandler which should hide the calendar.
 window._dynarch_popupCalendar.callCloseHandler();
 return Calendar.stopEvent(ev);
 }
};

/** Shows the calendar. */
Calendar.prototype.show = function () {
 var rows = this.table.getElementsByTagName("tr");
 for (var i = rows.length; i > 0;) {
 var row = rows[--i];
 Calendar.removeClass(row, "rowhilite");
 var cells = row.getElementsByTagName("td");
 for (var j = cells.length; j > 0;) {
 var cell = cells[--j];
 Calendar.removeClass(cell, "hilite");
 Calendar.removeClass(cell, "active");
 }
 }
 this.element.style.display = "block";
 this.hidden = false;
 if (this.isPopup) {
 window._dynarch_popupCalendar = this;
 Calendar.addEvent(document, "keydown", Calendar._keyEvent);
 Calendar.addEvent(document, "keypress", Calendar._keyEvent);
 Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
 }
 this.hideShowCovered();
};

/**
 * Hides the calendar. Also removes any "hilite" from the class of any TD
 * element.
 */
Calendar.prototype.hide = function () {
 if (this.isPopup) {
 Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
 Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
 Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
 }
 this.element.style.display = "none";
 this.hidden = true;
 this.hideShowCovered();
};

/**
 * Shows the calendar at a given absolute position (beware that, depending on
 * the calendar element style -- position property -- this might be relative
 * to the parent's containing rectangle).
 */
Calendar.prototype.showAt = function (x, y) {
 var s = this.element.style;
 s.left = x + "px";
 s.top = y + "px";
 this.show();
};

/** Shows the calendar near a given element. */
Calendar.prototype.showAtElement = function (el, opts) {
 var self = this;
 var p = Calendar.getAbsolutePos(el);
 if (!opts || typeof opts != "string") {
 this.showAt(p.x, p.y + el.offsetHeight);
 return true;
 }
 function fixPosition(box) {
 if (box.x < 0)
 box.x = 0;
 if (box.y < 0)
 box.y = 0;
 var cp = document.createElement("div");
 var s = cp.style;
 s.position = "absolute";
 s.right = s.bottom = s.width = s.height = "0px";
 document.body.appendChild(cp);
 var br = Calendar.getAbsolutePos(cp);
 document.body.removeChild(cp);
 if (Calendar.is_ie) {
 br.y += document.body.scrollTop;
 br.x += document.body.scrollLeft;
 } else {
 br.y += window.scrollY;
 br.x += window.scrollX;
 }
 var tmp = box.x + box.width - br.x;
 if (tmp > 0) box.x -= tmp;
 tmp = box.y + box.height - br.y;
 if (tmp > 0) box.y -= tmp;
 };
 this.element.style.display = "block";
 Calendar.continuation_for_the_fucking_khtml_browser = function() {
 var w = self.element.offsetWidth;
 var h = self.element.offsetHeight;
 self.element.style.display = "none";
 var valign = opts.substr(0, 1);
 var halign = "l";
 if (opts.length > 1) {
 halign = opts.substr(1, 1);
 }
 // vertical alignment
 switch (valign) {
 case "T": p.y -= h; break;
 case "B": p.y += el.offsetHeight; break;
 case "C": p.y += (el.offsetHeight - h) / 2; break;
 case "t": p.y += el.offsetHeight - h; break;
 case "b": break; // already there
 }
 // horizontal alignment
 switch (halign) {
 case "L": p.x -= w; break;
 case "R": p.x += el.offsetWidth; break;
 case "C": p.x += (el.offsetWidth - w) / 2; break;
 case "l": p.x += el.offsetWidth - w; break;
 case "r": break; // already there
 }
 p.width = w;
 p.height = h + 40;
 self.monthsCombo.style.display = "none";
 fixPosition(p);
 self.showAt(p.x, p.y);
 };
 if (Calendar.is_khtml)
 setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
 else
 Calendar.continuation_for_the_fucking_khtml_browser();
};

/** Customizes the date format. */
Calendar.prototype.setDateFormat = function (str) {
 this.dateFormat = str;
};

/** Customizes the tooltip date format. */
Calendar.prototype.setTtDateFormat = function (str) {
 this.ttDateFormat = str;
};

/**
 * Tries to identify the date represented in a string. If successful it also
 * calls this.setDate which moves the calendar to the given date.
 */
Calendar.prototype.parseDate = function(str, fmt) {
 if (!fmt)
 fmt = this.dateFormat;
 this.setDate(Date.parseDate(str, fmt));
};

Calendar.prototype.hideShowCovered = function () {
 if (!Calendar.is_ie && !Calendar.is_opera)
 return;
 function getVisib(obj){
 var value = obj.style.visibility;
 if (!value) {
 if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
 if (!Calendar.is_khtml)
 value = document.defaultView.
 getComputedStyle(obj, "").getPropertyValue("visibility");
 else
 value = '';
 } else if (obj.currentStyle) { // IE
 value = obj.currentStyle.visibility;
 } else
 value = '';
 }
 return value;
 };

 var tags = new Array("applet", "iframe", "select");
 var el = this.element;

 var p = Calendar.getAbsolutePos(el);
 var EX1 = p.x;
 var EX2 = el.offsetWidth + EX1;
 var EY1 = p.y;
 var EY2 = el.offsetHeight + EY1;

 for (var k = tags.length; k > 0; ) {
 var ar = document.getElementsByTagName(tags[--k]);
 var cc = null;

 for (var i = ar.length; i > 0;) {
 cc = ar[--i];

 p = Calendar.getAbsolutePos(cc);
 var CX1 = p.x;
 var CX2 = cc.offsetWidth + CX1;
 var CY1 = p.y;
 var CY2 = cc.offsetHeight + CY1;

 if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
 if (!cc.__msh_save_visibility) {
 cc.__msh_save_visibility = getVisib(cc);
 }
 cc.style.visibility = cc.__msh_save_visibility;
 } else {
 if (!cc.__msh_save_visibility) {
 cc.__msh_save_visibility = getVisib(cc);
 }
 cc.style.visibility = "hidden";
 }
 }
 }
};

/** Internal function; it displays the bar with the names of the weekday. */
Calendar.prototype._displayWeekdays = function () {
 var fdow = this.firstDayOfWeek;
 var cell = this.firstdayname;
 var weekend = Calendar._TT["WEEKEND"];
 for (var i = 0; i < 7; ++i) {
 cell.className = "day name";
 var realday = (i + fdow) % 7;
 if (i) {
 cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
 cell.navtype = 100;
 cell.calendar = this;
 cell.fdow = realday;
 Calendar._add_evs(cell);
 }
 if (weekend.indexOf(realday.toString()) != -1) {
 Calendar.addClass(cell, "weekend");
 }
 cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
 cell = cell.nextSibling;
 }
};

/** Internal function. Hides all combo boxes that might be displayed. */
Calendar.prototype._hideCombos = function () {
 this.monthsCombo.style.display = "none";
 this.yearsCombo.style.display = "none";
};

/** Internal function. Starts dragging the element. */
Calendar.prototype._dragStart = function (ev) {
 if (this.dragging) {
 return;
 }
 this.dragging = true;
 var posX;
 var posY;
 if (Calendar.is_ie) {
 posY = window.event.clientY + document.body.scrollTop;
 posX = window.event.clientX + document.body.scrollLeft;
 } else {
 posY = ev.clientY + window.scrollY;
 posX = ev.clientX + window.scrollX;
 }
 var st = this.element.style;
 this.xOffs = posX - parseInt(st.left);
 this.yOffs = posY - parseInt(st.top);
 with (Calendar) {
 addEvent(document, "mousemove", calDragIt);
 addEvent(document, "mouseup", calDragEnd);
 }
};

// BEGIN: DATE OBJECT PATCHES

/** Adds the number of days array to the Date object. */
Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

/** Constants used for time computations */
Date.SECOND = 1000 /* milliseconds */;
Date.MINUTE = 60 * Date.SECOND;
Date.HOUR = 60 * Date.MINUTE;
Date.DAY = 24 * Date.HOUR;
Date.WEEK = 7 * Date.DAY;

Date.parseDate = function(str, fmt) {
 var today = new CalendarDateObject();
 var y = 0;
 var m = -1;
 var d = 0;

 // translate date into en_US, because split() cannot parse non-latin stuff
 var a = str;
 var i;
 for (i = 0; i < Calendar._MN.length; i++) {
 a = a.replace(Calendar._MN[i], enUS.m.wide[i]);
 }
 for (i = 0; i < Calendar._SMN.length; i++) {
 a = a.replace(Calendar._SMN[i], enUS.m.abbr[i]);
 }
 a = a.replace(Calendar._am, 'am');
 a = a.replace(Calendar._am.toLowerCase(), 'am');
 a = a.replace(Calendar._pm, 'pm');
 a = a.replace(Calendar._pm.toLowerCase(), 'pm');

 a = a.split(/\W+/);

 var b = fmt.match(/%./g);
 var i = 0, j = 0;
 var hr = 0;
 var min = 0;
 for (i = 0; i < a.length; ++i) {
 if (!a[i])
 continue;
 switch (b[i]) {
 case "%d":
 case "%e":
 d = parseInt(a[i], 10);
 break;

 case "%m":
 m = parseInt(a[i], 10) - 1;
 break;

 case "%Y":
 case "%y":
 y = parseInt(a[i], 10);
 (y < 100) && (y += (y > 29) ? 1900 : 2000);
 break;

 case "%b":
 for (j = 0; j < 12; ++j) {
 if (enUS.m.abbr[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
 }
 break;

 case "%B":
 for (j = 0; j < 12; ++j) {
 if (enUS.m.wide[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
 }
 break;

 case "%H":
 case "%I":
 case "%k":
 case "%l":
 hr = parseInt(a[i], 10);
 break;

 case "%P":
 case "%p":
 if (/pm/i.test(a[i]) && hr < 12)
 hr += 12;
 else if (/am/i.test(a[i]) && hr >= 12)
 hr -= 12;
 break;

 case "%M":
 min = parseInt(a[i], 10);
 break;
 }
 }
 if (isNaN(y)) y = today.getFullYear();
 if (isNaN(m)) m = today.getMonth();
 if (isNaN(d)) d = today.getDate();
 if (isNaN(hr)) hr = today.getHours();
 if (isNaN(min)) min = today.getMinutes();
 if (y != 0 && m != -1 && d != 0)
 return new CalendarDateObject(y, m, d, hr, min, 0);
 y = 0; m = -1; d = 0;
 for (i = 0; i < a.length; ++i) {
 if (a[i].search(/[a-zA-Z]+/) != -1) {
 var t = -1;
 for (j = 0; j < 12; ++j) {
 if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
 }
 if (t != -1) {
 if (m != -1) {
 d = m+1;
 }
 m = t;
 }
 } else if (parseInt(a[i], 10) <= 12 && m == -1) {
 m = a[i]-1;
 } else if (parseInt(a[i], 10) > 31 && y == 0) {
 y = parseInt(a[i], 10);
 (y < 100) && (y += (y > 29) ? 1900 : 2000);
 } else if (d == 0) {
 d = a[i];
 }
 }
 if (y == 0)
 y = today.getFullYear();
 if (m != -1 && d != 0)
 return new CalendarDateObject(y, m, d, hr, min, 0);
 return today;
};

/** Returns the number of days in the current month */
Date.prototype.getMonthDays = function(month) {
 var year = this.getFullYear();
 if (typeof month == "undefined") {
 month = this.getMonth();
 }
 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
 return 29;
 } else {
 return Date._MD[month];
 }
};

/** Returns the number of day in the year. */
Date.prototype.getDayOfYear = function() {
 var now = new CalendarDateObject(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var then = new CalendarDateObject(this.getFullYear(), 0, 0, 0, 0, 0);
 var time = now - then;
 return Math.floor(time / Date.DAY);
};

/** Returns the number of the week in year, as defined in ISO 8601. */
Date.prototype.getWeekNumber = function() {
 var d = new CalendarDateObject(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var DoW = d.getDay();
 d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
 var ms = d.valueOf(); // GMT
 d.setMonth(0);
 d.setDate(4); // Thu in Week 1
 return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};

/** Checks date and time equality */
Date.prototype.equalsTo = function(date) {
 return ((this.getFullYear() == date.getFullYear()) &&
 (this.getMonth() == date.getMonth()) &&
 (this.getDate() == date.getDate()) &&
 (this.getHours() == date.getHours()) &&
 (this.getMinutes() == date.getMinutes()));
};

/** Set only the year, month, date parts (keep existing time) */
Date.prototype.setDateOnly = function(date) {
 var tmp = new CalendarDateObject(date);
 this.setDate(1);
 this.setFullYear(tmp.getFullYear());
 this.setMonth(tmp.getMonth());
 this.setDate(tmp.getDate());
};

/** Prints the date in a string according to the given format. */
Date.prototype.print = function (str) {
 var m = this.getMonth();
 var d = this.getDate();
 var y = this.getFullYear();
 var wn = this.getWeekNumber();
 var w = this.getDay();
 var s = {};
 var hr = this.getHours();
 var pm = (hr >= 12);
 var ir = (pm) ? (hr - 12) : hr;
 var dy = this.getDayOfYear();
 if (ir == 0)
 ir = 12;
 var min = this.getMinutes();
 var sec = this.getSeconds();
 s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
 s["%A"] = Calendar._DN[w]; // full weekday name
 s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
 s["%B"] = Calendar._MN[m]; // full month name
 // FIXME: %c : preferred date and time representation for the current locale
 s["%C"] = 1 + Math.floor(y / 100); // the century number
 s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
 s["%e"] = d; // the day of the month (range 1 to 31)
 // FIXME: %D : american date style: %m/%d/%y
 // FIXME: %E, %F, %G, %g, %h (man strftime)
 s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
 s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
 s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
 s["%k"] = hr; // hour, range 0 to 23 (24h format)
 s["%l"] = ir; // hour, range 1 to 12 (12h format)
 s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
 s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
 s["%n"] = "\n"; // a newline character
 s["%p"] = pm ? Calendar._pm.toUpperCase() : Calendar._am.toUpperCase();
 s["%P"] = pm ? Calendar._pm.toLowerCase() : Calendar._am.toLowerCase();
 // FIXME: %r : the time in am/pm notation %I:%M:%S %p
 // FIXME: %R : the time in 24-hour notation %H:%M
 s["%s"] = Math.floor(this.getTime() / 1000);
 s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
 s["%t"] = "\t"; // a tab character
 // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
 s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
 s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON)
 s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN)
 // FIXME: %x : preferred date representation for the current locale without the time
 // FIXME: %X : preferred time representation for the current locale without the date
 s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
 s["%Y"] = y; // year with the century
 s["%%"] = "%"; // a literal '%' character

 var re = /%./g;
 if (!Calendar.is_ie5 && !Calendar.is_khtml)
 return str.replace(re, function (par) { return s[par] || par; });

 var a = str.match(re);
 for (var i = 0; i < a.length; i++) {
 var tmp = s[a[i]];
 if (tmp) {
 re = new RegExp(a[i], 'g');
 str = str.replace(re, tmp);
 }
 }

 return str;
};

Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
Date.prototype.setFullYear = function(y) {
 var d = new CalendarDateObject(this);
 d.__msh_oldSetFullYear(y);
 if (d.getMonth() != this.getMonth())
 this.setDate(28);
 this.__msh_oldSetFullYear(y);
};

CalendarDateObject.prototype = new Date();
CalendarDateObject.prototype.constructor = CalendarDateObject;
CalendarDateObject.prototype.parent = Date.prototype;
function CalendarDateObject() {
 var dateObj;
 if (arguments.length > 1) {
 dateObj = eval("new this.parent.constructor("+Array.prototype.slice.call(arguments).join(",")+");");
 } else if (arguments.length > 0) {
 dateObj = new this.parent.constructor(arguments[0]);
 } else {
 dateObj = new this.parent.constructor();
 if (typeof(CalendarDateObject._LOCAL_TIMZEONE_OFFSET_SECONDS) != "undefined") {
 dateObj.setTime(dateObj.getTime()+(CalendarDateObject._LOCAL_TIMZEONE_OFFSET_SECONDS - dateObj.getTimezoneOffset())*1000);
 }
 }
 return dateObj;
}

// END: DATE OBJECT PATCHES


// global object that remembers the calendar
window._dynarch_popupCalendar = null;

/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/
 * ---------------------------------------------------------------------------
 *
 * The DHTML Calendar
 *
 * Details and latest version at:
 * http://dynarch.com/mishoo/calendar.epl
 *
 * This script is distributed under the GNU Lesser General Public License.
 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
 *
 * This file defines helper functions for setting up the calendar. They are
 * intended to help non-programmers get a working calendar on their site
 * quickly. This script should not be seen as part of the calendar. It just
 * shows you what one can do with the calendar, while in the same time
 * providing a quick and simple method for setting it up. If you need
 * exhaustive customization of the calendar creation process feel free to
 * modify this code to suit your needs (this is recommended and much better
 * than modifying calendar.js itself).
 */
 Calendar.setup=function(params){function param_default(pname,def){if(typeof params[pname]=="undefined"){params[pname]=def;}};param_default("inputField",null);param_default("displayArea",null);param_default("button",null);param_default("eventName","click");param_default("ifFormat","%Y/%m/%d");param_default("daFormat","%Y/%m/%d");param_default("singleClick",true);param_default("disableFunc",null);param_default("dateStatusFunc",params["disableFunc"]);param_default("dateText",null);param_default("firstDay",null);param_default("align","Br");param_default("range",[1900,2999]);param_default("weekNumbers",true);param_default("flat",null);param_default("flatCallback",null);param_default("onSelect",null);param_default("onClose",null);param_default("onUpdate",null);param_default("date",null);param_default("showsTime",false);param_default("timeFormat","24");param_default("electric",true);param_default("step",2);param_default("position",null);param_default("cache",false);param_default("showOthers",false);param_default("multiple",null);var tmp=["inputField","displayArea","button"];for(var i in tmp){if(typeof params[tmp[i]]=="string"){params[tmp[i]]=document.getElementById(params[tmp[i]]);}}if(!(params.flat||params.multiple||params.inputField||params.displayArea||params.button)){alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code");return false;}function onSelect(cal){var p=cal.params;var update=(cal.dateClicked||p.electric);if(update&&p.inputField){p.inputField.value=cal.date.print(p.ifFormat);if(typeof p.inputField.onchange=="function")p.inputField.onchange();}if(update&&p.displayArea)p.displayArea.innerHTML=cal.date.print(p.daFormat);if(update&&typeof p.onUpdate=="function")p.onUpdate(cal);if(update&&p.flat){if(typeof p.flatCallback=="function")p.flatCallback(cal);}if(update&&p.singleClick&&cal.dateClicked)cal.callCloseHandler();};if(params.flat!=null){if(typeof params.flat=="string")params.flat=document.getElementById(params.flat);if(!params.flat){alert("Calendar.setup:\n Flat specified but can't find parent.");return false;}var cal=new Calendar(params.firstDay,params.date,params.onSelect||onSelect);cal.showsOtherMonths=params.showOthers;cal.showsTime=params.showsTime;cal.time24=(params.timeFormat=="24");cal.params=params;cal.weekNumbers=params.weekNumbers;cal.setRange(params.range[0],params.range[1]);cal.setDateStatusHandler(params.dateStatusFunc);cal.getDateText=params.dateText;if(params.ifFormat){cal.setDateFormat(params.ifFormat);}if(params.inputField&&typeof params.inputField.value=="string"){cal.parseDate(params.inputField.value);}cal.create(params.flat);cal.show();return false;}var triggerEl=params.button||params.displayArea||params.inputField;triggerEl["on"+params.eventName]=function(){var dateEl=params.inputField||params.displayArea;var dateFmt=params.inputField?params.ifFormat:params.daFormat;var mustCreate=false;var cal=window.calendar;if(dateEl)params.date=Date.parseDate(dateEl.value||dateEl.innerHTML,dateFmt);if(!(cal&&params.cache)){window.calendar=cal=new Calendar(params.firstDay,params.date,params.onSelect||onSelect,params.onClose||function(cal){cal.hide();});cal.showsTime=params.showsTime;cal.time24=(params.timeFormat=="24");cal.weekNumbers=params.weekNumbers;mustCreate=true;}else{if(params.date)cal.setDate(params.date);cal.hide();}if(params.multiple){cal.multiple={};for(var i=params.multiple.length;--i>=0;){var d=params.multiple[i];var ds=d.print("%Y%m%d");cal.multiple[ds]=d;}}cal.showsOtherMonths=params.showOthers;cal.yearStep=params.step;cal.setRange(params.range[0],params.range[1]);cal.params=params;cal.setDateStatusHandler(params.dateStatusFunc);cal.getDateText=params.dateText;cal.setDateFormat(dateFmt);if(mustCreate)cal.create();cal.refresh();if(!params.position)cal.showAtElement(params.button||params.displayArea||params.inputField,params.align);else cal.showAt(params.position[0],params.position[1]);return false;};return cal;};
