/*
 * jQuery validation plug-in post1.5
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.validate.js 5957 2008-11-30 12:46:18Z joern.zaefferer $
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */

(function($) {

$.extend($.fn, {
 // http://docs.jquery.com/Plugins/Validation/validate
 validate: function( options ) {
 
 // if nothing is selected, return nothing; can't chain anyway
 if (!this.length) {
 options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
 return;
 }
 
 // check if a validator for this form was already created
 var validator = $.data(this[0], 'validator');
 if ( validator ) {
 return validator;
 }
 
 validator = new $.validator( options, this[0] );
 $.data(this[0], 'validator', validator); 
 
 if ( validator.settings.onsubmit ) {
 
 // allow suppresing validation by adding a cancel class to the submit button
 this.find("input, button").filter(".cancel").click(function() {
 validator.cancelSubmit = true;
 });
 
 // validate the form on submit
 this.submit( function( event ) {
 if ( validator.settings.debug )
 // prevent form submit to be able to see console output
 event.preventDefault();
 
 function handle() {
 if ( validator.settings.submitHandler ) {
 validator.settings.submitHandler.call( validator, validator.currentForm );
 return false;
 }
 return true;
 }
 
 // prevent submit for invalid forms or custom submit handlers
 if ( validator.cancelSubmit ) {
 validator.cancelSubmit = false;
 return handle();
 }
 if ( validator.form() ) {
 if ( validator.pendingRequest ) {
 validator.formSubmitted = true;
 return false;
 }
 return handle();
 } else {
 validator.focusInvalid();
 return false;
 }
 });
 }
 
 return validator;
 },
 // http://docs.jquery.com/Plugins/Validation/valid
 valid: function() {
 if ( $(this[0]).is('form')) {
 return this.validate().form();
 } else {
 var valid = false;
 var validator = $(this[0].form).validate();
 this.each(function() {
 valid |= validator.element(this);
 });
 return valid;
 }
 },
 // attributes: space seperated list of attributes to retrieve and remove
 removeAttrs: function(attributes) {
 var result = {},
 $element = this;
 $.each(attributes.split(/\s/), function() {
 result[this] = $element.attr(this);
 $element.removeAttr(this);
 });
 return result;
 },
 // http://docs.jquery.com/Plugins/Validation/rules
 rules: function(command, argument) {
 var element = this[0];
 
 if (command) {
 var settings = $.data(element.form, 'validator').settings;
 var staticRules = settings.rules;
 var existingRules = $.validator.staticRules(element);
 switch(command) {
 case "add":
 $.extend(existingRules, $.validator.normalizeRule(argument));
 staticRules[element.name] = existingRules;
 if (argument.messages)
 settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
 break;
 case "remove":
 if (!argument) {
 delete staticRules[element.name];
 return existingRules;
 }
 var filtered = {};
 $.each(argument.split(/\s/), function(index, method) {
 filtered[method] = existingRules[method];
 delete existingRules[method];
 });
 return filtered;
 }
 }
 
 var data = $.validator.normalizeRules(
 $.extend(
 {},
 $.validator.metadataRules(element),
 $.validator.classRules(element),
 $.validator.attributeRules(element),
 $.validator.staticRules(element)
 ), element);
 
 // make sure required is at front
 if (data.required) {
 var param = data.required;
 delete data.required;
 data = $.extend({required: param}, data);
 }
 
 return data;
 },
 // destructive add
 push: function( t ) {
 return this.setArray( this.add(t).get() );
 }
});

// Custom selectors
$.extend($.expr[":"], {
 // http://docs.jquery.com/Plugins/Validation/blank
 blank: function(a) {return !$.trim(a.value);},
 // http://docs.jquery.com/Plugins/Validation/filled
 filled: function(a) {return !!$.trim(a.value);},
 // http://docs.jquery.com/Plugins/Validation/unchecked
 unchecked: function(a) {return !a.checked;}
});


$.format = function(source, params) {
 if ( arguments.length == 1 ) 
 return function() {
 var args = $.makeArray(arguments);
 args.unshift(source);
 return $.format.apply( this, args );
 };
 if ( arguments.length > 2 && params.constructor != Array ) {
 params = $.makeArray(arguments).slice(1);
 }
 if ( params.constructor != Array ) {
 params = [ params ];
 }
 $.each(params, function(i, n) {
 source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
 });
 return source;
};

// constructor for validator
$.validator = function( options, form ) {
 this.settings = $.extend( {}, $.validator.defaults, options );
 this.currentForm = form;
 this.init();
};

$.extend($.validator, {

 defaults: {
 messages: {},
 groups: {},
 rules: {},
 errorClass: "error",
 errorElement: "label",
 focusInvalid: true,
 errorContainer: $( [] ),
 errorLabelContainer: $( [] ),
 onsubmit: true,
 ignore: [],
 ignoreTitle: false,
 onfocusin: function(element) {
 this.lastActive = element;
 
 // hide error label and remove error class on focus if enabled
 if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
 this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass );
 this.errorsFor(element).hide();
 }
 },
 onfocusout: function(element) {
 if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
 this.element(element);
 }
 },
 onkeyup: function(element) {
 if ( element.name in this.submitted || element == this.lastElement ) {
 this.element(element);
 }
 },
 onclick: function(element) {
 if ( element.name in this.submitted )
 this.element(element);
 },
 highlight: function( element, errorClass ) {
 $( element ).addClass( errorClass );
 },
 unhighlight: function( element, errorClass ) {
 $( element ).removeClass( errorClass );
 }
 },

 // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
 setDefaults: function(settings) {
 $.extend( $.validator.defaults, settings );
 },

 messages: {
 required: "This field is required.",
 remote: "Please fix this field.",
 email: "Please enter a valid email address.",
 url: "Please enter a valid URL.",
 date: "Please enter a valid date.",
 dateISO: "Please enter a valid date (ISO).",
 dateDE: "Bitte geben Sie ein gültiges Datum ein.",
 number: "Please enter a valid number.",
 numberDE: "Bitte geben Sie eine Nummer ein.",
 digits: "Please enter only digits",
 creditcard: "Please enter a valid credit card number.",
 equalTo: "Please enter the same value again.",
 accept: "Please enter a value with a valid extension.",
 maxlength: $.format("Please enter no more than {0} characters."),
 minlength: $.format("Please enter at least {0} characters."),
 rangelength: $.format("Please enter a value between {0} and {1} characters long."),
 range: $.format("Please enter a value between {0} and {1}."),
 max: $.format("Please enter a value less than or equal to {0}."),
 min: $.format("Please enter a value greater than or equal to {0}.")
 },
 
 autoCreateRanges: false,
 
 prototype: {
 
 init: function() {
 this.labelContainer = $(this.settings.errorLabelContainer);
 this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
 this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
 this.submitted = {};
 this.valueCache = {};
 this.pendingRequest = 0;
 this.pending = {};
 this.invalid = {};
 this.reset();
 
 var groups = (this.groups = {});
 $.each(this.settings.groups, function(key, value) {
 $.each(value.split(/\s/), function(index, name) {
 groups[name] = key;
 });
 });
 var rules = this.settings.rules;
 $.each(rules, function(key, value) {
 rules[key] = $.validator.normalizeRule(value);
 });
 
 function delegate(event) {
 var validator = $.data(this[0].form, "validator");
 validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] );
 }
 $(this.currentForm)
 .delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate)
 .delegate("click", ":radio, :checkbox", delegate);

 if (this.settings.invalidHandler)
 $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
 },

 // http://docs.jquery.com/Plugins/Validation/Validator/form
 form: function() {
 this.checkForm();
 $.extend(this.submitted, this.errorMap);
 this.invalid = $.extend({}, this.errorMap);
 if (!this.valid())
 $(this.currentForm).triggerHandler("invalid-form", [this]);
 this.showErrors();
 return this.valid();
 },
 
 checkForm: function() {
 this.prepareForm();
 for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
 this.check( elements[i] );
 }
 return this.valid(); 
 },
 
 // http://docs.jquery.com/Plugins/Validation/Validator/element
 element: function( element ) {
 element = this.clean( element );
 this.lastElement = element;
 this.prepareElement( element );
 this.currentElements = $(element);
 var result = this.check( element );
 if ( result ) {
 delete this.invalid[element.name];
 } else {
 this.invalid[element.name] = true;
 }
 if ( !this.numberOfInvalids() ) {
 // Hide error containers on last error
 this.toHide.push( this.containers );
 }
 this.showErrors();
 return result;
 },

 // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
 showErrors: function(errors) {
 if(errors) {
 // add items to error list and map
 $.extend( this.errorMap, errors );
 this.errorList = [];
 for ( var name in errors ) {
 this.errorList.push({
 message: errors[name],
 element: this.findByName(name)[0]
 });
 }
 // remove items from success list
 this.successList = $.grep( this.successList, function(element) {
 return !(element.name in errors);
 });
 }
 this.settings.showErrors
 ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
 : this.defaultShowErrors();
 },
 
 // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
 resetForm: function() {
 if ( $.fn.resetForm )
 $( this.currentForm ).resetForm();
 this.submitted = {};
 this.prepareForm();
 this.hideErrors();
 this.elements().removeClass( this.settings.errorClass );
 },
 
 numberOfInvalids: function() {
 return this.objectLength(this.invalid);
 },
 
 objectLength: function( obj ) {
 var count = 0;
 for ( var i in obj )
 count++;
 return count;
 },
 
 hideErrors: function() {
 this.addWrapper( this.toHide ).hide();
 },
 
 valid: function() {
 return this.size() == 0;
 },
 
 size: function() {
 return this.errorList.length;
 },
 
 focusInvalid: function() {
 if( this.settings.focusInvalid ) {
 try {
 $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus();
 } catch(e) {
 // ignore IE throwing errors when focusing hidden elements
 }
 }
 },
 
 findLastActive: function() {
 var lastActive = this.lastActive;
 return lastActive && $.grep(this.errorList, function(n) {
 return n.element.name == lastActive.name;
 }).length == 1 && lastActive;
 },
 
 elements: function() {
 var validator = this,
 rulesCache = {};
 
 // select all valid inputs inside the form (no submit or reset buttons)
 // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
 return $([]).add(this.currentForm.elements)
 .filter(":input")
 .not(":submit, :reset, :image, [disabled]")
 .not( this.settings.ignore )
 .filter(function() {
 !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
 
 // select only the first element for each name, and only those with rules specified
 if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
 return false;
 
 rulesCache[this.name] = true;
 return true;
 });
 },
 
 clean: function( selector ) {
 return $( selector )[0];
 },
 
 errors: function() {
 return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
 },
 
 reset: function() {
 this.successList = [];
 this.errorList = [];
 this.errorMap = {};
 this.toShow = $([]);
 this.toHide = $([]);
 this.formSubmitted = false;
 this.currentElements = $([]);
 },
 
 prepareForm: function() {
 this.reset();
 this.toHide = this.errors().push( this.containers );
 },
 
 prepareElement: function( element ) {
 this.reset();
 this.toHide = this.errorsFor(element);
 },
 
 check: function( element ) {
 element = this.clean( element );
 
 // if radio/checkbox, validate first element in group instead
 if (this.checkable(element)) {
 element = this.findByName( element.name )[0];
 }
 
 var rules = $(element).rules();
 var dependencyMismatch = false;
 for( method in rules ) {
 var rule = { method: method, parameters: rules[method] };
 try {
 var result = $.validator.methods[method].call( this, element.value, element, rule.parameters );
 
 // if a method indicates that the field is optional and therefore valid,
 // don't mark it as valid when there are no other rules
 if ( result == "dependency-mismatch" ) {
 dependencyMismatch = true;
 continue;
 }
 dependencyMismatch = false;
 
 if ( result == "pending" ) {
 this.toHide = this.toHide.not( this.errorsFor(element) );
 return;
 }
 
 if( !result ) {
 this.formatAndAdd( element, rule );
 return false;
 }
 } catch(e) {
 this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
 + ", check the '" + rule.method + "' method");
 throw e;
 }
 }
 if (dependencyMismatch)
 return;
 if ( this.objectLength(rules) )
 this.successList.push(element);
 return true;
 },
 
 // return the custom message for the given element and validation method
 // specified in the element's "messages" metadata
 customMetaMessage: function(element, method) {
 if (!$.metadata)
 return;
 
 var meta = this.settings.meta
 ? $(element).metadata()[this.settings.meta]
 : $(element).metadata();
 
 return meta && meta.messages && meta.messages[method];
 },
 
 // return the custom message for the given element name and validation method
 customMessage: function( name, method ) {
 var m = this.settings.messages[name];
 return m && (m.constructor == String
 ? m
 : m[method]);
 },
 
 // return the first defined argument, allowing empty strings
 findDefined: function() {
 for(var i = 0; i < arguments.length; i++) {
 if (arguments[i] !== undefined)
 return arguments[i];
 }
 return undefined;
 },
 
 defaultMessage: function( element, method) {
 return this.findDefined(
 this.customMessage( element.name, method ),
 this.customMetaMessage( element, method ),
 // title is never undefined, so handle empty string as undefined
 !this.settings.ignoreTitle && element.title || undefined,
 $.validator.messages[method],
 "<strong>Warning: No message defined for " + element.name + "</strong>"
 );
 },
 
 formatAndAdd: function( element, rule ) {
 var message = this.defaultMessage( element, rule.method );
 if ( typeof message == "function" ) 
 message = message.call(this, rule.parameters, element);
 this.errorList.push({
 message: message,
 element: element
 });
 this.errorMap[element.name] = message;
 this.submitted[element.name] = message;
 },
 
 addWrapper: function(toToggle) {
 if ( this.settings.wrapper )
 toToggle.push( toToggle.parents( this.settings.wrapper ) );
 return toToggle;
 },
 
 defaultShowErrors: function() {
 for ( var i = 0; this.errorList[i]; i++ ) {
 var error = this.errorList[i];
 this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass );
 this.showLabel( error.element, error.message );
 }
 if( this.errorList.length ) {
 this.toShow.push( this.containers );
 }
 if (this.settings.success) {
 for ( var i = 0; this.successList[i]; i++ ) {
 this.showLabel( this.successList[i] );
 }
 }
 if (this.settings.unhighlight) {
 for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
 this.settings.unhighlight.call( this, elements[i], this.settings.errorClass );
 }
 }
 this.toHide = this.toHide.not( this.toShow );
 this.hideErrors();
 this.addWrapper( this.toShow ).show();
 },
 
 validElements: function() {
 return this.currentElements.not(this.invalidElements());
 },
 
 invalidElements: function() {
 return $(this.errorList).map(function() {
 return this.element;
 });
 },
 
 showLabel: function(element, message) {
 var label = this.errorsFor( element );
 if ( label.length ) {
 // refresh error/success class
 label.removeClass().addClass( this.settings.errorClass );
 
 // check if we have a generated label, replace the message then
 label.attr("generated") && label.html(message);
 } else {
 // create label
 label = $("<" + this.settings.errorElement + "/>")
 .attr({"for": this.idOrName(element), generated: true})
 .addClass(this.settings.errorClass)
 .html(message || "");
 if ( this.settings.wrapper ) {
 // make sure the element is visible, even in IE
 // actually showing the wrapped element is handled elsewhere
 label = label.hide().show().wrap("<" + this.settings.wrapper + ">").parent();
 }
 if ( !this.labelContainer.append(label).length )
 this.settings.errorPlacement
 ? this.settings.errorPlacement(label, $(element) )
 : label.insertAfter(element);
 }
 if ( !message && this.settings.success ) {
 label.text("");
 typeof this.settings.success == "string"
 ? label.addClass( this.settings.success )
 : this.settings.success( label );
 }
 this.toShow.push(label);
 },
 
 errorsFor: function(element) {
 return this.errors().filter("[@for='" + this.idOrName(element) + "']");
 },
 
 idOrName: function(element) {
 return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
 },

 checkable: function( element ) {
 return /radio|checkbox/i.test(element.type);
 },
 
 findByName: function( name ) {
 // select by name and filter by form for performance over form.find("[name=...]")
 var form = this.currentForm;
 return $(document.getElementsByName(name)).map(function(index, element) {
 return element.form == form && element.name == name && element || null;
 });
 },
 
 getLength: function(value, element) {
 switch( element.nodeName.toLowerCase() ) {
 case 'select':
 return $("option:selected", element).length;
 case 'input':
 if( this.checkable( element) )
 return this.findByName(element.name).filter(':checked').length;
 }
 return value.length;
 },
 
 depend: function(param, element) {
 return this.dependTypes[typeof param]
 ? this.dependTypes[typeof param](param, element)
 : true;
 },
 
 dependTypes: {
 "boolean": function(param, element) {
 return param;
 },
 "string": function(param, element) {
 return !!$(param, element.form).length;
 },
 "function": function(param, element) {
 return param(element);
 }
 },
 
 optional: function(element) {
 return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
 },
 
 startRequest: function(element) {
 if (!this.pending[element.name]) {
 this.pendingRequest++;
 this.pending[element.name] = true;
 }
 },
 
 stopRequest: function(element, valid) {
 this.pendingRequest--;
 // sometimes synchronization fails, make sure pendingRequest is never < 0
 if (this.pendingRequest < 0)
 this.pendingRequest = 0;
 delete this.pending[element.name];
 if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
 $(this.currentForm).submit();
 } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
 $(this.currentForm).triggerHandler("invalid-form", [this]);
 }
 },
 
 previousValue: function(element) {
 return $.data(element, "previousValue") || $.data(element, "previousValue", previous = {
 old: null,
 valid: true,
 message: this.defaultMessage( element, "remote" )
 });
 }
 
 },
 
 classRuleSettings: {
 required: {required: true},
 email: {email: true},
 url: {url: true},
 date: {date: true},
 dateISO: {dateISO: true},
 dateDE: {dateDE: true},
 number: {number: true},
 numberDE: {numberDE: true},
 digits: {digits: true},
 creditcard: {creditcard: true}
 },
 
 addClassRules: function(className, rules) {
 className.constructor == String ?
 this.classRuleSettings[className] = rules :
 $.extend(this.classRuleSettings, className);
 },
 
 classRules: function(element) {
 var rules = {};
 var classes = $(element).attr('class');
 classes && $.each(classes.split(' '), function() {
 if (this in $.validator.classRuleSettings) {
 $.extend(rules, $.validator.classRuleSettings[this]);
 }
 });
 return rules;
 },
 
 attributeRules: function(element) {
 var rules = {};
 var $element = $(element);
 
 for (method in $.validator.methods) {
 var value = $element.attr(method);
 if (value) {
 rules[method] = value;
 }
 }
 
 // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
 if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
 delete rules.maxlength;
 }
 
 return rules;
 },
 
 metadataRules: function(element) {
 if (!$.metadata) return {};
 
 var meta = $.data(element.form, 'validator').settings.meta;
 return meta ?
 $(element).metadata()[meta] :
 $(element).metadata();
 },
 
 staticRules: function(element) {
 var rules = {};
 var validator = $.data(element.form, 'validator');
 if (validator.settings.rules) {
 rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
 }
 return rules;
 },
 
 normalizeRules: function(rules, element) {
 // handle dependency check
 $.each(rules, function(prop, val) {
 // ignore rule when param is explicitly false, eg. required:false
 if (val === false) {
 delete rules[prop];
 return;
 }
 if (val.param || val.depends) {
 var keepRule = true;
 switch (typeof val.depends) {
 case "string":
 keepRule = !!$(val.depends, element.form).length;
 break;
 case "function":
 keepRule = val.depends.call(element, element);
 break;
 }
 if (keepRule) {
 rules[prop] = val.param !== undefined ? val.param : true;
 } else {
 delete rules[prop];
 }
 }
 });
 
 // evaluate parameters
 $.each(rules, function(rule, parameter) {
 rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
 });
 
 // clean number parameters
 $.each(['minlength', 'maxlength', 'min', 'max'], function() {
 if (rules[this]) {
 rules[this] = Number(rules[this]);
 }
 });
 $.each(['rangelength', 'range'], function() {
 if (rules[this]) {
 rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
 }
 });
 
 if ($.validator.autoCreateRanges) {
 // auto-create ranges
 if (rules.min && rules.max) {
 rules.range = [rules.min, rules.max];
 delete rules.min;
 delete rules.max;
 }
 if (rules.minlength && rules.maxlength) {
 rules.rangelength = [rules.minlength, rules.maxlength];
 delete rules.minlength;
 delete rules.maxlength;
 }
 }
 
 // To support custom messages in metadata ignore rule methods titled "messages"
 if (rules.messages) {
 delete rules.messages
 }
 
 return rules;
 },
 
 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
 normalizeRule: function(data) {
 if( typeof data == "string" ) {
 var transformed = {};
 $.each(data.split(/\s/), function() {
 transformed[this] = true;
 });
 data = transformed;
 }
 return data;
 },
 
 // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
 addMethod: function(name, method, message) {
 $.validator.methods[name] = method;
 $.validator.messages[name] = message;
 if (method.length < 3) {
 $.validator.addClassRules(name, $.validator.normalizeRule(name));
 }
 },

 methods: {

 // http://docs.jquery.com/Plugins/Validation/Methods/required
 required: function(value, element, param) {
 // check if dependency is met
 if ( !this.depend(param, element) )
 return "dependency-mismatch";
 switch( element.nodeName.toLowerCase() ) {
 case 'select':
 var options = $("option:selected", element);
 return options.length > 0 && ( element.type == "select-multiple" || ($.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);
 case 'input':
 if ( this.checkable(element) )
 return this.getLength(value, element) > 0;
 default:
 return $.trim(value).length > 0;
 }
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/remote
 remote: function(value, element, param) {
 if ( this.optional(element) )
 return "dependency-mismatch";
 
 var previous = this.previousValue(element);
 
 if (!this.settings.messages[element.name] )
 this.settings.messages[element.name] = {};
 this.settings.messages[element.name].remote = typeof previous.message == "function" ? previous.message(value) : previous.message;
 
 param = typeof param == "string" && {url:param} || param; 
 
 if ( previous.old !== value ) {
 previous.old = value;
 var validator = this;
 this.startRequest(element);
 var data = {};
 data[element.name] = value;
 $.ajax($.extend(true, {
 url: param,
 mode: "abort",
 port: "validate" + element.name,
 dataType: "json",
 data: data,
 success: function(response) {
 if ( response ) {
 var submitted = validator.formSubmitted;
 validator.prepareElement(element);
 validator.formSubmitted = submitted;
 validator.successList.push(element);
 validator.showErrors();
 } else {
 var errors = {};
 errors[element.name] = response || validator.defaultMessage( element, "remote" );
 validator.showErrors(errors);
 }
 previous.valid = response;
 validator.stopRequest(element, response);
 }
 }, param));
 return "pending";
 } else if( this.pending[element.name] ) {
 return "pending";
 }
 return previous.valid;
 },

 // http://docs.jquery.com/Plugins/Validation/Methods/minlength
 minlength: function(value, element, param) {
 return this.optional(element) || this.getLength(value, element) >= param;
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
 maxlength: function(value, element, param) {
 return this.optional(element) || this.getLength(value, element) <= param;
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
 rangelength: function(value, element, param) {
 var length = this.getLength(value, element);
 return this.optional(element) || ( length >= param[0] && length <= param[1] );
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/min
 min: function( value, element, param ) {
 return this.optional(element) || value >= param;
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/max
 max: function( value, element, param ) {
 return this.optional(element) || value <= param;
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/range
 range: function( value, element, param ) {
 return this.optional(element) || ( value >= param[0] && value <= param[1] );
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/email
 email: function(value, element) {
 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
 return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/url
 url: function(value, element) {
 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
 return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/date
 date: function(value, element) {
 return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
 dateISO: function(value, element) {
 return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/dateDE
 dateDE: function(value, element) {
 return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/number
 number: function(value, element) {
 return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/numberDE
 numberDE: function(value, element) {
 return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/digits
 digits: function(value, element) {
 return this.optional(element) || /^\d+$/.test(value);
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
 // based on http://en.wikipedia.org/wiki/Luhn
 creditcard: function(value, element) {
 if ( this.optional(element) )
 return "dependency-mismatch";
 // accept only digits and dashes
 if (/[^0-9-]+/.test(value))
 return false;
 var nCheck = 0,
 nDigit = 0,
 bEven = false;

 value = value.replace(/\D/g, "");

 for (n = value.length - 1; n >= 0; n--) {
 var cDigit = value.charAt(n);
 var nDigit = parseInt(cDigit, 10);
 if (bEven) {
 if ((nDigit *= 2) > 9)
 nDigit -= 9;
 }
 nCheck += nDigit;
 bEven = !bEven;
 }

 return (nCheck % 10) == 0;
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/accept
 accept: function(value, element, param) {
 param = typeof param == "string" ? param : "png|jpe?g|gif";
 return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
 },
 
 // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
 equalTo: function(value, element, param) {
 return value == $(param).val();
 }
 
 }
 
});

})(jQuery);

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
;(function($) {
 var ajax = $.ajax;
 var pendingRequests = {};
 $.ajax = function(settings) {
 // create settings for compatibility with ajaxSetup
 settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
 var port = settings.port;
 if (settings.mode == "abort") {
 if ( pendingRequests[port] ) {
 pendingRequests[port].abort();
 }
 return (pendingRequests[port] = ajax.apply(this, arguments));
 }
 return ajax.apply(this, arguments);
 };
})(jQuery);

// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 

// provides triggerEvent(type: String, target: Element) to trigger delegated events
;(function($) {
 $.each({
 focus: 'focusin',
 blur: 'focusout' 
 }, function( original, fix ){
 $.event.special[fix] = {
 setup:function() {
 if ( $.browser.msie ) return false;
 this.addEventListener( original, $.event.special[fix].handler, true );
 },
 teardown:function() {
 if ( $.browser.msie ) return false;
 this.removeEventListener( original,
 $.event.special[fix].handler, true );
 },
 handler: function(e) {
 arguments[0] = $.event.fix(e);
 arguments[0].type = fix;
 return $.event.handle.apply(this, arguments);
 }
 };
 });
 $.extend($.fn, {
 delegate: function(type, delegate, handler) {
 return this.bind(type, function(event) {
 var target = $(event.target);
 if (target.is(delegate)) {
 return handler.apply(target, arguments);
 }
 });
 },
 triggerEvent: function(type, target) {
 return this.triggerHandler(type, [$.event.fix({ type: type, target: target })]);
 }
 })
})(jQuery);

/*!
 * jQuery Cycle Plugin (with Transition Definitions)
 * Examples and documentation at: http://jquery.malsup.com/cycle/
 * Copyright (c) 2007-2009 M. Alsup
 * Version: 2.72 (09-SEP-2009)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * Requires: jQuery v1.2.6 or later
 *
 * Originally based on the work of:
 * 1) Matt Oakes
 * 2) Torsten Baldes (http://medienfreunde.com/lab/innerfade/)
 * 3) Benjamin Sterling (http://www.benjaminsterling.com/experiments/jqShuffle/)
 */
;(function($) {

var ver = '2.72';

// if $.support is not defined (pre jQuery 1.3) add what I need
if ($.support == undefined) {
 $.support = {
 opacity: !($.browser.msie)
 };
}

function debug(s) {
 if ($.fn.cycle.debug)
 log(s);
} 
function log() {
 if (window.console && window.console.log)
 window.console.log('[cycle] ' + Array.prototype.join.call(arguments,' '));
 //$('body').append('<div>'+Array.prototype.join.call(arguments,' ')+'</div>');
};

// the options arg can be...
// a number - indicates an immediate transition should occur to the given slide index
// a string - 'stop', 'pause', 'resume', or the name of a transition effect (ie, 'fade', 'zoom', etc)
// an object - properties to control the slideshow
//
// the arg2 arg can be...
// the name of an fx (only used in conjunction with a numeric value for 'options')
// the value true (only used in conjunction with a options == 'resume') and indicates
// that the resume should occur immediately (not wait for next timeout)

$.fn.cycle = function(options, arg2) {
 var o = { s: this.selector, c: this.context };

 // in 1.3+ we can fix mistakes with the ready state
 if (this.length === 0 && options != 'stop') {
 if (!$.isReady && o.s) {
 log('DOM not ready, queuing slideshow');
 $(function() {
 $(o.s,o.c).cycle(options,arg2);
 });
 return this;
 }
 // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
 log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
 return this;
 }

 // iterate the matched nodeset
 return this.each(function() {
 var opts = handleArguments(this, options, arg2);
 if (opts === false)
 return;

 // stop existing slideshow for this container (if there is one)
 if (this.cycleTimeout)
 clearTimeout(this.cycleTimeout);
 this.cycleTimeout = this.cyclePause = 0;

 var $cont = $(this);
 var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children();
 var els = $slides.get();
 if (els.length < 2) {
 log('terminating; too few slides: ' + els.length);
 return;
 }

 var opts2 = buildOptions($cont, $slides, els, opts, o);
 if (opts2 === false)
 return;

 var startTime = opts2.continuous ? 10 : getTimeout(opts2.currSlide, opts2.nextSlide, opts2, !opts2.rev);

 // if it's an auto slideshow, kick it off
 if (startTime) {
 startTime += (opts2.delay || 0);
 if (startTime < 10)
 startTime = 10;
 debug('first timeout: ' + startTime);
 this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts2.rev)}, startTime);
 }
 });
};

// process the args that were passed to the plugin fn
function handleArguments(cont, options, arg2) {
 if (cont.cycleStop == undefined)
 cont.cycleStop = 0;
 if (options === undefined || options === null)
 options = {};
 if (options.constructor == String) {
 switch(options) {
 case 'stop':
 cont.cycleStop++; // callbacks look for change
 if (cont.cycleTimeout)
 clearTimeout(cont.cycleTimeout);
 cont.cycleTimeout = 0;
 $(cont).removeData('cycle.opts');
 return false;
 case 'pause':
 cont.cyclePause = 1;
 return false;
 case 'resume':
 cont.cyclePause = 0;
 if (arg2 === true) { // resume now!
 options = $(cont).data('cycle.opts');
 if (!options) {
 log('options not found, can not resume');
 return false;
 }
 if (cont.cycleTimeout) {
 clearTimeout(cont.cycleTimeout);
 cont.cycleTimeout = 0;
 }
 go(options.elements, options, 1, 1);
 }
 return false;
 case 'prev':
 case 'next':
 var opts = $(cont).data('cycle.opts');
 if (!opts) {
 log('options not found, "prev/next" ignored');
 return false;
 }
 $.fn.cycle[options](opts);
 return false;
 default:
 options = { fx: options };
 };
 return options;
 }
 else if (options.constructor == Number) {
 // go to the requested slide
 var num = options;
 options = $(cont).data('cycle.opts');
 if (!options) {
 log('options not found, can not advance slide');
 return false;
 }
 if (num < 0 || num >= options.elements.length) {
 log('invalid slide index: ' + num);
 return false;
 }
 options.nextSlide = num;
 if (cont.cycleTimeout) {
 clearTimeout(cont.cycleTimeout);
 cont.cycleTimeout = 0;
 }
 if (typeof arg2 == 'string')
 options.oneTimeFx = arg2;
 go(options.elements, options, 1, num >= options.currSlide);
 return false;
 }
 return options;
};

function removeFilter(el, opts) {
 if (!$.support.opacity && opts.cleartype && el.style.filter) {
 try { el.style.removeAttribute('filter'); }
 catch(smother) {} // handle old opera versions
 }
};

// one-time initialization
function buildOptions($cont, $slides, els, options, o) {
 // support metadata plugin (v1.0 and v2.0)
 var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
 if (opts.autostop)
 opts.countdown = opts.autostopCount || els.length;

 var cont = $cont[0];
 $cont.data('cycle.opts', opts);
 opts.$cont = $cont;
 opts.stopCount = cont.cycleStop;
 opts.elements = els;
 opts.before = opts.before ? [opts.before] : [];
 opts.after = opts.after ? [opts.after] : [];
 opts.after.unshift(function(){ opts.busy=0; });

 // push some after callbacks
 if (!$.support.opacity && opts.cleartype)
 opts.after.push(function() { removeFilter(this, opts); });
 if (opts.continuous)
 opts.after.push(function() { go(els,opts,0,!opts.rev); });

 saveOriginalOpts(opts);

 // clearType corrections
 if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
 clearTypeFix($slides);

 // container requires non-static position so that slides can be position within
 if ($cont.css('position') == 'static')
 $cont.css('position', 'relative');
 if (opts.width)
 $cont.width(opts.width);
 if (opts.height && opts.height != 'auto')
 $cont.height(opts.height);

 if (opts.startingSlide)
 opts.startingSlide = parseInt(opts.startingSlide);

 // if random, mix up the slide array
 if (opts.random) {
 opts.randomMap = [];
 for (var i = 0; i < els.length; i++)
 opts.randomMap.push(i);
 opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
 opts.randomIndex = 0;
 opts.startingSlide = opts.randomMap[0];
 }
 else if (opts.startingSlide >= els.length)
 opts.startingSlide = 0; // catch bogus input
 opts.currSlide = opts.startingSlide = opts.startingSlide || 0;
 var first = opts.startingSlide;

 // set position and zIndex on all the slides
 $slides.css({position: 'absolute',top:0,left:0}).hide().each(function(i) {
 var z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
 $(this).css('z-index', z)
 });

 // make sure first slide is visible
 $(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case
 removeFilter(els[first], opts);

 // stretch slides
 if (opts.fit && opts.width)
 $slides.width(opts.width);
 if (opts.fit && opts.height && opts.height != 'auto')
 $slides.height(opts.height);

 // stretch container
 var reshape = opts.containerResize && !$cont.innerHeight();
 if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9
 var maxw = 0, maxh = 0;
 for(var j=0; j < els.length; j++) {
 var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight();
 if (!w) w = e.offsetWidth;
 if (!h) h = e.offsetHeight;
 maxw = w > maxw ? w : maxw;
 maxh = h > maxh ? h : maxh;
 }
 if (maxw > 0 && maxh > 0)
 $cont.css({width:maxw+'px',height:maxh+'px'});
 }

 if (opts.pause)
 $cont.hover(function(){this.cyclePause++;},function(){this.cyclePause--;});

 if (supportMultiTransitions(opts) === false)
 return false;

 // apparently a lot of people use image slideshows without height/width attributes on the images.
 // Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that.
 var requeue = false;
 options.requeueAttempts = options.requeueAttempts || 0;
 $slides.each(function() {
 // try to get height/width of each slide
 var $el = $(this);
 this.cycleH = (opts.fit && opts.height) ? opts.height : $el.height();
 this.cycleW = (opts.fit && opts.width) ? opts.width : $el.width();

 if ( $el.is('img') ) {
 // sigh.. sniffing, hacking, shrugging... this crappy hack tries to account for what browsers do when
 // an image is being downloaded and the markup did not include sizing info (height/width attributes);
 // there seems to be some "default" sizes used in this situation
 var loadingIE = ($.browser.msie && this.cycleW == 28 && this.cycleH == 30 && !this.complete);
 var loadingFF = ($.browser.mozilla && this.cycleW == 34 && this.cycleH == 19 && !this.complete);
 var loadingOp = ($.browser.opera && ((this.cycleW == 42 && this.cycleH == 19) || (this.cycleW == 37 && this.cycleH == 17)) && !this.complete);
 var loadingOther = (this.cycleH == 0 && this.cycleW == 0 && !this.complete);
 // don't requeue for images that are still loading but have a valid size
 if (loadingIE || loadingFF || loadingOp || loadingOther) {
 if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever
 log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH);
 setTimeout(function() {$(o.s,o.c).cycle(options)}, opts.requeueTimeout);
 requeue = true;
 return false; // break each loop
 }
 else {
 log('could not determine size of image: '+this.src, this.cycleW, this.cycleH);
 }
 }
 }
 return true;
 });

 if (requeue)
 return false;

 opts.cssBefore = opts.cssBefore || {};
 opts.animIn = opts.animIn || {};
 opts.animOut = opts.animOut || {};

 $slides.not(':eq('+first+')').css(opts.cssBefore);
 if (opts.cssFirst)
 $($slides[first]).css(opts.cssFirst);

 if (opts.timeout) {
 opts.timeout = parseInt(opts.timeout);
 // ensure that timeout and speed settings are sane
 if (opts.speed.constructor == String)
 opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed);
 if (!opts.sync)
 opts.speed = opts.speed / 2;
 while((opts.timeout - opts.speed) < 250) // sanitize timeout
 opts.timeout += opts.speed;
 }
 if (opts.easing)
 opts.easeIn = opts.easeOut = opts.easing;
 if (!opts.speedIn)
 opts.speedIn = opts.speed;
 if (!opts.speedOut)
 opts.speedOut = opts.speed;

 opts.slideCount = els.length;
 opts.currSlide = opts.lastSlide = first;
 if (opts.random) {
 opts.nextSlide = opts.currSlide;
 if (++opts.randomIndex == els.length)
 opts.randomIndex = 0;
 opts.nextSlide = opts.randomMap[opts.randomIndex];
 }
 else
 opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;

 // run transition init fn
 if (!opts.multiFx) {
 var init = $.fn.cycle.transitions[opts.fx];
 if ($.isFunction(init))
 init($cont, $slides, opts);
 else if (opts.fx != 'custom' && !opts.multiFx) {
 log('unknown transition: ' + opts.fx,'; slideshow terminating');
 return false;
 }
 }

 // fire artificial events
 var e0 = $slides[first];
 if (opts.before.length)
 opts.before[0].apply(e0, [e0, e0, opts, true]);
 if (opts.after.length > 1)
 opts.after[1].apply(e0, [e0, e0, opts, true]);

 if (opts.next)
 $(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,opts.rev?-1:1)});
 if (opts.prev)
 $(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,opts.rev?1:-1)});
 if (opts.pager)
 buildPager(els,opts);

 exposeAddSlide(opts, els);

 return opts;
};

// save off original opts so we can restore after clearing state
function saveOriginalOpts(opts) {
 opts.original = { before: [], after: [] };
 opts.original.cssBefore = $.extend({}, opts.cssBefore);
 opts.original.cssAfter = $.extend({}, opts.cssAfter);
 opts.original.animIn = $.extend({}, opts.animIn);
 opts.original.animOut = $.extend({}, opts.animOut);
 $.each(opts.before, function() { opts.original.before.push(this); });
 $.each(opts.after, function() { opts.original.after.push(this); });
};

function supportMultiTransitions(opts) {
 var i, tx, txs = $.fn.cycle.transitions;
 // look for multiple effects
 if (opts.fx.indexOf(',') > 0) {
 opts.multiFx = true;
 opts.fxs = opts.fx.replace(/\s*/g,'').split(',');
 // discard any bogus effect names
 for (i=0; i < opts.fxs.length; i++) {
 var fx = opts.fxs[i];
 tx = txs[fx];
 if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) {
 log('discarding unknown transition: ',fx);
 opts.fxs.splice(i,1);
 i--;
 }
 }
 // if we have an empty list then we threw everything away!
 if (!opts.fxs.length) {
 log('No valid transitions named; slideshow terminating.');
 return false;
 }
 }
 else if (opts.fx == 'all') { // auto-gen the list of transitions
 opts.multiFx = true;
 opts.fxs = [];
 for (p in txs) {
 tx = txs[p];
 if (txs.hasOwnProperty(p) && $.isFunction(tx))
 opts.fxs.push(p);
 }
 }
 if (opts.multiFx && opts.randomizeEffects) {
 // munge the fxs array to make effect selection random
 var r1 = Math.floor(Math.random() * 20) + 30;
 for (i = 0; i < r1; i++) {
 var r2 = Math.floor(Math.random() * opts.fxs.length);
 opts.fxs.push(opts.fxs.splice(r2,1)[0]);
 }
 debug('randomized fx sequence: ',opts.fxs);
 }
 return true;
};

// provide a mechanism for adding slides after the slideshow has started
function exposeAddSlide(opts, els) {
 opts.addSlide = function(newSlide, prepend) {
 var $s = $(newSlide), s = $s[0];
 if (!opts.autostopCount)
 opts.countdown++;
 els[prepend?'unshift':'push'](s);
 if (opts.els)
 opts.els[prepend?'unshift':'push'](s); // shuffle needs this
 opts.slideCount = els.length;

 $s.css('position','absolute');
 $s[prepend?'prependTo':'appendTo'](opts.$cont);

 if (prepend) {
 opts.currSlide++;
 opts.nextSlide++;
 }

 if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
 clearTypeFix($s);

 if (opts.fit && opts.width)
 $s.width(opts.width);
 if (opts.fit && opts.height && opts.height != 'auto')
 $slides.height(opts.height);
 s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
 s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();

 $s.css(opts.cssBefore);

 if (opts.pager)
 $.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);

 if ($.isFunction(opts.onAddSlide))
 opts.onAddSlide($s);
 else
 $s.hide(); // default behavior
 };
}

// reset internal state; we do this on every pass in order to support multiple effects
$.fn.cycle.resetState = function(opts, fx) {
 fx = fx || opts.fx;
 opts.before = []; opts.after = [];
 opts.cssBefore = $.extend({}, opts.original.cssBefore);
 opts.cssAfter = $.extend({}, opts.original.cssAfter);
 opts.animIn = $.extend({}, opts.original.animIn);
 opts.animOut = $.extend({}, opts.original.animOut);
 opts.fxFn = null;
 $.each(opts.original.before, function() { opts.before.push(this); });
 $.each(opts.original.after, function() { opts.after.push(this); });

 // re-init
 var init = $.fn.cycle.transitions[fx];
 if ($.isFunction(init))
 init(opts.$cont, $(opts.elements), opts);
};

// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt
function go(els, opts, manual, fwd) {
 // opts.busy is true if we're in the middle of an animation
 if (manual && opts.busy && opts.manualTrump) {
 // let manual transitions requests trump active ones
 $(els).stop(true,true);
 opts.busy = false;
 }
 // don't begin another timeout-based transition if there is one active
 if (opts.busy)
 return;

 var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide];

 // stop cycling if we have an outstanding stop request
 if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual)
 return;

 // check to see if we should stop cycling based on autostop options
 if (!manual && !p.cyclePause &&
 ((opts.autostop && (--opts.countdown <= 0)) ||
 (opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
 if (opts.end)
 opts.end(opts);
 return;
 }

 // if slideshow is paused, only transition on a manual trigger
 if (manual || !p.cyclePause) {
 var fx = opts.fx;
 // keep trying to get the slide size if we don't have it yet
 curr.cycleH = curr.cycleH || $(curr).height();
 curr.cycleW = curr.cycleW || $(curr).width();
 next.cycleH = next.cycleH || $(next).height();
 next.cycleW = next.cycleW || $(next).width();

 // support multiple transition types
 if (opts.multiFx) {
 if (opts.lastFx == undefined || ++opts.lastFx >= opts.fxs.length)
 opts.lastFx = 0;
 fx = opts.fxs[opts.lastFx];
 opts.currFx = fx;
 }

 // one-time fx overrides apply to: $('div').cycle(3,'zoom');
 if (opts.oneTimeFx) {
 fx = opts.oneTimeFx;
 opts.oneTimeFx = null;
 }

 $.fn.cycle.resetState(opts, fx);

 // run the before callbacks
 if (opts.before.length)
 $.each(opts.before, function(i,o) {
 if (p.cycleStop != opts.stopCount) return;
 o.apply(next, [curr, next, opts, fwd]);
 });

 // stage the after callacks
 var after = function() {
 $.each(opts.after, function(i,o) {
 if (p.cycleStop != opts.stopCount) return;
 o.apply(next, [curr, next, opts, fwd]);
 });
 };

 if (opts.nextSlide != opts.currSlide) {
 // get ready to perform the transition
 opts.busy = 1;
 if (opts.fxFn) // fx function provided?
 opts.fxFn(curr, next, opts, after, fwd);
 else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ?
 $.fn.cycle[opts.fx](curr, next, opts, after);
 else
 $.fn.cycle.custom(curr, next, opts, after, manual && opts.fastOnEvent);
 }

 // calculate the next slide
 opts.lastSlide = opts.currSlide;
 if (opts.random) {
 opts.currSlide = opts.nextSlide;
 if (++opts.randomIndex == els.length)
 opts.randomIndex = 0;
 opts.nextSlide = opts.randomMap[opts.randomIndex];
 }
 else { // sequence
 var roll = (opts.nextSlide + 1) == els.length;
 opts.nextSlide = roll ? 0 : opts.nextSlide+1;
 opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
 }

 if (opts.pager)
 $.fn.cycle.updateActivePagerLink(opts.pager, opts.currSlide);
 }

 // stage the next transtion
 var ms = 0;
 if (opts.timeout && !opts.continuous)
 ms = getTimeout(curr, next, opts, fwd);
 else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic
 ms = 10;
 if (ms > 0)
 p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.rev) }, ms);
};

// invoked after transition
$.fn.cycle.updateActivePagerLink = function(pager, currSlide) {
 $(pager).find('a').removeClass('activeSlide').filter('a:eq('+currSlide+')').addClass('activeSlide');
};

// calculate timeout value for current transition
function getTimeout(curr, next, opts, fwd) {
 if (opts.timeoutFn) {
 // call user provided calc fn
 var t = opts.timeoutFn(curr,next,opts,fwd);
 while ((t - opts.speed) < 250) // sanitize timeout
 t += opts.speed;
 debug('calculated timeout: ' + t + '; speed: ' + opts.speed);
 if (t !== false)
 return t;
 }
 return opts.timeout;
};

// expose next/prev function, caller must pass in state
$.fn.cycle.next = function(opts) { advance(opts, opts.rev?-1:1); };
$.fn.cycle.prev = function(opts) { advance(opts, opts.rev?1:-1);};

// advance slide forward or back
function advance(opts, val) {
 var els = opts.elements;
 var p = opts.$cont[0], timeout = p.cycleTimeout;
 if (timeout) {
 clearTimeout(timeout);
 p.cycleTimeout = 0;
 }
 if (opts.random && val < 0) {
 // move back to the previously display slide
 opts.randomIndex--;
 if (--opts.randomIndex == -2)
 opts.randomIndex = els.length-2;
 else if (opts.randomIndex == -1)
 opts.randomIndex = els.length-1;
 opts.nextSlide = opts.randomMap[opts.randomIndex];
 }
 else if (opts.random) {
 if (++opts.randomIndex == els.length)
 opts.randomIndex = 0;
 opts.nextSlide = opts.randomMap[opts.randomIndex];
 }
 else {
 opts.nextSlide = opts.currSlide + val;
 if (opts.nextSlide < 0) {
 if (opts.nowrap) return false;
 opts.nextSlide = els.length - 1;
 }
 else if (opts.nextSlide >= els.length) {
 if (opts.nowrap) return false;
 opts.nextSlide = 0;
 }
 }

 if ($.isFunction(opts.prevNextClick))
 opts.prevNextClick(val > 0, opts.nextSlide, els[opts.nextSlide]);
 go(els, opts, 1, val>=0);
 return false;
};

function buildPager(els, opts) {
 var $p = $(opts.pager);
 $.each(els, function(i,o) {
 $.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
 });
 $.fn.cycle.updateActivePagerLink(opts.pager, opts.startingSlide);
};

$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
 var a;
 if ($.isFunction(opts.pagerAnchorBuilder))
 a = opts.pagerAnchorBuilder(i,el);
 else
 a = '<a href="#">'+(i+1)+'</a>';
 
 if (!a)
 return;
 var $a = $(a);
 // don't reparent if anchor is in the dom
 if ($a.parents('body').length === 0) {
 var arr = [];
 if ($p.length > 1) {
 $p.each(function() {
 var $clone = $a.clone(true);
 $(this).append($clone);
 arr.push($clone);
 });
 $a = $(arr);
 }
 else {
 $a.appendTo($p);
 }
 }

 $a.bind(opts.pagerEvent, function(e) {
 e.preventDefault();
 opts.nextSlide = i;
 var p = opts.$cont[0], timeout = p.cycleTimeout;
 if (timeout) {
 clearTimeout(timeout);
 p.cycleTimeout = 0;
 }
 if ($.isFunction(opts.pagerClick))
 opts.pagerClick(opts.nextSlide, els[opts.nextSlide]);
 go(els,opts,1,opts.currSlide < i); // trigger the trans
 return false;
 });
 
 if (opts.pagerEvent != 'click')
 $a.click(function(){return false;}); // supress click
 
 if (opts.pauseOnPagerHover)
 $a.hover(function() { opts.$cont[0].cyclePause++; }, function() { opts.$cont[0].cyclePause--; } );
};

// helper fn to calculate the number of slides between the current and the next
$.fn.cycle.hopsFromLast = function(opts, fwd) {
 var hops, l = opts.lastSlide, c = opts.currSlide;
 if (fwd)
 hops = c > l ? c - l : opts.slideCount - l;
 else
 hops = c < l ? l - c : l + opts.slideCount - c;
 return hops;
};

// fix clearType problems in ie6 by setting an explicit bg color
// (otherwise text slides look horrible during a fade transition)
function clearTypeFix($slides) {
 function hex(s) {
 s = parseInt(s).toString(16);
 return s.length < 2 ? '0'+s : s;
 };
 function getBg(e) {
 for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
 var v = $.css(e,'background-color');
 if (v.indexOf('rgb') >= 0 ) {
 var rgb = v.match(/\d+/g);
 return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
 }
 if (v && v != 'transparent')
 return v;
 }
 return '#ffffff';
 };
 $slides.each(function() { $(this).css('background-color', getBg(this)); });
};

// reset common props before the next transition
$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) {
 $(opts.elements).not(curr).hide();
 opts.cssBefore.opacity = 1;
 opts.cssBefore.display = 'block';
 if (w !== false && next.cycleW > 0)
 opts.cssBefore.width = next.cycleW;
 if (h !== false && next.cycleH > 0)
 opts.cssBefore.height = next.cycleH;
 opts.cssAfter = opts.cssAfter || {};
 opts.cssAfter.display = 'none';
 $(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0));
 $(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1));
};

// the actual fn for effecting a transition
$.fn.cycle.custom = function(curr, next, opts, cb, speedOverride) {
 var $l = $(curr), $n = $(next);
 var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut;
 $n.css(opts.cssBefore);
 if (speedOverride) {
 if (typeof speedOverride == 'number')
 speedIn = speedOut = speedOverride;
 else
 speedIn = speedOut = 1;
 easeIn = easeOut = null;
 }
 var fn = function() {$n.animate(opts.animIn, speedIn, easeIn, cb)};
 $l.animate(opts.animOut, speedOut, easeOut, function() {
 if (opts.cssAfter) $l.css(opts.cssAfter);
 if (!opts.sync) fn();
 });
 if (opts.sync) fn();
};

// transition definitions - only fade is defined here, transition pack defines the rest
$.fn.cycle.transitions = {
 fade: function($cont, $slides, opts) {
 $slides.not(':eq('+opts.currSlide+')').css('opacity',0);
 opts.before.push(function(curr,next,opts) {
 $.fn.cycle.commonReset(curr,next,opts);
 opts.cssBefore.opacity = 0;
 });
 opts.animIn = { opacity: 1 };
 opts.animOut = { opacity: 0 };
 opts.cssBefore = { top: 0, left: 0 };
 }
};

$.fn.cycle.ver = function() { return ver; };

// override these globally if you like (they are all optional)
$.fn.cycle.defaults = {
 fx: 'fade', // name of transition effect (or comma separated names, ex: fade,scrollUp,shuffle)
 timeout: 4000, // milliseconds between slide transitions (0 to disable auto advance)
 timeoutFn: null, // callback for determining per-slide timeout value: function(currSlideElement, nextSlideElement, options, forwardFlag)
 continuous: 0, // true to start next transition immediately after current one completes
 speed: 1000, // speed of the transition (any valid fx speed value)
 speedIn: null, // speed of the 'in' transition
 speedOut: null, // speed of the 'out' transition
 next: null, // selector for element to use as click trigger for next slide
 prev: null, // selector for element to use as click trigger for previous slide
 prevNextClick: null, // callback fn for prev/next clicks: function(isNext, zeroBasedSlideIndex, slideElement)
 prevNextEvent:'click',// event which drives the manual transition to the previous or next slide
 pager: null, // selector for element to use as pager container
 pagerClick: null, // callback fn for pager clicks: function(zeroBasedSlideIndex, slideElement)
 pagerEvent: 'click', // name of event which drives the pager navigation
 pagerAnchorBuilder: null, // callback fn for building anchor links: function(index, DOMelement)
 before: null, // transition callback (scope set to element to be shown): function(currSlideElement, nextSlideElement, options, forwardFlag)
 after: null, // transition callback (scope set to element that was shown): function(currSlideElement, nextSlideElement, options, forwardFlag)
 end: null, // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options)
 easing: null, // easing method for both in and out transitions
 easeIn: null, // easing for "in" transition
 easeOut: null, // easing for "out" transition
 shuffle: null, // coords for shuffle animation, ex: { top:15, left: 200 }
 animIn: null, // properties that define how the slide animates in
 animOut: null, // properties that define how the slide animates out
 cssBefore: null, // properties that define the initial state of the slide before transitioning in
 cssAfter: null, // properties that defined the state of the slide after transitioning out
 fxFn: null, // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag)
 height: 'auto', // container height
 startingSlide: 0, // zero-based index of the first slide to be displayed
 sync: 1, // true if in/out transitions should occur simultaneously
 random: 0, // true for random, false for sequence (not applicable to shuffle fx)
 fit: 0, // force slides to fit container
 containerResize: 1, // resize container to fit largest slide
 pause: 0, // true to enable "pause on hover"
 pauseOnPagerHover: 0, // true to pause when hovering over pager link
 autostop: 0, // true to end slideshow after X transitions (where X == slide count)
 autostopCount: 0, // number of transitions (optionally used with autostop to define X)
 delay: 0, // additional delay (in ms) for first transition (hint: can be negative)
 slideExpr: null, // expression for selecting slides (if something other than all children is required)
 cleartype: !$.support.opacity, // true if clearType corrections should be applied (for IE)
 cleartypeNoBg: false, // set to true to disable extra cleartype fixing (leave false to force background color setting on slides)
 nowrap: 0, // true to prevent slideshow from wrapping
 fastOnEvent: 0, // force fast transitions when triggered manually (via pager or prev/next); value == time in ms
 randomizeEffects: 1, // valid when multiple effects are used; true to make the effect sequence random
 rev: 0, // causes animations to transition in reverse
 manualTrump: true, // causes manual transition to stop an active transition instead of being ignored
 requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded
 requeueTimeout: 250 // ms delay for requeue
};

})(jQuery);


/*!
 * jQuery Cycle Plugin Transition Definitions
 * This script is a plugin for the jQuery Cycle Plugin
 * Examples and documentation at: http://malsup.com/jquery/cycle/
 * Copyright (c) 2007-2008 M. Alsup
 * Version: 2.72
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
(function($) {

//
// These functions define one-time slide initialization for the named
// transitions. To save file size feel free to remove any of these that you
// don't need.
//
$.fn.cycle.transitions.none = function($cont, $slides, opts) {
 opts.fxFn = function(curr,next,opts,after){
 $(next).show();
 $(curr).hide();
 after();
 };
}

// scrollUp/Down/Left/Right
$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
 $cont.css('overflow','hidden');
 opts.before.push($.fn.cycle.commonReset);
 var h = $cont.height();
 opts.cssBefore ={ top: h, left: 0 };
 opts.cssFirst = { top: 0 };
 opts.animIn = { top: 0 };
 opts.animOut = { top: -h };
};
$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
 $cont.css('overflow','hidden');
 opts.before.push($.fn.cycle.commonReset);
 var h = $cont.height();
 opts.cssFirst = { top: 0 };
 opts.cssBefore= { top: -h, left: 0 };
 opts.animIn = { top: 0 };
 opts.animOut = { top: h };
};
$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
 $cont.css('overflow','hidden');
 opts.before.push($.fn.cycle.commonReset);
 var w = $cont.width();
 opts.cssFirst = { left: 0 };
 opts.cssBefore= { left: w, top: 0 };
 opts.animIn = { left: 0 };
 opts.animOut = { left: 0-w };
};
$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
 $cont.css('overflow','hidden');
 opts.before.push($.fn.cycle.commonReset);
 var w = $cont.width();
 opts.cssFirst = { left: 0 };
 opts.cssBefore= { left: -w, top: 0 };
 opts.animIn = { left: 0 };
 opts.animOut = { left: w };
};
$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
 $cont.css('overflow','hidden').width();
 opts.before.push(function(curr, next, opts, fwd) {
 $.fn.cycle.commonReset(curr,next,opts);
 opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW);
 opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW;
 });
 opts.cssFirst = { left: 0 };
 opts.cssBefore= { top: 0 };
 opts.animIn = { left: 0 };
 opts.animOut = { top: 0 };
};
$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
 $cont.css('overflow','hidden');
 opts.before.push(function(curr, next, opts, fwd) {
 $.fn.cycle.commonReset(curr,next,opts);
 opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1);
 opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH;
 });
 opts.cssFirst = { top: 0 };
 opts.cssBefore= { left: 0 };
 opts.animIn = { top: 0 };
 opts.animOut = { left: 0 };
};

// slideX/slideY
$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $(opts.elements).not(curr).hide();
 $.fn.cycle.commonReset(curr,next,opts,false,true);
 opts.animIn.width = next.cycleW;
 });
 opts.cssBefore = { left: 0, top: 0, width: 0 };
 opts.animIn = { width: 'show' };
 opts.animOut = { width: 0 };
};
$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $(opts.elements).not(curr).hide();
 $.fn.cycle.commonReset(curr,next,opts,true,false);
 opts.animIn.height = next.cycleH;
 });
 opts.cssBefore = { left: 0, top: 0, height: 0 };
 opts.animIn = { height: 'show' };
 opts.animOut = { height: 0 };
};

// shuffle
$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
 var i, w = $cont.css('overflow', 'visible').width();
 $slides.css({left: 0, top: 0});
 opts.before.push(function(curr,next,opts) {
 $.fn.cycle.commonReset(curr,next,opts,true,true,true);
 });
 // only adjust speed once!
 if (!opts.speedAdjusted) {
 opts.speed = opts.speed / 2; // shuffle has 2 transitions
 opts.speedAdjusted = true;
 }
 opts.random = 0;
 opts.shuffle = opts.shuffle || {left:-w, top:15};
 opts.els = [];
 for (i=0; i < $slides.length; i++)
 opts.els.push($slides[i]);

 for (i=0; i < opts.currSlide; i++)
 opts.els.push(opts.els.shift());

 // custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
 opts.fxFn = function(curr, next, opts, cb, fwd) {
 var $el = fwd ? $(curr) : $(next);
 $(next).css(opts.cssBefore);
 var count = opts.slideCount;
 $el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
 var hops = $.fn.cycle.hopsFromLast(opts, fwd);
 for (var k=0; k < hops; k++)
 fwd ? opts.els.push(opts.els.shift()) : opts.els.unshift(opts.els.pop());
 if (fwd) {
 for (var i=0, len=opts.els.length; i < len; i++)
 $(opts.els[i]).css('z-index', len-i+count);
 }
 else {
 var z = $(curr).css('z-index');
 $el.css('z-index', parseInt(z)+1+count);
 }
 $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
 $(fwd ? this : curr).hide();
 if (cb) cb();
 });
 });
 };
 opts.cssBefore = { display: 'block', opacity: 1, top: 0, left: 0 };
};

// turnUp/Down/Left/Right
$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,true,false);
 opts.cssBefore.top = next.cycleH;
 opts.animIn.height = next.cycleH;
 });
 opts.cssFirst = { top: 0 };
 opts.cssBefore = { left: 0, height: 0 };
 opts.animIn = { top: 0 };
 opts.animOut = { height: 0 };
};
$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,true,false);
 opts.animIn.height = next.cycleH;
 opts.animOut.top = curr.cycleH;
 });
 opts.cssFirst = { top: 0 };
 opts.cssBefore = { left: 0, top: 0, height: 0 };
 opts.animOut = { height: 0 };
};
$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,false,true);
 opts.cssBefore.left = next.cycleW;
 opts.animIn.width = next.cycleW;
 });
 opts.cssBefore = { top: 0, width: 0 };
 opts.animIn = { left: 0 };
 opts.animOut = { width: 0 };
};
$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,false,true);
 opts.animIn.width = next.cycleW;
 opts.animOut.left = curr.cycleW;
 });
 opts.cssBefore = { top: 0, left: 0, width: 0 };
 opts.animIn = { left: 0 };
 opts.animOut = { width: 0 };
};

// zoom
$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,false,false,true);
 opts.cssBefore.top = next.cycleH/2;
 opts.cssBefore.left = next.cycleW/2;
 opts.animIn = { top: 0, left: 0, width: next.cycleW, height: next.cycleH };
 opts.animOut = { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 };
 });
 opts.cssFirst = { top:0, left: 0 };
 opts.cssBefore = { width: 0, height: 0 };
};

// fadeZoom
$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,false,false);
 opts.cssBefore.left = next.cycleW/2;
 opts.cssBefore.top = next.cycleH/2;
 opts.animIn = { top: 0, left: 0, width: next.cycleW, height: next.cycleH };
 });
 opts.cssBefore = { width: 0, height: 0 };
 opts.animOut = { opacity: 0 };
};

// blindX
$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
 var w = $cont.css('overflow','hidden').width();
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts);
 opts.animIn.width = next.cycleW;
 opts.animOut.left = curr.cycleW;
 });
 opts.cssBefore = { left: w, top: 0 };
 opts.animIn = { left: 0 };
 opts.animOut = { left: w };
};
// blindY
$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
 var h = $cont.css('overflow','hidden').height();
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts);
 opts.animIn.height = next.cycleH;
 opts.animOut.top = curr.cycleH;
 });
 opts.cssBefore = { top: h, left: 0 };
 opts.animIn = { top: 0 };
 opts.animOut = { top: h };
};
// blindZ
$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
 var h = $cont.css('overflow','hidden').height();
 var w = $cont.width();
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts);
 opts.animIn.height = next.cycleH;
 opts.animOut.top = curr.cycleH;
 });
 opts.cssBefore = { top: h, left: w };
 opts.animIn = { top: 0, left: 0 };
 opts.animOut = { top: h, left: w };
};

// growX - grow horizontally from centered 0 width
$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,false,true);
 opts.cssBefore.left = this.cycleW/2;
 opts.animIn = { left: 0, width: this.cycleW };
 opts.animOut = { left: 0 };
 });
 opts.cssBefore = { width: 0, top: 0 };
};
// growY - grow vertically from centered 0 height
$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,true,false);
 opts.cssBefore.top = this.cycleH/2;
 opts.animIn = { top: 0, height: this.cycleH };
 opts.animOut = { top: 0 };
 });
 opts.cssBefore = { height: 0, left: 0 };
};

// curtainX - squeeze in both edges horizontally
$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,false,true,true);
 opts.cssBefore.left = next.cycleW/2;
 opts.animIn = { left: 0, width: this.cycleW };
 opts.animOut = { left: curr.cycleW/2, width: 0 };
 });
 opts.cssBefore = { top: 0, width: 0 };
};
// curtainY - squeeze in both edges vertically
$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,true,false,true);
 opts.cssBefore.top = next.cycleH/2;
 opts.animIn = { top: 0, height: next.cycleH };
 opts.animOut = { top: curr.cycleH/2, height: 0 };
 });
 opts.cssBefore = { left: 0, height: 0 };
};

// cover - curr slide covered by next slide
$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
 var d = opts.direction || 'left';
 var w = $cont.css('overflow','hidden').width();
 var h = $cont.height();
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts);
 if (d == 'right')
 opts.cssBefore.left = -w;
 else if (d == 'up')
 opts.cssBefore.top = h;
 else if (d == 'down')
 opts.cssBefore.top = -h;
 else
 opts.cssBefore.left = w;
 });
 opts.animIn = { left: 0, top: 0};
 opts.animOut = { opacity: 1 };
 opts.cssBefore = { top: 0, left: 0 };
};

// uncover - curr slide moves off next slide
$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
 var d = opts.direction || 'left';
 var w = $cont.css('overflow','hidden').width();
 var h = $cont.height();
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,true,true,true);
 if (d == 'right')
 opts.animOut.left = w;
 else if (d == 'up')
 opts.animOut.top = -h;
 else if (d == 'down')
 opts.animOut.top = h;
 else
 opts.animOut.left = -w;
 });
 opts.animIn = { left: 0, top: 0 };
 opts.animOut = { opacity: 1 };
 opts.cssBefore = { top: 0, left: 0 };
};

// toss - move top slide and fade away
$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
 var w = $cont.css('overflow','visible').width();
 var h = $cont.height();
 opts.before.push(function(curr, next, opts) {
 $.fn.cycle.commonReset(curr,next,opts,true,true,true);
 // provide default toss settings if animOut not provided
 if (!opts.animOut.left && !opts.animOut.top)
 opts.animOut = { left: w*2, top: -h/2, opacity: 0 };
 else
 opts.animOut.opacity = 0;
 });
 opts.cssBefore = { left: 0, top: 0 };
 opts.animIn = { left: 0 };
};

// wipe - clip animation
$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
 var w = $cont.css('overflow','hidden').width();
 var h = $cont.height();
 opts.cssBefore = opts.cssBefore || {};
 var clip;
 if (opts.clip) {
 if (/l2r/.test(opts.clip))
 clip = 'rect(0px 0px '+h+'px 0px)';
 else if (/r2l/.test(opts.clip))
 clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
 else if (/t2b/.test(opts.clip))
 clip = 'rect(0px '+w+'px 0px 0px)';
 else if (/b2t/.test(opts.clip))
 clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
 else if (/zoom/.test(opts.clip)) {
 var top = parseInt(h/2);
 var left = parseInt(w/2);
 clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)';
 }
 }

 opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';

 var d = opts.cssBefore.clip.match(/(\d+)/g);
 var t = parseInt(d[0]), r = parseInt(d[1]), b = parseInt(d[2]), l = parseInt(d[3]);

 opts.before.push(function(curr, next, opts) {
 if (curr == next) return;
 var $curr = $(curr), $next = $(next);
 $.fn.cycle.commonReset(curr,next,opts,true,true,false);
 opts.cssAfter.display = 'block';

 var step = 1, count = parseInt((opts.speedIn / 13)) - 1;
 (function f() {
 var tt = t ? t - parseInt(step * (t/count)) : 0;
 var ll = l ? l - parseInt(step * (l/count)) : 0;
 var bb = b < h ? b + parseInt(step * ((h-b)/count || 1)) : h;
 var rr = r < w ? r + parseInt(step * ((w-r)/count || 1)) : w;
 $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
 (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
 })();
 });
 opts.cssBefore = { display: 'block', opacity: 1, top: 0, left: 0 };
 opts.animIn = { left: 0 };
 opts.animOut = { left: 0 };
};

})(jQuery);
/*
 * jQuery HoverPulse Plugin by M. Alsup
 * Examples and docs at: http://malsup.com/jquery/hoverpulse/
 * Dual licensed under the MIT and GPL
 * Requires: jQuery v1.2.6 or later
 * @version: 1.01 26-FEB-2009
 */

(function($) {

$.fn.hoverpulse = function(options) {
 // in 1.3+ we can fix mistakes with the ready state
 if (this.length == 0) {
 if (!$.isReady && this.selector) {
 var s = this.selector, c = this.context;
 $(function() {
 $(s,c).hoverpulse(options);
 });
 }
 return this;
 } 
 
 var opts = $.extend({}, $.fn.hoverpulse.defaults, options);

 // parent must be relatively positioned
 this.parent().css({ position: 'relative' });
 // pulsing element must be absolutely positioned
 this.css({ position: 'absolute', top: 0, left: 0 });

 this.each(function() {
 var $this = $(this);
 var w = $this.width(), h = $this.height();
 $this.data('hoverpulse.size', { w: parseInt(w), h: parseInt(h) });
 });

 // bind hover event for behavior
 return this.hover(
 // hover over
 function() {
 var $this = $(this);
 $this.parent().css('z-index', opts.zIndexActive);
 
 var size = $this.data('hoverpulse.size');
 var w = size.w, h = size.h;
 $this.stop().animate({ 
 top: ('-'+opts.size+'px'), 
 left: ('-'+opts.size+'px'), 
 height: (h+2*opts.size)+'px', 
 width: (w+2*opts.size)+'px' 
 }, opts.speed);
 },
 // hover out
 function() {
 var $this = $(this);
 var size = $this.data('hoverpulse.size');
 var w = size.w, h = size.h;
 
 $this.stop().animate({ 
 top: 0, 
 left: 0, 
 height: (h+'px'), 
 width: (w+'px') 
 }, opts.speed, function() {
 $this.parent().css('z-index', opts.zIndexNormal);
 });
 }
 );
};

$.fn.hoverpulse.defaults = {
 size: 20,
 speed: 200,
 zIndexActive: 100,
 zIndexNormal: 1
};

})(jQuery);

jQuery.noConflict();
jQuery(document).ready(function() {
 jQuery(".scrollable").scrollable();
 jQuery(".slidetabs").tabs(".images > div", {
 effect: 'fade',
 fadeOutSpeed: "slow",
 rotate: true
 }).slideshow({
 autoplay: true,
 interval: 5000,
 clickable: false
 });
 jQuery('#event_date').datepicker({dateFormat:'yy-mm-dd',showOn: 'button', buttonImage: SKIN_URL+'images/icon-calendar.gif', buttonImageOnly: true});
 
 /* Terms & conditions */
 jQuery('.tnc-popup').click(function(){return false;});
 jQuery('.tnc-popup').hover(
 function () {
 jQuery(this).parent().parent().parent().children('div.agreement-content').show();
 },
 function () {
 jQuery(this).parent().parent().parent().children('div.agreement-content').hide();
 }
 );
 
 /* Home Portfolio Block */
 jQuery('div.portfolio-thumb a img').hover(
 function() {
 jQuery(this).animate({opacity:1},100);
 },
 function() {
 jQuery(this).animate({opacity:0.8},100);
 }
 );
 
 Shadowbox.init();
 
 jQuery("select[rel='product-options']").change(function(){
 var sku = jQuery("select[rel='product-options'] option:selected").attr("rel");
 jQuery("#image").attr("src",jQuery("a[title='"+sku+"']").attr("prodDetailImg"));
 jQuery("#image").attr("from",jQuery("a[title='"+sku+"']").attr("item"));
 return false;
 });
 jQuery("select[rel='product-options']").keypress(function(){
 var sku = jQuery("select[rel='product-options'] option:selected").attr("rel");
 jQuery("#image").attr("src",jQuery("a[title='"+sku+"']").attr("prodDetailImg"));
 jQuery("#image").attr("from",jQuery("a[title='"+sku+"']").attr("item"));
 return false;
 });
 
 jQuery('div.slider-gallery').each(function () {
 var ul = jQuery('ul', this);
 var productWidth = ul.innerWidth() - jQuery(this).outerWidth();

 var slider = jQuery('.slider', this).slider({ 
 handle: '.slider-handle',
 min: 0, 
 max: productWidth, 
 slide: function (ev, ui) {
 ul.css('left', '-' + ui.value + 'px');
 }, 
 stop: function (ev, ui) {
 ul.animate({ 'left' : '-' + ui.value + 'px' }, 500, 'linear');
 }
 });
 });
 
 jQuery("#image").click(function(){
 Shadowbox.init({continuous: true});
 var bookmark = jQuery(this).attr("from");
 var items = new Array();
 var count = 0;
 jQuery('a[rel^=ProdThumbs]').each(function(){
 items[count] = this;
 ++count;
 });
 if (items.length){
 Shadowbox.setup(items, {gallery:'VersionGallery'});
 }
 Shadowbox.open(items[bookmark]);
 });
 jQuery("#product-thumbs li a").each(function(){
 jQuery(this).click(function(){
 Shadowbox.clearCache();
 jQuery("#image").attr("src",jQuery(this).attr("prodDetailImg"));
 jQuery("#image").attr("from",jQuery(this).attr("item"));
 jQuery("select[rel='product-options'] option[rel='"+jQuery(this).attr("title")+"']").attr("selected","selected");
 return false;
 });
 });
 
 if (window.default_portfolio !== undefined) {
 var whatUserURL = "/ajax/portfolio-prod-list?prod_id="+default_portfolio;
 var aboutEventURL = "/ajax/portfolio-desc?prod_id="+default_portfolio;
 jQuery('#aboutEvent').load(aboutEventURL,{},function(xml){
 jQuery('#about-event-loading').hide();
 jQuery('#whatUsed').load(whatUserURL,{},function(xml){
 jQuery('#what-used-loading').hide();
 //Height adjustment
 var newHeight = jQuery('div.portfolio-column-right').height()-54;
 jQuery('#whatUsed').css("height",newHeight);
 });
 });
 }
 
 //Buttons
 //Product View
 jQuery('div.product-view').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("product-view-rollover");},
 function() {jQuery(this).removeClass("product-view-rollover");}
 );
 });
 //Add To Event
 jQuery('div.product-add').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("product-add-rollover");},
 function() {jQuery(this).removeClass("product-add-rollover");}
 );
 });
 //Create an Account
 jQuery('.account-create').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("account-create-rollover");},
 function() {jQuery(this).removeClass("account-create-rollover");}
 );
 });
 
 //Login to Account
 jQuery('.account-login').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("account-login-rollover");},
 function() {jQuery(this).removeClass("account-login-rollover");}
 );
 });
 //Account Retrieve Password
 jQuery('input.account-password').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("account-password-rollover");},
 function() {jQuery(this).removeClass("account-password-rollover");}
 );
 });
 //Save
 jQuery('input.button-save').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-save-rollover");},
 function() {jQuery(this).removeClass("button-save-rollover");}
 );
 });
 //Back
 jQuery('div.button-back').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-back-rollover");},
 function() {jQuery(this).removeClass("button-back-rollover");}
 );
 });
 //Back Quote History
 jQuery('div.button-back-history').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-back-history-rollover");},
 function() {jQuery(this).removeClass("button-back-history-rollover");}
 );
 });
 //Update Qty
 jQuery('input.button-updade-qty').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-updade-qty-rollover");},
 function() {jQuery(this).removeClass("button-updade-qty-rollover");}
 );
 });
 //Continue Shopping
 jQuery('div.button-continue-shopping').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-continue-shopping-rollover");},
 function() {jQuery(this).removeClass("button-continue-shopping-rollover");}
 );
 });
 //Continue
 jQuery('div.button-continue').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-continue-rollover");},
 function() {jQuery(this).removeClass("button-continue-rollover");}
 );
 });
 //Cart Request a Quote
 jQuery('div.button-cart-request').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-cart-request-rollover");},
 function() {jQuery(this).removeClass("button-cart-request-rollover");}
 );
 });
 //Cart Submit a Quote
 jQuery('input.button-cart-submit').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-cart-submit-rollover");},
 function() {jQuery(this).removeClass("button-cart-submit-rollover");}
 );
 });
 //Space Planner
 jQuery('div.button-space-planner').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-space-planner-rollover");},
 function() {jQuery(this).removeClass("button-space-planner-rollover");}
 );
 });
 //Send Email
 jQuery('input.button-send-email').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-send-email-rollover");},
 function() {jQuery(this).removeClass("button-send-email-rollover");}
 );
 });
 //Submit
 jQuery('input.button-submit').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-submit-rollover");},
 function() {jQuery(this).removeClass("button-submit-rollover");}
 );
 });
 //Close
 jQuery('div.button-close').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-close-rollover");},
 function() {jQuery(this).removeClass("button-close-rollover");}
 );
 });
 //Browse Catalog
 jQuery('div.button-browse-catalog').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-browse-catalog-rollover");},
 function() {jQuery(this).removeClass("button-browse-catalog-rollover");}
 );
 });
 //Apply
 jQuery('input.button-apply').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-apply-rollover");},
 function() {jQuery(this).removeClass("button-apply-rollover");}
 );
 });
 //Cancel
 jQuery('div.button-cancel').each(function(){
 jQuery(this).hover(
 function() {jQuery(this).addClass("button-cancel-rollover");},
 function() {jQuery(this).removeClass("button-cancel-rollover");}
 );
 });
 //About Us Dropdown
 jQuery('#state-select option').each(function(){
 jQuery(this).click(function(){
 window.location.href= "#" + jQuery(this).attr('value');
 });
 })
 
 //Contact Form
 //Checkboxes Value toggle
 jQuery('input.quickFormCheck').each(function() {
 jQuery(this).click(function(){
 if(jQuery(this).val() == "on"){jQuery(this).attr("value","off");}else{jQuery(this).attr("value","on");}
 });
 });
 
 //Default Contact Form to SalesForce
 jQuery("#productContactForm").submit(function(){
 /* Validate the form */
 var errors = false;
 errors = fieldValidate(jQuery("#productContactForm input[name=first_name]"),errors);
 errors = fieldValidate(jQuery("#productContactForm input[name=last_name]"),errors);
 errors = fieldValidate(jQuery("#productContactForm input[name=zip]"),errors);
 errors = fieldValidate(jQuery("#productContactForm input[name=email]"),errors);
 if(jQuery("#productContactForm select[name=region_id]").length) {
 errors = fieldValidate(jQuery("#productContactForm select[name=region_id]"),errors);
 }
 if(jQuery("#productContactForm input[name=city]").length) {
 errors = fieldValidate(jQuery("#productContactForm input[name=city]"),errors);
 }
 if(jQuery("#productContactForm input[name=phone]").length) {
 errors = fieldValidate(jQuery("#productContactForm input[name=phone]"),errors);
 }
 if(jQuery("#productContactForm input[name=first_name_cmc]").length) {
 errors = fieldValidate(jQuery("#productContactForm input[name=first_name_cmc]"),errors);
 }
 if(jQuery("#productContactForm input[name=last_name_cmc]").length) {
 errors = fieldValidate(jQuery("#productContactForm input[name=last_name_cmc]"),errors);
 }
 if(jQuery("#productContactForm input[name=email_cmc]").length) {
 errors = fieldValidate(jQuery("#productContactForm input[name=email_cmc]"),errors);
 }
 if(jQuery("#productContactForm input[name=cfr_district]").length) {
 errors = fieldValidate(jQuery("#productContactForm input[name=cfr_district]"),errors);
 }
 if (errors) {
 return false;
 }
 /* Validations successful */
 jQuery('#loading').css('display','block');
 jQuery.post(
 '/ajax/contact',
 {
 first_name: jQuery('#first_name').val(),
 last_name: jQuery('#last_name').val(),
 phone: jQuery('#phone').val(),
 email: jQuery('#email').val(),
 comments: jQuery('#comments').val(),
 company: jQuery('#company').val(),
 city: jQuery('#city').val(),
 state: jQuery('#region_id option:selected').html(),
 region: jQuery('#region').val(),
 zip: jQuery('#zip').val(),
 recordType: jQuery('#recordType').val(),
 fromURL: jQuery('#fromURL').val(),
 orderCart: jQuery('#orderCart').val(),
 first_name_cmc: jQuery('#first_name_cmc').val(),
 last_name_cmc: jQuery('#last_name_cmc').val(),
 email_cmc: jQuery('#email_cmc').val(),
 event_date: jQuery('input[name="event_date"]').val(),
 rep_name: jQuery('#rep_name option:selected').html(),
 cfr_district: jQuery('select[name="cfr_district"] option:selected').val(),
 client_current: jQuery('input[name="client_current"]:selected').val(),
 client_prev: jQuery('input[name="client_prev"]:selected').val()
 },
 function(xml){
 jQuery('#loading').remove();
 //Tag Omniture
 s = s_gi(OMNI_ID);
 s.linkTrackEvents="event2";
 s.linkTrackVars="events";
 s.events="event2";
 s.tl(s,'o','lead form submission');
 
 //Load Thank You
 jQuery('#QF_content').load('/ajax/contact-thankyou');
 }
 );
 
 return false;
 });
 
 //Download Catalog Omniture tag
 jQuery("a.download-catalog").click(function(){
 s = s_gi(OMNI_ID);
 s.linkTrackEvents="event1";
 s.linkTrackVars="events";
 s.events="event1";
 s.tl(s,"o","download full catalog");
 });
 
 jQuery("#state-select").change(function(){
 var url = jQuery("#state-select option:selected").val();
 if (url.length > 0) {
 window.location = "#"+jQuery(this).val();
 }
 }).trigger('change');
 
});

function fieldValidate(obj,er) {
 var invalid = false;
 /* Validate the pattern */
 if (obj.attr("required") == "required") {
 if (!obj.val() || obj.val() == "" || obj.children("option:selected").val() == "") {
 obj.addClass("invalid");
 invalid = true;
 } else {
 obj.removeClass("invalid");
 invalid = false;
 }
 }
 if(obj.attr("pattern")) {
 var pattern = eval("/^"+obj.attr("pattern")+"$/");
 if (!pattern.test(obj.val())) {
 obj.addClass("invalid");
 invalid = true;
 } else {
 obj.removeClass("invalid");
 invalid = false;
 }
 }
 
 /* Return erros flag */
 if (!er) {
 return invalid;
 } else {
 return er; 
 }
}
/*
Copyright (c) 2007, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt
version: 2.4.1

Note: This file includes yahoo, dom, event, and anim

*/
if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=A[C].split(".");E=YAHOO;for(B=(D[0]=="YAHOO")?1:0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]];}}return E;};YAHOO.log=function(D,A,C){var B=YAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return false;}};YAHOO.register=function(A,E,D){var I=YAHOO.env.modules;if(!I[A]){I[A]={versions:[],builds:[]};}var B=I[A],H=D.version,G=D.build,F=YAHOO.env.listeners;B.name=A;B.version=H;B.build=G;B.versions.push(H);B.builds.push(G);B.mainClass=E;for(var C=0;C<F.length;C=C+1){F[C](B);}if(E){E.VERSION=H;E.BUILD=G;}else{YAHOO.log("mainClass is undefined for module "+A,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(A){return YAHOO.env.modules[A]||null;};YAHOO.env.ua=function(){var C={ie:0,opera:0,gecko:0,webkit:0,mobile:null};var B=navigator.userAgent,A;if((/KHTML/).test(B)){C.webkit=1;}A=B.match(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){C.webkit=parseFloat(A[1]);if(/ Mobile\//.test(B)){C.mobile="Apple";}else{A=B.match(/NokiaN[^\/]*/);if(A){C.mobile=A[0];}}}if(!C.webkit){A=B.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){C.opera=parseFloat(A[1]);A=B.match(/Opera Mini[^;]*/);if(A){C.mobile=A[0];}}else{A=B.match(/MSIE\s([^;]*)/);if(A&&A[1]){C.ie=parseFloat(A[1]);}else{A=B.match(/Gecko\/([^\s]*)/);if(A){C.gecko=1;A=B.match(/rv:([^\s\)]*)/);if(A&&A[1]){C.gecko=parseFloat(A[1]);}}}}}return C;}();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var B=YAHOO_config.listener,A=YAHOO.env.listeners,D=true,C;if(B){for(C=0;C<A.length;C=C+1){if(A[C]==B){D=false;break;}}if(D){A.push(B);}}}})();YAHOO.lang=YAHOO.lang||{isArray:function(B){if(B){var A=YAHOO.lang;return A.isNumber(B.length)&&A.isFunction(B.splice);}return false;},isBoolean:function(A){return typeof A==="boolean";},isFunction:function(A){return typeof A==="function";},isNull:function(A){return A===null;},isNumber:function(A){return typeof A==="number"&&isFinite(A);},isObject:function(A){return(A&&(typeof A==="object"||YAHOO.lang.isFunction(A)))||false;},isString:function(A){return typeof A==="string";},isUndefined:function(A){return typeof A==="undefined";},hasOwnProperty:function(A,B){if(Object.prototype.hasOwnProperty){return A.hasOwnProperty(B);}return !YAHOO.lang.isUndefined(A[B])&&A.constructor.prototype[B]!==A[B];},_IEEnumFix:function(C,B){if(YAHOO.env.ua.ie){var E=["toString","valueOf"],A;for(A=0;A<E.length;A=A+1){var F=E[A],D=B[F];if(YAHOO.lang.isFunction(D)&&D!=Object.prototype[F]){C[F]=D;}}}},extend:function(D,E,C){if(!E||!D){throw new Error("YAHOO.lang.extend failed, please check that all dependencies are included.");}var B=function(){};B.prototype=E.prototype;D.prototype=new B();D.prototype.constructor=D;D.superclass=E.prototype;if(E.prototype.constructor==Object.prototype.constructor){E.prototype.constructor=E;}if(C){for(var A in C){D.prototype[A]=C[A];}YAHOO.lang._IEEnumFix(D.prototype,C);}},augmentObject:function(E,D){if(!D||!E){throw new Error("Absorb failed, verify dependencies.");}var A=arguments,C,F,B=A[2];if(B&&B!==true){for(C=2;C<A.length;C=C+1){E[A[C]]=D[A[C]];}}else{for(F in D){if(B||!E[F]){E[F]=D[F];}}YAHOO.lang._IEEnumFix(E,D);}},augmentProto:function(D,C){if(!C||!D){throw new Error("Augment failed, verify dependencies.");}var A=[D.prototype,C.prototype];for(var B=2;B<arguments.length;B=B+1){A.push(arguments[B]);}YAHOO.lang.augmentObject.apply(this,A);},dump:function(A,G){var C=YAHOO.lang,D,F,I=[],J="{...}",B="f(){...}",H=", ",E=" => ";if(!C.isObject(A)){return A+"";}else{if(A instanceof Date||("nodeType" in A&&"tagName" in A)){return A;}else{if(C.isFunction(A)){return B;}}}G=(C.isNumber(G))?G:3;if(C.isArray(A)){I.push("[");for(D=0,F=A.length;D<F;D=D+1){if(C.isObject(A[D])){I.push((G>0)?C.dump(A[D],G-1):J);}else{I.push(A[D]);}I.push(H);}if(I.length>1){I.pop();}I.push("]");}else{I.push("{");for(D in A){if(C.hasOwnProperty(A,D)){I.push(D+E);if(C.isObject(A[D])){I.push((G>0)?C.dump(A[D],G-1):J);}else{I.push(A[D]);}I.push(H);}}if(I.length>1){I.pop();}I.push("}");}return I.join("");},substitute:function(Q,B,J){var G,F,E,M,N,P,D=YAHOO.lang,L=[],C,H="dump",K=" ",A="{",O="}";for(;;){G=Q.lastIndexOf(A);if(G<0){break;}F=Q.indexOf(O,G);if(G+1>=F){break;}C=Q.substring(G+1,F);M=C;P=null;E=M.indexOf(K);if(E>-1){P=M.substring(E+1);M=M.substring(0,E);}N=B[M];if(J){N=J(M,N,P);}if(D.isObject(N)){if(D.isArray(N)){N=D.dump(N,parseInt(P,10));}else{P=P||"";var I=P.indexOf(H);if(I>-1){P=P.substring(4);}if(N.toString===Object.prototype.toString||I>-1){N=D.dump(N,parseInt(P,10));}else{N=N.toString();}}}else{if(!D.isString(N)&&!D.isNumber(N)){N="~-"+L.length+"-~";L[L.length]=C;}}Q=Q.substring(0,G)+N+Q.substring(F+1);}for(G=L.length-1;G>=0;G=G-1){Q=Q.replace(new RegExp("~-"+G+"-~"),"{"+L[G]+"}","g");}return Q;},trim:function(A){try{return A.replace(/^\s+|\s+$/g,"");}catch(B){return A;}},merge:function(){var D={},B=arguments;for(var C=0,A=B.length;C<A;C=C+1){YAHOO.lang.augmentObject(D,B[C],true);}return D;},later:function(H,B,I,D,E){H=H||0;B=B||{};var C=I,G=D,F,A;if(YAHOO.lang.isString(I)){C=B[I];}if(!C){throw new TypeError("method undefined");}if(!YAHOO.lang.isArray(G)){G=[D];}F=function(){C.apply(B,G);};A=(E)?setInterval(F,H):setTimeout(F,H);return{interval:E,cancel:function(){if(this.interval){clearInterval(A);}else{clearTimeout(A);}}};},isValue:function(B){var A=YAHOO.lang;return(A.isObject(B)||A.isString(B)||A.isNumber(B)||A.isBoolean(B));}};YAHOO.util.Lang=YAHOO.lang;YAHOO.lang.augment=YAHOO.lang.augmentProto;YAHOO.augment=YAHOO.lang.augmentProto;YAHOO.extend=YAHOO.lang.extend;YAHOO.register("yahoo",YAHOO,{version:"2.4.1",build:"742"});(function(){var B=YAHOO.util,L,J,H=0,K={},F={},N=window.document;var C=YAHOO.env.ua.opera,M=YAHOO.env.ua.webkit,A=YAHOO.env.ua.gecko,G=YAHOO.env.ua.ie;var E={HYPHEN:/(-[a-z])/i,ROOT_TAG:/^body|html$/i};var O=function(Q){if(!E.HYPHEN.test(Q)){return Q;}if(K[Q]){return K[Q];}var R=Q;while(E.HYPHEN.exec(R)){R=R.replace(RegExp.$1,RegExp.$1.substr(1).toUpperCase());}K[Q]=R;return R;};var P=function(R){var Q=F[R];if(!Q){Q=new RegExp("(?:^|\\s+)"+R+"(?:\\s+|$)");F[R]=Q;}return Q;};if(N.defaultView&&N.defaultView.getComputedStyle){L=function(Q,T){var S=null;if(T=="float"){T="cssFloat";}var R=N.defaultView.getComputedStyle(Q,"");if(R){S=R[O(T)];}return Q.style[T]||S;};}else{if(N.documentElement.currentStyle&&G){L=function(Q,S){switch(O(S)){case"opacity":var U=100;try{U=Q.filters["DXImageTransform.Microsoft.Alpha"].opacity;}catch(T){try{U=Q.filters("alpha").opacity;}catch(T){}}return U/100;case"float":S="styleFloat";default:var R=Q.currentStyle?Q.currentStyle[S]:null;return(Q.style[S]||R);}};}else{L=function(Q,R){return Q.style[R];};}}if(G){J=function(Q,R,S){switch(R){case"opacity":if(YAHOO.lang.isString(Q.style.filter)){Q.style.filter="alpha(opacity="+S*100+")";if(!Q.currentStyle||!Q.currentStyle.hasLayout){Q.style.zoom=1;}}break;case"float":R="styleFloat";default:Q.style[R]=S;}};}else{J=function(Q,R,S){if(R=="float"){R="cssFloat";}Q.style[R]=S;};}var D=function(Q,R){return Q&&Q.nodeType==1&&(!R||R(Q));};YAHOO.util.Dom={get:function(S){if(S&&(S.tagName||S.item)){return S;}if(YAHOO.lang.isString(S)||!S){return N.getElementById(S);}if(S.length!==undefined){var T=[];for(var R=0,Q=S.length;R<Q;++R){T[T.length]=B.Dom.get(S[R]);}return T;}return S;},getStyle:function(Q,S){S=O(S);var R=function(T){return L(T,S);};return B.Dom.batch(Q,R,B.Dom,true);},setStyle:function(Q,S,T){S=O(S);var R=function(U){J(U,S,T);};B.Dom.batch(Q,R,B.Dom,true);},getXY:function(Q){var R=function(S){if((S.parentNode===null||S.offsetParent===null||this.getStyle(S,"display")=="none")&&S!=S.ownerDocument.body){return false;}return I(S);};return B.Dom.batch(Q,R,B.Dom,true);},getX:function(Q){var R=function(S){return B.Dom.getXY(S)[0];};return B.Dom.batch(Q,R,B.Dom,true);},getY:function(Q){var R=function(S){return B.Dom.getXY(S)[1];};return B.Dom.batch(Q,R,B.Dom,true);},setXY:function(Q,T,S){var R=function(W){var V=this.getStyle(W,"position");if(V=="static"){this.setStyle(W,"position","relative");V="relative";}var Y=this.getXY(W);if(Y===false){return false;}var X=[parseInt(this.getStyle(W,"left"),10),parseInt(this.getStyle(W,"top"),10)];if(isNaN(X[0])){X[0]=(V=="relative")?0:W.offsetLeft;}if(isNaN(X[1])){X[1]=(V=="relative")?0:W.offsetTop;}if(T[0]!==null){W.style.left=T[0]-Y[0]+X[0]+"px";}if(T[1]!==null){W.style.top=T[1]-Y[1]+X[1]+"px";}if(!S){var U=this.getXY(W);if((T[0]!==null&&U[0]!=T[0])||(T[1]!==null&&U[1]!=T[1])){this.setXY(W,T,true);}}};B.Dom.batch(Q,R,B.Dom,true);},setX:function(R,Q){B.Dom.setXY(R,[Q,null]);},setY:function(Q,R){B.Dom.setXY(Q,[null,R]);},getRegion:function(Q){var R=function(S){if((S.parentNode===null||S.offsetParent===null||this.getStyle(S,"display")=="none")&&S!=N.body){return false;}var T=B.Region.getRegion(S);return T;};return B.Dom.batch(Q,R,B.Dom,true);},getClientWidth:function(){return B.Dom.getViewportWidth();},getClientHeight:function(){return B.Dom.getViewportHeight();},getElementsByClassName:function(U,Y,V,W){Y=Y||"*";V=(V)?B.Dom.get(V):null||N;if(!V){return[];}var R=[],Q=V.getElementsByTagName(Y),X=P(U);for(var S=0,T=Q.length;S<T;++S){if(X.test(Q[S].className)){R[R.length]=Q[S];if(W){W.call(Q[S],Q[S]);}}}return R;},hasClass:function(S,R){var Q=P(R);var T=function(U){return Q.test(U.className);};return B.Dom.batch(S,T,B.Dom,true);},addClass:function(R,Q){var S=function(T){if(this.hasClass(T,Q)){return false;}T.className=YAHOO.lang.trim([T.className,Q].join(" "));return true;};return B.Dom.batch(R,S,B.Dom,true);},removeClass:function(S,R){var Q=P(R);var T=function(U){if(!this.hasClass(U,R)){return false;}var V=U.className;U.className=V.replace(Q," ");if(this.hasClass(U,R)){this.removeClass(U,R);}U.className=YAHOO.lang.trim(U.className);return true;};return B.Dom.batch(S,T,B.Dom,true);},replaceClass:function(T,R,Q){if(!Q||R===Q){return false;}var S=P(R);var U=function(V){if(!this.hasClass(V,R)){this.addClass(V,Q);return true;}V.className=V.className.replace(S," "+Q+" ");if(this.hasClass(V,R)){this.replaceClass(V,R,Q);}V.className=YAHOO.lang.trim(V.className);return true;};return B.Dom.batch(T,U,B.Dom,true);},generateId:function(Q,S){S=S||"yui-gen";var R=function(T){if(T&&T.id){return T.id;}var U=S+H++;if(T){T.id=U;}return U;};return B.Dom.batch(Q,R,B.Dom,true)||R.apply(B.Dom,arguments);},isAncestor:function(Q,R){Q=B.Dom.get(Q);R=B.Dom.get(R);if(!Q||!R){return false;}if(Q.contains&&R.nodeType&&!M){return Q.contains(R);}else{if(Q.compareDocumentPosition&&R.nodeType){return !!(Q.compareDocumentPosition(R)&16);}else{if(R.nodeType){return !!this.getAncestorBy(R,function(S){return S==Q;});}}}return false;},inDocument:function(Q){return this.isAncestor(N.documentElement,Q);},getElementsBy:function(X,R,S,U){R=R||"*";S=(S)?B.Dom.get(S):null||N;if(!S){return[];}var T=[],W=S.getElementsByTagName(R);for(var V=0,Q=W.length;V<Q;++V){if(X(W[V])){T[T.length]=W[V];if(U){U(W[V]);}}}return T;},batch:function(U,X,W,S){U=(U&&(U.tagName||U.item))?U:B.Dom.get(U);if(!U||!X){return false;}var T=(S)?W:window;if(U.tagName||U.length===undefined){return X.call(T,U,W);}var V=[];for(var R=0,Q=U.length;R<Q;++R){V[V.length]=X.call(T,U[R],W);}return V;},getDocumentHeight:function(){var R=(N.compatMode!="CSS1Compat")?N.body.scrollHeight:N.documentElement.scrollHeight;var Q=Math.max(R,B.Dom.getViewportHeight());return Q;},getDocumentWidth:function(){var R=(N.compatMode!="CSS1Compat")?N.body.scrollWidth:N.documentElement.scrollWidth;var Q=Math.max(R,B.Dom.getViewportWidth());return Q;},getViewportHeight:function(){var Q=self.innerHeight;var R=N.compatMode;if((R||G)&&!C){Q=(R=="CSS1Compat")?N.documentElement.clientHeight:N.body.clientHeight;
}return Q;},getViewportWidth:function(){var Q=self.innerWidth;var R=N.compatMode;if(R||G){Q=(R=="CSS1Compat")?N.documentElement.clientWidth:N.body.clientWidth;}return Q;},getAncestorBy:function(Q,R){while(Q=Q.parentNode){if(D(Q,R)){return Q;}}return null;},getAncestorByClassName:function(R,Q){R=B.Dom.get(R);if(!R){return null;}var S=function(T){return B.Dom.hasClass(T,Q);};return B.Dom.getAncestorBy(R,S);},getAncestorByTagName:function(R,Q){R=B.Dom.get(R);if(!R){return null;}var S=function(T){return T.tagName&&T.tagName.toUpperCase()==Q.toUpperCase();};return B.Dom.getAncestorBy(R,S);},getPreviousSiblingBy:function(Q,R){while(Q){Q=Q.previousSibling;if(D(Q,R)){return Q;}}return null;},getPreviousSibling:function(Q){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getPreviousSiblingBy(Q);},getNextSiblingBy:function(Q,R){while(Q){Q=Q.nextSibling;if(D(Q,R)){return Q;}}return null;},getNextSibling:function(Q){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getNextSiblingBy(Q);},getFirstChildBy:function(Q,S){var R=(D(Q.firstChild,S))?Q.firstChild:null;return R||B.Dom.getNextSiblingBy(Q.firstChild,S);},getFirstChild:function(Q,R){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getFirstChildBy(Q);},getLastChildBy:function(Q,S){if(!Q){return null;}var R=(D(Q.lastChild,S))?Q.lastChild:null;return R||B.Dom.getPreviousSiblingBy(Q.lastChild,S);},getLastChild:function(Q){Q=B.Dom.get(Q);return B.Dom.getLastChildBy(Q);},getChildrenBy:function(R,T){var S=B.Dom.getFirstChildBy(R,T);var Q=S?[S]:[];B.Dom.getNextSiblingBy(S,function(U){if(!T||T(U)){Q[Q.length]=U;}return false;});return Q;},getChildren:function(Q){Q=B.Dom.get(Q);if(!Q){}return B.Dom.getChildrenBy(Q);},getDocumentScrollLeft:function(Q){Q=Q||N;return Math.max(Q.documentElement.scrollLeft,Q.body.scrollLeft);},getDocumentScrollTop:function(Q){Q=Q||N;return Math.max(Q.documentElement.scrollTop,Q.body.scrollTop);},insertBefore:function(R,Q){R=B.Dom.get(R);Q=B.Dom.get(Q);if(!R||!Q||!Q.parentNode){return null;}return Q.parentNode.insertBefore(R,Q);},insertAfter:function(R,Q){R=B.Dom.get(R);Q=B.Dom.get(Q);if(!R||!Q||!Q.parentNode){return null;}if(Q.nextSibling){return Q.parentNode.insertBefore(R,Q.nextSibling);}else{return Q.parentNode.appendChild(R);}},getClientRegion:function(){var S=B.Dom.getDocumentScrollTop(),R=B.Dom.getDocumentScrollLeft(),T=B.Dom.getViewportWidth()+R,Q=B.Dom.getViewportHeight()+S;return new B.Region(S,T,Q,R);}};var I=function(){if(N.documentElement.getBoundingClientRect){return function(R){var S=R.getBoundingClientRect();var Q=R.ownerDocument;return[S.left+B.Dom.getDocumentScrollLeft(Q),S.top+B.Dom.getDocumentScrollTop(Q)];};}else{return function(S){var T=[S.offsetLeft,S.offsetTop];var R=S.offsetParent;var Q=(M&&B.Dom.getStyle(S,"position")=="absolute"&&S.offsetParent==S.ownerDocument.body);if(R!=S){while(R){T[0]+=R.offsetLeft;T[1]+=R.offsetTop;if(!Q&&M&&B.Dom.getStyle(R,"position")=="absolute"){Q=true;}R=R.offsetParent;}}if(Q){T[0]-=S.ownerDocument.body.offsetLeft;T[1]-=S.ownerDocument.body.offsetTop;}R=S.parentNode;while(R.tagName&&!E.ROOT_TAG.test(R.tagName)){if(B.Dom.getStyle(R,"display").search(/^inline|table-row.*$/i)){T[0]-=R.scrollLeft;T[1]-=R.scrollTop;}R=R.parentNode;}return T;};}}();})();YAHOO.util.Region=function(C,D,A,B){this.top=C;this[1]=C;this.right=D;this.bottom=A;this.left=B;this[0]=B;};YAHOO.util.Region.prototype.contains=function(A){return(A.left>=this.left&&A.right<=this.right&&A.top>=this.top&&A.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(E){var C=Math.max(this.top,E.top);var D=Math.min(this.right,E.right);var A=Math.min(this.bottom,E.bottom);var B=Math.max(this.left,E.left);if(A>=C&&D>=B){return new YAHOO.util.Region(C,D,A,B);}else{return null;}};YAHOO.util.Region.prototype.union=function(E){var C=Math.min(this.top,E.top);var D=Math.max(this.right,E.right);var A=Math.max(this.bottom,E.bottom);var B=Math.min(this.left,E.left);return new YAHOO.util.Region(C,D,A,B);};YAHOO.util.Region.prototype.toString=function(){return("Region {top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+"}");};YAHOO.util.Region.getRegion=function(D){var F=YAHOO.util.Dom.getXY(D);var C=F[1];var E=F[0]+D.offsetWidth;var A=F[1]+D.offsetHeight;var B=F[0];return new YAHOO.util.Region(C,E,A,B);};YAHOO.util.Point=function(A,B){if(YAHOO.lang.isArray(A)){B=A[1];A=A[0];}this.x=this.right=this.left=this[0]=A;this.y=this.top=this.bottom=this[1]=B;};YAHOO.util.Point.prototype=new YAHOO.util.Region();YAHOO.register("dom",YAHOO.util.Dom,{version:"2.4.1",build:"742"});YAHOO.util.CustomEvent=function(D,B,C,A){this.type=D;this.scope=B||window;this.silent=C;this.signature=A||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var E="_YUICEOnSubscribe";if(D!==E){this.subscribeEvent=new YAHOO.util.CustomEvent(E,this,true);}this.lastError=null;};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(B,C,A){if(!B){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,A);}this.subscribers.push(new YAHOO.util.Subscriber(B,C,A));},unsubscribe:function(D,F){if(!D){return this.unsubscribeAll();}var E=false;for(var B=0,A=this.subscribers.length;B<A;++B){var C=this.subscribers[B];if(C&&C.contains(D,F)){this._delete(B);E=true;}}return E;},fire:function(){var D=this.subscribers.length;if(!D&&this.silent){return true;}var H=[],F=true,C,I=false;for(C=0;C<arguments.length;++C){H.push(arguments[C]);}if(!this.silent){}for(C=0;C<D;++C){var L=this.subscribers[C];if(!L){I=true;}else{if(!this.silent){}var K=L.getScope(this.scope);if(this.signature==YAHOO.util.CustomEvent.FLAT){var A=null;if(H.length>0){A=H[0];}try{F=L.fn.call(K,A,L.obj);}catch(E){this.lastError=E;}}else{try{F=L.fn.call(K,this.type,H,L.obj);}catch(G){this.lastError=G;}}if(false===F){if(!this.silent){}return false;}}}if(I){var J=[],B=this.subscribers;for(C=0,D=B.length;C<D;C=C+1){J.push(B[C]);}this.subscribers=J;}return true;},unsubscribeAll:function(){for(var B=0,A=this.subscribers.length;B<A;++B){this._delete(A-1-B);}this.subscribers=[];return B;},_delete:function(A){var B=this.subscribers[A];if(B){delete B.fn;delete B.obj;}this.subscribers[A]=null;},toString:function(){return"CustomEvent: '"+this.type+"', scope: "+this.scope;}};YAHOO.util.Subscriber=function(B,C,A){this.fn=B;this.obj=YAHOO.lang.isUndefined(C)?null:C;this.override=A;};YAHOO.util.Subscriber.prototype.getScope=function(A){if(this.override){if(this.override===true){return this.obj;}else{return this.override;}}return A;};YAHOO.util.Subscriber.prototype.contains=function(A,B){if(B){return(this.fn==A&&this.obj==B);}else{return(this.fn==A);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", override: "+(this.override||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var H=false;var I=[];var J=[];var G=[];var E=[];var C=0;var F=[];var B=[];var A=0;var D={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9};return{POLL_RETRYS:4000,POLL_INTERVAL:10,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:YAHOO.env.ua.ie,_interval:null,_dri:null,DOMReady:false,startInterval:function(){if(!this._interval){var K=this;var L=function(){K._tryPreloadAttach();};this._interval=setInterval(L,this.POLL_INTERVAL);}},onAvailable:function(P,M,Q,O,N){var K=(YAHOO.lang.isString(P))?[P]:P;for(var L=0;L<K.length;L=L+1){F.push({id:K[L],fn:M,obj:Q,override:O,checkReady:N});}C=this.POLL_RETRYS;this.startInterval();},onContentReady:function(M,K,N,L){this.onAvailable(M,K,N,L,true);},onDOMReady:function(K,M,L){if(this.DOMReady){setTimeout(function(){var N=window;if(L){if(L===true){N=M;}else{N=L;}}K.call(N,"DOMReady",[],M);},0);}else{this.DOMReadyEvent.subscribe(K,M,L);}},addListener:function(M,K,V,Q,L){if(!V||!V.call){return false;}if(this._isValidCollection(M)){var W=true;for(var R=0,T=M.length;R<T;++R){W=this.on(M[R],K,V,Q,L)&&W;}return W;}else{if(YAHOO.lang.isString(M)){var P=this.getEl(M);if(P){M=P;}else{this.onAvailable(M,function(){YAHOO.util.Event.on(M,K,V,Q,L);});return true;}}}if(!M){return false;}if("unload"==K&&Q!==this){J[J.length]=[M,K,V,Q,L];return true;}var Y=M;if(L){if(L===true){Y=Q;}else{Y=L;}}var N=function(Z){return V.call(Y,YAHOO.util.Event.getEvent(Z,M),Q);};var X=[M,K,V,N,Y,Q,L];var S=I.length;I[S]=X;if(this.useLegacyEvent(M,K)){var O=this.getLegacyIndex(M,K);if(O==-1||M!=G[O][0]){O=G.length;B[M.id+K]=O;G[O]=[M,K,M["on"+K]];E[O]=[];M["on"+K]=function(Z){YAHOO.util.Event.fireLegacyEvent(YAHOO.util.Event.getEvent(Z),O);};}E[O].push(X);}else{try{this._simpleAdd(M,K,N,false);}catch(U){this.lastError=U;this.removeListener(M,K,V);return false;}}return true;},fireLegacyEvent:function(O,M){var Q=true,K,S,R,T,P;S=E[M];for(var L=0,N=S.length;L<N;++L){R=S[L];if(R&&R[this.WFN]){T=R[this.ADJ_SCOPE];P=R[this.WFN].call(T,O);Q=(Q&&P);}}K=G[M];if(K&&K[2]){K[2](O);}return Q;},getLegacyIndex:function(L,M){var K=this.generateId(L)+M;if(typeof B[K]=="undefined"){return -1;}else{return B[K];}},useLegacyEvent:function(L,M){if(this.webkit&&("click"==M||"dblclick"==M)){var K=parseInt(this.webkit,10);if(!isNaN(K)&&K<418){return true;}}return false;},removeListener:function(L,K,T){var O,R,V;if(typeof L=="string"){L=this.getEl(L);}else{if(this._isValidCollection(L)){var U=true;for(O=0,R=L.length;O<R;++O){U=(this.removeListener(L[O],K,T)&&U);}return U;}}if(!T||!T.call){return this.purgeElement(L,false,K);}if("unload"==K){for(O=0,R=J.length;O<R;O++){V=J[O];if(V&&V[0]==L&&V[1]==K&&V[2]==T){J[O]=null;return true;}}return false;}var P=null;var Q=arguments[3];if("undefined"===typeof Q){Q=this._getCacheIndex(L,K,T);}if(Q>=0){P=I[Q];}if(!L||!P){return false;}if(this.useLegacyEvent(L,K)){var N=this.getLegacyIndex(L,K);var M=E[N];if(M){for(O=0,R=M.length;O<R;++O){V=M[O];if(V&&V[this.EL]==L&&V[this.TYPE]==K&&V[this.FN]==T){M[O]=null;break;}}}}else{try{this._simpleRemove(L,K,P[this.WFN],false);}catch(S){this.lastError=S;return false;}}delete I[Q][this.WFN];delete I[Q][this.FN];I[Q]=null;return true;},getTarget:function(M,L){var K=M.target||M.srcElement;return this.resolveTextNode(K);},resolveTextNode:function(K){if(K&&3==K.nodeType){return K.parentNode;}else{return K;}},getPageX:function(L){var K=L.pageX;if(!K&&0!==K){K=L.clientX||0;if(this.isIE){K+=this._getScrollLeft();}}return K;},getPageY:function(K){var L=K.pageY;if(!L&&0!==L){L=K.clientY||0;if(this.isIE){L+=this._getScrollTop();}}return L;},getXY:function(K){return[this.getPageX(K),this.getPageY(K)];
},getRelatedTarget:function(L){var K=L.relatedTarget;if(!K){if(L.type=="mouseout"){K=L.toElement;}else{if(L.type=="mouseover"){K=L.fromElement;}}}return this.resolveTextNode(K);},getTime:function(M){if(!M.time){var L=new Date().getTime();try{M.time=L;}catch(K){this.lastError=K;return L;}}return M.time;},stopEvent:function(K){this.stopPropagation(K);this.preventDefault(K);},stopPropagation:function(K){if(K.stopPropagation){K.stopPropagation();}else{K.cancelBubble=true;}},preventDefault:function(K){if(K.preventDefault){K.preventDefault();}else{K.returnValue=false;}},getEvent:function(M,K){var L=M||window.event;if(!L){var N=this.getEvent.caller;while(N){L=N.arguments[0];if(L&&Event==L.constructor){break;}N=N.caller;}}return L;},getCharCode:function(L){var K=L.keyCode||L.charCode||0;if(YAHOO.env.ua.webkit&&(K in D)){K=D[K];}return K;},_getCacheIndex:function(O,P,N){for(var M=0,L=I.length;M<L;++M){var K=I[M];if(K&&K[this.FN]==N&&K[this.EL]==O&&K[this.TYPE]==P){return M;}}return -1;},generateId:function(K){var L=K.id;if(!L){L="yuievtautoid-"+A;++A;K.id=L;}return L;},_isValidCollection:function(L){try{return(L&&typeof L!=="string"&&L.length&&!L.tagName&&!L.alert&&typeof L[0]!=="undefined");}catch(K){return false;}},elCache:{},getEl:function(K){return(typeof K==="string")?document.getElementById(K):K;},clearCache:function(){},DOMReadyEvent:new YAHOO.util.CustomEvent("DOMReady",this),_load:function(L){if(!H){H=true;var K=YAHOO.util.Event;K._ready();K._tryPreloadAttach();}},_ready:function(L){var K=YAHOO.util.Event;if(!K.DOMReady){K.DOMReady=true;K.DOMReadyEvent.fire();K._simpleRemove(document,"DOMContentLoaded",K._ready);}},_tryPreloadAttach:function(){if(this.locked){return false;}if(this.isIE){if(!this.DOMReady){this.startInterval();return false;}}this.locked=true;var P=!H;if(!P){P=(C>0);}var O=[];var Q=function(S,T){var R=S;if(T.override){if(T.override===true){R=T.obj;}else{R=T.override;}}T.fn.call(R,T.obj);};var L,K,N,M;for(L=0,K=F.length;L<K;++L){N=F[L];if(N&&!N.checkReady){M=this.getEl(N.id);if(M){Q(M,N);F[L]=null;}else{O.push(N);}}}for(L=0,K=F.length;L<K;++L){N=F[L];if(N&&N.checkReady){M=this.getEl(N.id);if(M){if(H||M.nextSibling){Q(M,N);F[L]=null;}}else{O.push(N);}}}C=(O.length===0)?0:C-1;if(P){this.startInterval();}else{clearInterval(this._interval);this._interval=null;}this.locked=false;return true;},purgeElement:function(O,P,R){var M=(YAHOO.lang.isString(O))?this.getEl(O):O;var Q=this.getListeners(M,R),N,K;if(Q){for(N=0,K=Q.length;N<K;++N){var L=Q[N];this.removeListener(M,L.type,L.fn,L.index);}}if(P&&M&&M.childNodes){for(N=0,K=M.childNodes.length;N<K;++N){this.purgeElement(M.childNodes[N],P,R);}}},getListeners:function(M,K){var P=[],L;if(!K){L=[I,J];}else{if(K==="unload"){L=[J];}else{L=[I];}}var R=(YAHOO.lang.isString(M))?this.getEl(M):M;for(var O=0;O<L.length;O=O+1){var T=L[O];if(T&&T.length>0){for(var Q=0,S=T.length;Q<S;++Q){var N=T[Q];if(N&&N[this.EL]===R&&(!K||K===N[this.TYPE])){P.push({type:N[this.TYPE],fn:N[this.FN],obj:N[this.OBJ],adjust:N[this.OVERRIDE],scope:N[this.ADJ_SCOPE],index:Q});}}}}return(P.length)?P:null;},_unload:function(R){var Q=YAHOO.util.Event,O,N,L,K,M;for(O=0,K=J.length;O<K;++O){L=J[O];if(L){var P=window;if(L[Q.ADJ_SCOPE]){if(L[Q.ADJ_SCOPE]===true){P=L[Q.UNLOAD_OBJ];}else{P=L[Q.ADJ_SCOPE];}}L[Q.FN].call(P,Q.getEvent(R,L[Q.EL]),L[Q.UNLOAD_OBJ]);J[O]=null;L=null;P=null;}}J=null;if(YAHOO.env.ua.ie&&I&&I.length>0){N=I.length;while(N){M=N-1;L=I[M];if(L){Q.removeListener(L[Q.EL],L[Q.TYPE],L[Q.FN],M);}N--;}L=null;}G=null;Q._simpleRemove(window,"unload",Q._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var K=document.documentElement,L=document.body;if(K&&(K.scrollTop||K.scrollLeft)){return[K.scrollTop,K.scrollLeft];}else{if(L){return[L.scrollTop,L.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(M,N,L,K){M.addEventListener(N,L,(K));};}else{if(window.attachEvent){return function(M,N,L,K){M.attachEvent("on"+N,L);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(M,N,L,K){M.removeEventListener(N,L,(K));};}else{if(window.detachEvent){return function(L,M,K){L.detachEvent("on"+M,K);};}else{return function(){};}}}()};}();(function(){var A=YAHOO.util.Event;A.on=A.addListener;if(A.isIE){YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);A._dri=setInterval(function(){var C=document.createElement("p");try{C.doScroll("left");clearInterval(A._dri);A._dri=null;A._ready();C=null;}catch(B){C=null;}},A.POLL_INTERVAL);}else{if(A.webkit){A._dri=setInterval(function(){var B=document.readyState;if("loaded"==B||"complete"==B){clearInterval(A._dri);A._dri=null;A._ready();}},A.POLL_INTERVAL);}else{A._simpleAdd(document,"DOMContentLoaded",A._ready);}}A._simpleAdd(window,"load",A._load);A._simpleAdd(window,"unload",A._unload);A._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscribers=this.__yui_subscribers||{};var B=this.__yui_subscribers;if(!B[A]){B[A]=[];}B[A].push({fn:C,obj:F,override:E});}},unsubscribe:function(C,E,G){this.__yui_events=this.__yui_events||{};var A=this.__yui_events;if(C){var F=A[C];if(F){return F.unsubscribe(E,G);}}else{var B=true;for(var D in A){if(YAHOO.lang.hasOwnProperty(A,D)){B=B&&A[D].unsubscribe(E,G);}}return B;}return false;},unsubscribeAll:function(A){return this.unsubscribe(A);},createEvent:function(G,D){this.__yui_events=this.__yui_events||{};var A=D||{};var I=this.__yui_events;if(I[G]){}else{var H=A.scope||this;var E=(A.silent);var B=new YAHOO.util.CustomEvent(G,H,E,YAHOO.util.CustomEvent.FLAT);I[G]=B;if(A.onSubscribeCallback){B.subscribeEvent.subscribe(A.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};
var F=this.__yui_subscribers[G];if(F){for(var C=0;C<F.length;++C){B.subscribe(F[C].fn,F[C].obj,F[C].override);}}}return I[G];},fireEvent:function(E,D,A,C){this.__yui_events=this.__yui_events||{};var G=this.__yui_events[E];if(!G){return null;}var B=[];for(var F=1;F<arguments.length;++F){B.push(arguments[F]);}return G.fire.apply(G,B);},hasEvent:function(A){if(this.__yui_events){if(this.__yui_events[A]){return true;}}return false;}};YAHOO.util.KeyListener=function(A,F,B,C){if(!A){}else{if(!F){}else{if(!B){}}}if(!C){C=YAHOO.util.KeyListener.KEYDOWN;}var D=new YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=new YAHOO.util.CustomEvent("enabled");this.disabledEvent=new YAHOO.util.CustomEvent("disabled");if(typeof A=="string"){A=document.getElementById(A);}if(typeof B=="function"){D.subscribe(B);}else{D.subscribe(B.fn,B.scope,B.correctScope);}function E(J,I){if(!F.shift){F.shift=false;}if(!F.alt){F.alt=false;}if(!F.ctrl){F.ctrl=false;}if(J.shiftKey==F.shift&&J.altKey==F.alt&&J.ctrlKey==F.ctrl){var G;if(F.keys instanceof Array){for(var H=0;H<F.keys.length;H++){G=F.keys[H];if(G==J.charCode){D.fire(J.charCode,J);break;}else{if(G==J.keyCode){D.fire(J.keyCode,J);break;}}}}else{G=F.keys;if(G==J.charCode){D.fire(J.charCode,J);}else{if(G==J.keyCode){D.fire(J.keyCode,J);}}}}}this.enable=function(){if(!this.enabled){YAHOO.util.Event.addListener(A,C,E);this.enabledEvent.fire(F);}this.enabled=true;};this.disable=function(){if(this.enabled){YAHOO.util.Event.removeListener(A,C,E);this.disabledEvent.fire(F);}this.enabled=false;};this.toString=function(){return"KeyListener ["+F.keys+"] "+A.tagName+(A.id?"["+A.id+"]":"");};};YAHOO.util.KeyListener.KEYDOWN="keydown";YAHOO.util.KeyListener.KEYUP="keyup";YAHOO.util.KeyListener.KEY={ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:32,TAB:9,UP:38};YAHOO.register("event",YAHOO.util.Event,{version:"2.4.1",build:"742"});YAHOO.register("yahoo-dom-event", YAHOO, {version: "2.4.1", build: "742"});
YAHOO.util.Anim=function(B,A,C,D){if(!B){}this.init(B,A,C,D);};YAHOO.util.Anim.prototype={toString:function(){var A=this.getEl();var B=A.id||A.tagName||A;return("Anim "+B);},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(A,C,B){return this.method(this.currentFrame,C,B-C,this.totalFrames);},setAttribute:function(A,C,B){if(this.patterns.noNegatives.test(A)){C=(C>0)?C:0;}YAHOO.util.Dom.setStyle(this.getEl(),A,C+B);},getAttribute:function(A){var C=this.getEl();var E=YAHOO.util.Dom.getStyle(C,A);if(E!=="auto"&&!this.patterns.offsetUnit.test(E)){return parseFloat(E);}var B=this.patterns.offsetAttribute.exec(A)||[];var F=!!(B[3]);var D=!!(B[2]);if(D||(YAHOO.util.Dom.getStyle(C,"position")=="absolute"&&F)){E=C["offset"+B[0].charAt(0).toUpperCase()+B[0].substr(1)];}else{E=0;}return E;},getDefaultUnit:function(A){if(this.patterns.defaultUnit.test(A)){return"px";}return"";},setRuntimeAttribute:function(B){var G;var C;var D=this.attributes;this.runtimeAttributes[B]={};var F=function(H){return(typeof H!=="undefined");};if(!F(D[B]["to"])&&!F(D[B]["by"])){return false;}G=(F(D[B]["from"]))?D[B]["from"]:this.getAttribute(B);if(F(D[B]["to"])){C=D[B]["to"];}else{if(F(D[B]["by"])){if(G.constructor==Array){C=[];for(var E=0,A=G.length;E<A;++E){C[E]=G[E]+D[B]["by"][E]*1;}}else{C=G+D[B]["by"]*1;}}}this.runtimeAttributes[B].start=G;this.runtimeAttributes[B].end=C;this.runtimeAttributes[B].unit=(F(D[B].unit))?D[B]["unit"]:this.getDefaultUnit(B);return true;},init:function(C,H,G,A){var B=false;var D=null;var F=0;C=YAHOO.util.Dom.get(C);this.attributes=H||{};this.duration=!YAHOO.lang.isUndefined(G)?G:1;this.method=A||YAHOO.util.Easing.easeNone;this.useSeconds=true;this.currentFrame=0;this.totalFrames=YAHOO.util.AnimMgr.fps;this.setEl=function(K){C=YAHOO.util.Dom.get(K);};this.getEl=function(){return C;};this.isAnimated=function(){return B;};this.getStartTime=function(){return D;};this.runtimeAttributes={};this.animate=function(){if(this.isAnimated()){return false;}this.currentFrame=0;this.totalFrames=(this.useSeconds)?Math.ceil(YAHOO.util.AnimMgr.fps*this.duration):this.duration;if(this.duration===0&&this.useSeconds){this.totalFrames=1;}YAHOO.util.AnimMgr.registerElement(this);return true;};this.stop=function(K){if(!this.isAnimated()){return false;}if(K){this.currentFrame=this.totalFrames;this._onTween.fire();}YAHOO.util.AnimMgr.stop(this);};var J=function(){this.onStart.fire();this.runtimeAttributes={};for(var K in this.attributes){this.setRuntimeAttribute(K);}B=true;F=0;D=new Date();};var I=function(){var M={duration:new Date()-this.getStartTime(),currentFrame:this.currentFrame};M.toString=function(){return("duration: "+M.duration+", currentFrame: "+M.currentFrame);};this.onTween.fire(M);var L=this.runtimeAttributes;for(var K in L){this.setAttribute(K,this.doMethod(K,L[K].start,L[K].end),L[K].unit);}F+=1;};var E=function(){var K=(new Date()-D)/1000;var L={duration:K,frames:F,fps:F/K};L.toString=function(){return("duration: "+L.duration+", frames: "+L.frames+", fps: "+L.fps);};B=false;F=0;this.onComplete.fire(L);};this._onStart=new YAHOO.util.CustomEvent("_start",this,true);this.onStart=new YAHOO.util.CustomEvent("start",this);this.onTween=new YAHOO.util.CustomEvent("tween",this);this._onTween=new YAHOO.util.CustomEvent("_tween",this,true);this.onComplete=new YAHOO.util.CustomEvent("complete",this);this._onComplete=new YAHOO.util.CustomEvent("_complete",this,true);this._onStart.subscribe(J);this._onTween.subscribe(I);this._onComplete.subscribe(E);}};YAHOO.util.AnimMgr=new function(){var C=null;var B=[];var A=0;this.fps=1000;this.delay=1;this.registerElement=function(F){B[B.length]=F;A+=1;F._onStart.fire();this.start();};this.unRegister=function(G,F){F=F||E(G);if(!G.isAnimated()||F==-1){return false;}G._onComplete.fire();B.splice(F,1);A-=1;if(A<=0){this.stop();}return true;};this.start=function(){if(C===null){C=setInterval(this.run,this.delay);}};this.stop=function(H){if(!H){clearInterval(C);for(var G=0,F=B.length;G<F;++G){this.unRegister(B[0],0);}B=[];C=null;A=0;}else{this.unRegister(H);}};this.run=function(){for(var H=0,F=B.length;H<F;++H){var G=B[H];if(!G||!G.isAnimated()){continue;}if(G.currentFrame<G.totalFrames||G.totalFrames===null){G.currentFrame+=1;if(G.useSeconds){D(G);}G._onTween.fire();}else{YAHOO.util.AnimMgr.stop(G,H);}}};var E=function(H){for(var G=0,F=B.length;G<F;++G){if(B[G]==H){return G;}}return -1;};var D=function(G){var J=G.totalFrames;var I=G.currentFrame;var H=(G.currentFrame*G.duration*1000/G.totalFrames);var F=(new Date()-G.getStartTime());var K=0;if(F<G.duration*1000){K=Math.round((F/H-1)*G.currentFrame);}else{K=J-(I+1);}if(K>0&&isFinite(K)){if(G.currentFrame+K>=J){K=J-(I+1);}G.currentFrame+=K;}};};YAHOO.util.Bezier=new function(){this.getPosition=function(E,D){var F=E.length;var C=[];for(var B=0;B<F;++B){C[B]=[E[B][0],E[B][1]];}for(var A=1;A<F;++A){for(B=0;B<F-A;++B){C[B][0]=(1-D)*C[B][0]+D*C[parseInt(B+1,10)][0];C[B][1]=(1-D)*C[B][1]+D*C[parseInt(B+1,10)][1];}}return[C[0][0],C[0][1]];};};(function(){YAHOO.util.ColorAnim=function(E,D,F,G){YAHOO.util.ColorAnim.superclass.constructor.call(this,E,D,F,G);};YAHOO.extend(YAHOO.util.ColorAnim,YAHOO.util.Anim);var B=YAHOO.util;var C=B.ColorAnim.superclass;var A=B.ColorAnim.prototype;A.toString=function(){var D=this.getEl();var E=D.id||D.tagName;return("ColorAnim "+E);};A.patterns.color=/color$/i;A.patterns.rgb=/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;A.patterns.hex=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;A.patterns.hex3=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;A.patterns.transparent=/^transparent|rgba\(0, 0, 0, 0\)$/;A.parseColor=function(D){if(D.length==3){return D;}var E=this.patterns.hex.exec(D);if(E&&E.length==4){return[parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16)];}E=this.patterns.rgb.exec(D);if(E&&E.length==4){return[parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10)];
}E=this.patterns.hex3.exec(D);if(E&&E.length==4){return[parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16)];}return null;};A.getAttribute=function(D){var F=this.getEl();if(this.patterns.color.test(D)){var G=YAHOO.util.Dom.getStyle(F,D);if(this.patterns.transparent.test(G)){var E=F.parentNode;G=B.Dom.getStyle(E,D);while(E&&this.patterns.transparent.test(G)){E=E.parentNode;G=B.Dom.getStyle(E,D);if(E.tagName.toUpperCase()=="HTML"){G="#fff";}}}}else{G=C.getAttribute.call(this,D);}return G;};A.doMethod=function(E,I,F){var H;if(this.patterns.color.test(E)){H=[];for(var G=0,D=I.length;G<D;++G){H[G]=C.doMethod.call(this,E,I[G],F[G]);}H="rgb("+Math.floor(H[0])+","+Math.floor(H[1])+","+Math.floor(H[2])+")";}else{H=C.doMethod.call(this,E,I,F);}return H;};A.setRuntimeAttribute=function(E){C.setRuntimeAttribute.call(this,E);if(this.patterns.color.test(E)){var G=this.attributes;var I=this.parseColor(this.runtimeAttributes[E].start);var F=this.parseColor(this.runtimeAttributes[E].end);if(typeof G[E]["to"]==="undefined"&&typeof G[E]["by"]!=="undefined"){F=this.parseColor(G[E].by);for(var H=0,D=I.length;H<D;++H){F[H]=I[H]+F[H];}}this.runtimeAttributes[E].start=I;this.runtimeAttributes[E].end=F;}};})();YAHOO.util.Easing={easeNone:function(B,A,D,C){return D*B/C+A;},easeIn:function(B,A,D,C){return D*(B/=C)*B+A;},easeOut:function(B,A,D,C){return -D*(B/=C)*(B-2)+A;},easeBoth:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B+A;}return -D/2*((--B)*(B-2)-1)+A;},easeInStrong:function(B,A,D,C){return D*(B/=C)*B*B*B+A;},easeOutStrong:function(B,A,D,C){return -D*((B=B/C-1)*B*B*B-1)+A;},easeBothStrong:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B*B*B+A;}return -D/2*((B-=2)*B*B*B-2)+A;},elasticIn:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return -(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;},elasticOut:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return B*Math.pow(2,-10*C)*Math.sin((C*F-D)*(2*Math.PI)/E)+G+A;},elasticBoth:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F/2)==2){return A+G;}if(!E){E=F*(0.3*1.5);}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}if(C<1){return -0.5*(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;}return B*Math.pow(2,-10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E)*0.5+G+A;},backIn:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*(B/=D)*B*((C+1)*B-C)+A;},backOut:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*((B=B/D-1)*B*((C+1)*B+C)+1)+A;},backBoth:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}if((B/=D/2)<1){return E/2*(B*B*(((C*=(1.525))+1)*B-C))+A;}return E/2*((B-=2)*B*(((C*=(1.525))+1)*B+C)+2)+A;},bounceIn:function(B,A,D,C){return D-YAHOO.util.Easing.bounceOut(C-B,0,D,C)+A;},bounceOut:function(B,A,D,C){if((B/=C)<(1/2.75)){return D*(7.5625*B*B)+A;}else{if(B<(2/2.75)){return D*(7.5625*(B-=(1.5/2.75))*B+0.75)+A;}else{if(B<(2.5/2.75)){return D*(7.5625*(B-=(2.25/2.75))*B+0.9375)+A;}}}return D*(7.5625*(B-=(2.625/2.75))*B+0.984375)+A;},bounceBoth:function(B,A,D,C){if(B<C/2){return YAHOO.util.Easing.bounceIn(B*2,0,D,C)*0.5+A;}return YAHOO.util.Easing.bounceOut(B*2-C,0,D,C)*0.5+D*0.5+A;}};(function(){YAHOO.util.Motion=function(G,F,H,I){if(G){YAHOO.util.Motion.superclass.constructor.call(this,G,F,H,I);}};YAHOO.extend(YAHOO.util.Motion,YAHOO.util.ColorAnim);var D=YAHOO.util;var E=D.Motion.superclass;var B=D.Motion.prototype;B.toString=function(){var F=this.getEl();var G=F.id||F.tagName;return("Motion "+G);};B.patterns.points=/^points$/i;B.setAttribute=function(F,H,G){if(this.patterns.points.test(F)){G=G||"px";E.setAttribute.call(this,"left",H[0],G);E.setAttribute.call(this,"top",H[1],G);}else{E.setAttribute.call(this,F,H,G);}};B.getAttribute=function(F){if(this.patterns.points.test(F)){var G=[E.getAttribute.call(this,"left"),E.getAttribute.call(this,"top")];}else{G=E.getAttribute.call(this,F);}return G;};B.doMethod=function(F,J,G){var I=null;if(this.patterns.points.test(F)){var H=this.method(this.currentFrame,0,100,this.totalFrames)/100;I=D.Bezier.getPosition(this.runtimeAttributes[F],H);}else{I=E.doMethod.call(this,F,J,G);}return I;};B.setRuntimeAttribute=function(O){if(this.patterns.points.test(O)){var G=this.getEl();var I=this.attributes;var F;var K=I["points"]["control"]||[];var H;var L,N;if(K.length>0&&!(K[0] instanceof Array)){K=[K];}else{var J=[];for(L=0,N=K.length;L<N;++L){J[L]=K[L];}K=J;}if(D.Dom.getStyle(G,"position")=="static"){D.Dom.setStyle(G,"position","relative");}if(C(I["points"]["from"])){D.Dom.setXY(G,I["points"]["from"]);}else{D.Dom.setXY(G,D.Dom.getXY(G));}F=this.getAttribute("points");if(C(I["points"]["to"])){H=A.call(this,I["points"]["to"],F);var M=D.Dom.getXY(this.getEl());for(L=0,N=K.length;L<N;++L){K[L]=A.call(this,K[L],F);}}else{if(C(I["points"]["by"])){H=[F[0]+I["points"]["by"][0],F[1]+I["points"]["by"][1]];for(L=0,N=K.length;L<N;++L){K[L]=[F[0]+K[L][0],F[1]+K[L][1]];}}}this.runtimeAttributes[O]=[F];if(K.length>0){this.runtimeAttributes[O]=this.runtimeAttributes[O].concat(K);}this.runtimeAttributes[O][this.runtimeAttributes[O].length]=H;}else{E.setRuntimeAttribute.call(this,O);}};var A=function(F,H){var G=D.Dom.getXY(this.getEl());F=[F[0]-G[0]+H[0],F[1]-G[1]+H[1]];return F;};var C=function(F){return(typeof F!=="undefined");};})();(function(){YAHOO.util.Scroll=function(E,D,F,G){if(E){YAHOO.util.Scroll.superclass.constructor.call(this,E,D,F,G);}};YAHOO.extend(YAHOO.util.Scroll,YAHOO.util.ColorAnim);var B=YAHOO.util;var C=B.Scroll.superclass;var A=B.Scroll.prototype;A.toString=function(){var D=this.getEl();var E=D.id||D.tagName;return("Scroll "+E);};A.doMethod=function(D,G,E){var F=null;if(D=="scroll"){F=[this.method(this.currentFrame,G[0],E[0]-G[0],this.totalFrames),this.method(this.currentFrame,G[1],E[1]-G[1],this.totalFrames)];
}else{F=C.doMethod.call(this,D,G,E);}return F;};A.getAttribute=function(D){var F=null;var E=this.getEl();if(D=="scroll"){F=[E.scrollLeft,E.scrollTop];}else{F=C.getAttribute.call(this,D);}return F;};A.setAttribute=function(D,G,F){var E=this.getEl();if(D=="scroll"){E.scrollLeft=G[0];E.scrollTop=G[1];}else{C.setAttribute.call(this,D,G,F);}};})();YAHOO.register("animation",YAHOO.util.Anim,{version:"2.4.1",build:"742"});

/**
 * An adapter for the Shadowbox media viewer and the Prototype + Scriptaculous
 * JavaScript framework.
 *
 * This file is part of Shadowbox.
 *
 * Shadowbox is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Shadowbox is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Shadowbox. If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Michael J. I. Jackson <mjijackson@gmail.com>
 * @copyright 2007 Michael J. I. Jackson
 * @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
 * @version SVN: $Id: shadowbox-prototype.js 55 2008-01-29 09:42:41Z mjijackson $
 */

if(typeof Prototype == 'undefined'){
 throw 'Unable to load Shadowbox, Prototype framework not found.';
}
if(typeof Effect == 'undefined'){
 throw 'Unable to load Shadowbox, Scriptaculous effects framework not found.';
}

// create the Shadowbox object first
var Shadowbox = {};

Shadowbox.lib = {

 /**
 * Gets the value of the style on the given element.
 *
 * @param {HTMLElement} el The DOM element
 * @param {String} style The name of the style (e.g. margin-top)
 * @return {mixed} The value of the given style
 * @public
 */
 getStyle: function(el, style){
 return Element.getStyle(el, style);
 },

 /**
 * Sets the style on the given element to the given value. May be an
 * object to specify multiple values.
 *
 * @param {HTMLElement} el The DOM element
 * @param {String/Object} style The name of the style to set if a
 * string, or an object of name =>
 * value pairs
 * @param {String} value The value to set the given style to
 * @return void
 * @public
 */
 setStyle: function(el, style, value){
 if(typeof style != 'object'){
 var temp = {};
 temp[style] = value;
 style = temp;
 }
 Element.setStyle(el, style);
 },

 /**
 * Gets a reference to the given element.
 *
 * @param {String/HTMLElement} el The element to fetch
 * @return {HTMLElement} A reference to the element
 * @public
 */
 get: function(el){
 return $(el);
 },

 /**
 * Removes an element from the DOM.
 *
 * @param {HTMLElement} el The element to remove
 * @return void
 * @public
 */
 remove: function(el){
 Element.remove(el);
 },

 /**
 * Gets the target of the given event. The event object passed will be
 * the same object that is passed to listeners registered with
 * addEvent().
 *
 * @param {mixed} e The event object
 * @return {HTMLElement} The event's target element
 * @public
 */
 getTarget: function(e){
 return Event.element(e);
 },

 /**
 * Prevents the event's default behavior. The event object passed will
 * be the same object that is passed to listeners registered with
 * addEvent().
 *
 * @param {mixed} e The event object
 * @return void
 * @public
 */
 preventDefault: function(e){
 Event.stop(e);
 },

 /**
 * Adds an event listener to the given element. It is expected that this
 * function will be passed the event as its first argument.
 *
 * @param {HTMLElement} el The DOM element to listen to
 * @param {String} name The name of the event to register
 * (i.e. 'click', 'scroll', etc.)
 * @param {Function} handler The event handler function
 * @return void
 * @public
 */
 addEvent: function(el, name, handler){
 Event.observe(el, name, handler);
 },

 /**
 * Removes an event listener from the given element.
 *
 * @param {HTMLElement} el The DOM element to stop listening to
 * @param {String} name The name of the event to stop
 * listening for (i.e. 'click')
 * @param {Function} handler The event handler function
 * @return void
 * @public
 */
 removeEvent: function(el, name, handler){
 Event.stopObserving(el, name, handler);
 },

 /**
 * Animates numerous styles of the given element. The second parameter
 * of this function will be an object of the type that is expected by
 * YAHOO.util.Anim. See http://developer.yahoo.com/yui/docs/YAHOO.util.Anim.html
 * for more information.
 *
 * @param {HTMLElement} el The DOM element to animate
 * @param {Object} obj The animation attributes/parameters
 * @param {Number} duration The duration of the animation
 * (in seconds)
 * @param {Function} callback A callback function to call when
 * the animation completes
 * @return void
 * @public
 */
 animate: function(el, obj, duration, callback){
 var o = {};
 for(var p in obj){
 for(var p in obj){
 o[p] = String(obj[p].to);
 if(p != 'opacity') o[p] += 'px';
 }
 }
 return new Effect.Morph(el, {
 afterFinish: callback,
 duration: duration,
 style: o
 });
 }

};

/**
 * A media-viewer script for web pages that allows content to be viewed without
 * navigating away from the original linking page.
 *
 * This file is part of Shadowbox.
 *
 * Shadowbox is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Shadowbox is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Shadowbox. If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Michael J. I. Jackson <mjijackson@gmail.com>
 * @copyright 2007 Michael J. I. Jackson
 * @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
 * @version SVN: $Id: shadowbox.js 75 2008-02-21 16:51:29Z mjijackson $
 */

if(typeof Shadowbox == 'undefined'){
 throw 'Unable to load Shadowbox, no base library adapter found.';
}

/**
 * The Shadowbox class. Used to display different media on a web page using a
 * Lightbox-like effect.
 *
 * Useful resources:
 * - http://www.alistapart.com/articles/byebyeembed
 * - http://www.w3.org/TR/html401/struct/objects.html
 * - http://www.dyn-web.com/dhtml/iframes/
 * - http://support.microsoft.com/kb/316992
 * - http://www.apple.com/quicktime/player/specs.html
 * - http://www.howtocreate.co.uk/wrongWithIE/?chapter=navigator.plugins
 *
 * @class Shadowbox
 * @author Michael J. I. Jackson <mjijackson@gmail.com>
 * @singleton
 */
(function(){

 /**
 * The current version of Shadowbox.
 *
 * @property {String} version
 * @private
 */
 var version = '1.0';

 /**
 * Contains the default options for Shadowbox. This object is almost
 * entirely customizable.
 *
 * @property {Object} options
 * @private
 */
 var options = {

 /**
 * A base URL that will be prepended to the loadingImage, flvPlayer, and
 * overlayBgImage options to save on typing.
 *
 * @var {String} assetURL
 */
 assetURL: '',

 /**
 * The path to the image to display while loading.
 *
 * @var {String} loadingImage
 
 loadingImage: 'images/loading.gif',
 
 */
 
 loadingImage: SKIN_URL + 'images/sb/loading.gif', 

 /**
 * Enable animations.
 *
 * @var {Boolean} animate
 */
 animate: true,

 /**
 * Specifies the sequence of the height and width animations. May be
 * 'wh' (width then height), 'hw' (height then width), or 'sync' (both
 * at the same time). Of course this will only work if animate is true.
 *
 * @var {String} animSequence
 */
 animSequence: 'wh',

 /**
 * The path to flvplayer.swf.
 *
 * @var {String} flvPlayer
 */
 flvPlayer: 'flvplayer.swf',

 /**
 * The background color and opacity of the overlay. Note: When viewing
 * movie files on FF Mac, the default background image will be used
 * because that browser has problems displaying movies above layers
 * that aren't 100% opaque.
 *
 * @var {String} overlayColor
 */
 overlayColor: '#000',

 /**
 * The background opacity to use for the overlay.
 *
 * @var {Number} overlayOpacity
 */
 overlayOpacity: 0.85,

 /**
 * A background image to use for browsers such as FF Mac that don't
 * support displaying movie content over backgrounds that aren't 100%
 * opaque.
 *
 * @var {String} overlayBgImage
 */
 overlayBgImage: SKIN_URL + 'images/sb/overlay-85.png',

 /**
 * Listen to the overlay for clicks. If the user clicks the overlay,
 * it will trigger Shadowbox.close().
 *
 * @var {Boolean} listenOverlay
 */
 listenOverlay: true,

 /**
 * Automatically play movies.
 *
 * @var {Boolean} autoplayMovies
 */
 autoplayMovies: true,

 /**
 * Enable movie controllers on movie players.
 *
 * @var {Boolean} showMovieControls
 */
 showMovieControls: true,

 /**
 * The duration of the resizing animations (in seconds).
 *
 * @var {Number} resizeDuration
 */
 resizeDuration: 0.35,

 /**
 * The duration of the overlay fade animation (in seconds).
 *
 * @var {Number} fadeDuration
 */
 fadeDuration: 0.35,

 /**
 * Show the navigation controls.
 *
 * @var {Boolean} displayNav
 */
 displayNav: true,

 /**
 * Enable continuous galleries. When this is true, users will be able
 * to skip to the first gallery image from the last using next and vice
 * versa.
 *
 * @var {Boolean} continuous
 */
 continuous: false,

 /**
 * Display the gallery counter.
 *
 * @var {Boolean} displayCounter
 */
 displayCounter: true,

 /**
 * This option may be either 'default' or 'skip'. The default counter is
 * a simple '1 of 5' message. The skip counter displays a link for each
 * piece in the gallery that enables a user to skip directly to any
 * piece.
 *
 * @var {String} counterType
 */
 counterType: 'default',

 /**
 * The amount of padding to maintain around the viewport edge (in
 * pixels). This only applies when the image is very large and takes up
 * the entire viewport.
 *
 * @var {Number} viewportPadding
 */
 viewportPadding: 20,

 /**
 * How to handle images that are too large for the viewport. 'resize'
 * will resize the image while preserving aspect ratio and display it at
 * the smaller resolution. 'drag' will display the image at its native
 * resolution but it will be draggable within the Shadowbox. 'none' will
 * display the image at its native resolution but it may be cropped.
 *
 * @var {String} handleLgImages
 */
 handleLgImages: 'resize',

 /**
 * The initial height of Shadowbox (in pixels).
 *
 * @var {Number} initialHeight
 */
 initialHeight: 160,

 /**
 * The initial width of Shadowbox (in pixels).
 *
 * @var {Number} initialWidth
 */
 initialWidth: 320,

 /**
 * Enable keyboard control. Note: If you disable the keys, you may want
 * to change the visual styles for the navigation elements that suggest
 * keyboard shortcuts.
 *
 * @var {Boolean} enableKeys
 */
 enableKeys: true,

 /**
 * The keys used to control Shadowbox. Note: In order to use these,
 * enableKeys must be true. Key values or key codes may be used.
 *
 * @var {Array}
 */
 keysClose: ['c', 'q', 27], // c, q, or esc
 keysNext: ['n', 39], // n or right arrow
 keysPrev: ['p', 37], // p or left arrow

 /**
 * A hook function to be fired when Shadowbox opens. The single argument
 * will be the current gallery element.
 *
 * @var {Function}
 */
 onOpen: null,

 /**
 * A hook function to be fired when Shadowbox finishes loading its
 * content. The single argument will be the current gallery element on
 * display.
 *
 * @var {Function}
 */
 onFinish: null,

 /**
 * A hook function to be fired when Shadowbox changes from one gallery
 * element to the next. The single argument will be the current gallery
 * element that is about to be displayed.
 *
 * @var {Function}
 */
 onChange: null,

 /**
 * A hook function that will be fired when Shadowbox closes. The single
 * argument will be the gallery element most recently displayed.
 *
 * @var {Function}
 */
 onClose: null,

 /**
 * The mode to use when handling unsupported media. May be either
 * 'remove' or 'link'. If it is 'remove', the unsupported gallery item
 * will merely be removed from the gallery. If it is the only item in
 * the gallery, the link will simply be followed. If it is 'link', a
 * link will be provided to the appropriate plugin page in place of the
 * gallery element.
 *
 * @var {String} handleUnsupported
 */
 handleUnsupported: 'link',

 /**
 * Skips calling Shadowbox.setup() in init(). This means that it must
 * be called later manually.
 *
 * @var {Boolean} skipSetup
 */
 skipSetup: false,

 /**
 * Text messages to use for Shadowbox. These are provided so they may be
 * translated into different languages.
 *
 * @var {Object} text
 */
 text: {

 cancel: 'Cancel',

 loading: 'loading',

 close: '<span class="shortcut">C</span>lose',

 next: '<span class="shortcut">N</span>ext',

 prev: '<span class="shortcut">P</span>revious',

 errors: {
 single: 'You must install the <a href="{0}">{1}</a> browser plugin to view this content.',
 shared: 'You must install both the <a href="{0}">{1}</a> and <a href="{2}">{3}</a> browser plugins to view this content.',
 either: 'You must install either the <a href="{0}">{1}</a> or the <a href="{2}">{3}</a> browser plugin to view this content.'
 }

 },

 /**
 * An object containing names of plugins and links to their respective
 * download pages.
 *
 * @var {Object} errors
 */
 errors: {

 fla: {
 name: 'Flash',
 url: 'http://www.adobe.com/products/flashplayer/'
 },

 qt: {
 name: 'QuickTime',
 url: 'http://www.apple.com/quicktime/download/'
 },

 wmp: {
 name: 'Windows Media Player',
 url: 'http://www.microsoft.com/windows/windowsmedia/'
 },

 f4m: {
 name: 'Flip4Mac',
 url: 'http://www.flip4mac.com/wmv_download.htm'
 }

 },

 /**
 * The HTML markup to use for Shadowbox. Note: The script depends on
 * most of these elements being present, so don't modify this variable
 * unless you know what you're doing.
 *
 * @var {Object} skin
 */
 skin: {

 main: '<div id="shadowbox_overlay"></div>' +
 '<div id="shadowbox_container">' +
 '<div id="shadowbox">' +
 '<div id="shadowbox_title">' +
 '<div id="shadowbox_title_inner"></div>' +
 '</div>' +
 '<div id="shadowbox_body">' +
 '<div id="shadowbox_body_inner"></div>' +
 '<div id="shadowbox_loading"></div>' +
 '</div>' +
 '<div id="shadowbox_toolbar">' +
 '<div id="shadowbox_toolbar_inner"></div>' +
 '</div>' +
 '</div>' +
 '</div>',

 loading: '<img src="{0}" alt="{1}" />' +
 '<span><a href="javascript:Shadowbox.close();">{2}</a></span>',

 counter: '<div id="shadowbox_counter">{0}</div>',

 close: '<div id="shadowbox_nav_close">' +
 '<a href="javascript:Shadowbox.close();">{0}</a>' +
 '</div>',

 next: '<div id="shadowbox_nav_next">' +
 '<a href="javascript:Shadowbox.next();">{0}</a>' +
 '</div>',

 prev: '<div id="shadowbox_nav_previous">' +
 '<a href="javascript:Shadowbox.previous();">{0}</a>' +
 '</div>'

 },

 /**
 * An object containing arrays of all supported file extensions. Each
 * property of this object contains an array. If this object is to be
 * modified, it must be done before calling init().
 *
 * - img: Supported image file extensions
 * - qt: Movie file extensions supported by QuickTime
 * - wmp: Movie file extensions supported by Windows Media Player
 * - qtwmp: Movie file extensions supported by both QuickTime and Windows Media Player
 * - iframe: File extensions that will be display in an iframe
 *
 * @var {Object} ext
 */
 ext: {
 img: ['png', 'jpg', 'jpeg', 'gif', 'bmp'],
 qt: ['dv', 'mov', 'moov', 'movie', 'mp4'],
 wmp: ['asf', 'wm', 'wmv'],
 qtwmp: ['avi', 'mpg', 'mpeg'],
 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'pl', 'php',
 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml',
 'txt', 'vbs']
 }

 };

 /**
 * Stores the default set of options in case a custom set of options is used
 * on a link-by-link basis so we can restore them later.
 *
 * @property {Object} default_options
 * @private
 */
 var default_options = null;

 /**
 * Shorthand for Shadowbox.lib.
 *
 * @property {Object} SL
 * @private
 */
 var SL = Shadowbox.lib;

 /**
 * An object containing some regular expressions we'll need later. Compiled
 * up front for speed.
 *
 * @property {Object} RE
 * @private
 */
 var RE = {
 resize: /(img|swf|flv)/, // file types to resize
 overlay: /(img|iframe|html|inline)/, // content types to not use an overlay image for on FF Mac
 swf: /\.swf\s*$/i, // swf file extension
 flv: /\.flv\s*$/i, // flv file extension
 domain: /:\/\/(.*?)[:\/]/, // domain prefix
 inline: /#(.+)$/, // inline element id
 rel: /^(light|shadow)box/i, // rel attribute format
 gallery: /^(light|shadow)box\[(.*?)\]/i, // rel attribute format for gallery link
 unsupported: /^unsupported-(\w+)/, // unsupported media type
 param: /\s*([a-z_]*?)\s*=\s*(.+)\s*/, // rel string parameter
 empty: /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i // elements that don't have children
 };

 /**
 * A cache of options for links that have been set up for use with
 * Shadowbox.
 *
 * @property {Array} cache
 * @private
 */
 var cache = [];

 /**
 * An array of pieces currently being viewed. In the case of non-gallery
 * pieces, this will only hold one object.
 *
 * @property {Array} current_gallery
 * @private
 */
 var current_gallery;

 /**
 * The array index of the current_gallery that is currently being viewed.
 *
 * @property {Number} current
 * @private
 */
 var current;

 /**
 * Keeps track of the current optimal height of the box. We use this so that
 * if the user resizes the browser window to get a better view, and we're
 * currently at a size smaller than the optimal, we can resize easily.
 *
 * @see resizeContent()
 * @property {Number} optimal_height
 * @private
 */
 var optimal_height = options.initialHeight;

 /**
 * Keeps track of the current optimal width of the box. See optimal_height
 * explanation (above).
 *
 * @property {Number} optimal_width
 * @private
 */
 var optimal_width = options.initialWidth;

 /**
 * Keeps track of the current height of the box. This is useful in drag
 * calculations.
 *
 * @property {Number} current_height
 * @private
 */
 var current_height = 0;

 /**
 * Keeps track of the current width of the box. Useful in drag calculations.
 *
 * @property {Number} current_width
 * @private
 */
 var current_width = 0;

 /**
 * Resource used to preload images. It's class-level so that when a new
 * image is requested, the same resource can be reassigned, cancelling
 * the original's callback.
 *
 * @property {HTMLElement} preloader
 * @private
 */
 var preloader;

 /**
 * Keeps track of whether or not Shadowbox has been initialized. We never
 * want to initialize twice.
 *
 * @property {Boolean} initialized
 * @private
 */
 var initialized = false;

 /**
 * Keeps track of whether or not Shadowbox is activated.
 *
 * @property {Boolean} activated
 * @private
 */
 var activated = false;

 /**
 * Keeps track of 4 floating values (x, y, start_x, & start_y) that are used
 * in the drag calculations.
 *
 * @property {Object} drag
 * @private
 */
 var drag;

 /**
 * Holds the draggable element so we don't have to fetch it every time
 * the mouse moves.
 *
 * @property {HTMLElement} draggable
 * @private
 */
 var draggable;

 /**
 * Keeps track of whether or not we're currently using the overlay
 * background image to display the current gallery. We do this because we
 * use different methods for fading the overlay in and out. The color fill
 * overlay fades in and out nicely, but the image overlay stutters. By
 * keeping track of the type of overlay in use, we don't have to check again
 * what type of overlay we're using when it's time to get rid of it later.
 *
 * @property {Boolean} overlay_img_needed
 * @private
 */
 var overlay_img_needed;

 /**
 * These parameters for simple browser detection. Used in Ext.js.
 *
 * @ignore
 */
 var ua = navigator.userAgent.toLowerCase();
 var isStrict = document.compatMode == 'CSS1Compat',
 isOpera = ua.indexOf("opera") > -1,
 isIE = ua.indexOf('msie') > -1,
 isIE7 = ua.indexOf('msie 7') > -1,
 isBorderBox = isIE && !isStrict,
 isSafari = (/webkit|khtml/).test(ua),
 isSafari3 = isSafari && !!(document.evaluate),
 isGecko = !isSafari && ua.indexOf('gecko') > -1,
 isWindows = (ua.indexOf('windows') != -1 || ua.indexOf('win32') != -1),
 isMac = (ua.indexOf('macintosh') != -1 || ua.indexOf('mac os x') != -1),
 isLinux = (ua.indexOf('linux') != -1);

 /**
 * Do we need to hack the position to make Shadowbox appear fixed? We could
 * hack this using CSS, but let's just get over all the hacks and let IE6
 * users get what they deserve! Down with hacks! Hmm...now that I think
 * about it, I should just flash all kinds of alerts and annoying popups on
 * their screens, and then redirect them to some foreign spyware site that
 * will upload a nasty virus...
 *
 * @property {Boolean} absolute_pos
 * @private
 */
 var absolute_pos = isIE && !isIE7;

 /**
 * Contains plugin support information. Each property of this object is a
 * boolean indicating whether that plugin is supported.
 *
 * - fla: Flash player
 * - qt: QuickTime player
 * - wmp: Windows Media player
 * - f4m: Flip4Mac plugin
 *
 * @property {Object} plugins
 * @private
 */
 var plugins = null;

 // detect plugin support
 if(navigator.plugins && navigator.plugins.length){
 var detectPlugin = function(plugin_name){
 var detected = false;
 for (var i = 0, len = navigator.plugins.length; i < len; ++i){
 if(navigator.plugins[i].name.indexOf(plugin_name) > -1){
 detected = true;
 break;
 }
 }
 return detected;
 };
 var f4m = detectPlugin('Flip4Mac');
 var plugins = {
 fla: detectPlugin('Shockwave Flash'),
 qt: detectPlugin('QuickTime'),
 wmp: !f4m && detectPlugin('Windows Media'), // if it's Flip4Mac, it's not really WMP
 f4m: f4m
 };
 }else{
 var detectPlugin = function(plugin_name){
 var detected = false;
 try {
 var axo = new ActiveXObject(plugin_name);
 if(axo){
 detected = true;
 }
 } catch (e) {}
 return detected;
 };
 var plugins = {
 fla: detectPlugin('ShockwaveFlash.ShockwaveFlash'),
 qt: detectPlugin('QuickTime.QuickTime'),
 wmp: detectPlugin('wmplayer.ocx'),
 f4m: false
 };
 }

 /**
 * Applies all properties of e to o. This function is recursive so that if
 * any properties of e are themselves objects, those objects will be applied
 * to objects with the same key that may exist in o.
 *
 * @param {Object} o The original object
 * @param {Object} e The extension object
 * @return {Object} The original object with all properties
 * of the extension object applied (deep)
 * @private
 */
 var apply = function(o, e){
 for(var p in e) o[p] = e[p];
 return o;
 };

 /**
 * Determines if the given object is an anchor/area element.
 *
 * @param {mixed} el The object to check
 * @return {Boolean} True if the object is a link element
 * @private
 */
 var isLink = function(el){
 return typeof el.tagName == 'string' && (el.tagName.toUpperCase() == 'A' || el.tagName.toUpperCase() == 'AREA');
 };

 /**
 * Gets the height of the viewport in pixels. Note: This function includes
 * scrollbars in Safari 3.
 *
 * @return {Number} The height of the viewport
 * @public
 * @static
 */
 SL.getViewportHeight = function(){
 var height = window.innerHeight; // Safari
 var mode = document.compatMode;
 if((mode || isIE) && !isOpera){
 height = isStrict ? document.documentElement.clientHeight : document.body.clientHeight;
 }
 return height;
 };

 /**
 * Gets the width of the viewport in pixels. Note: This function includes
 * scrollbars in Safari 3.
 *
 * @return {Number} The width of the viewport
 * @public
 * @static
 */
 SL.getViewportWidth = function(){
 var width = window.innerWidth; // Safari
 var mode = document.compatMode;
 if(mode || isIE){
 width = isStrict ? document.documentElement.clientWidth : document.body.clientWidth;
 }
 return width;
 };

 /**
 * Gets the height of the document (body and its margins) in pixels.
 *
 * @return {Number} The height of the document
 * @public
 * @static
 */
 SL.getDocumentHeight = function(){
 var scrollHeight = isStrict ? document.documentElement.scrollHeight : document.body.scrollHeight;
 return Math.max(scrollHeight, SL.getViewportHeight());
 };

 /**
 * Gets the width of the document (body and its margins) in pixels.
 *
 * @return {Number} The width of the document
 * @public
 * @static
 */
 SL.getDocumentWidth = function(){
 var scrollWidth = isStrict ? document.documentElement.scrollWidth : document.body.scrollWidth;
 return Math.max(scrollWidth, SL.getViewportWidth());
 };

 /**
 * A utility function used by the fade functions to clear the opacity
 * style setting of the given element. Required in some cases for IE.
 * Based on Ext.Element's clearOpacity.
 *
 * @param {HTMLElement} el The DOM element
 * @return void
 * @private
 */
 var clearOpacity = function(el){
 if(isIE){
 if(typeof el.style.filter == 'string' && (/alpha/i).test(el.style.filter)){
 el.style.filter = '';
 }
 }else{
 el.style.opacity = '';
 el.style['-moz-opacity'] = '';
 el.style['-khtml-opacity'] = '';
 }
 };

 /**
 * Fades the given element from 0 to the specified opacity.
 *
 * @param {HTMLElement} el The DOM element to fade
 * @param {Number} endingOpacity The final opacity to animate to
 * @param {Number} duration The duration of the animation
 * (in seconds)
 * @param {Function} callback A callback function to call
 * when the animation completes
 * @return void
 * @private
 */
 var fadeIn = function(el, endingOpacity, duration, callback){
 if(options.animate){
 SL.setStyle(el, 'opacity', 0);
 el.style.visibility = 'visible';
 SL.animate(el, {
 opacity: { to: endingOpacity }
 }, duration, function(){
 if(endingOpacity == 1) clearOpacity(el);
 if(typeof callback == 'function') callback();
 });
 }else{
 if(endingOpacity == 1){
 clearOpacity(el);
 }else{
 SL.setStyle(el, 'opacity', endingOpacity);
 }
 el.style.visibility = 'visible';
 if(typeof callback == 'function') callback();
 }
 };

 /**
 * Fades the given element from its current opacity to 0.
 *
 * @param {HTMLElement} el The DOM element to fade
 * @param {Number} duration The duration of the fade animation
 * @param {Function} callback A callback function to call when
 * the animation completes
 * @return void
 * @private
 */
 var fadeOut = function(el, duration, callback){
 var cb = function(){
 el.style.visibility = 'hidden';
 clearOpacity(el);
 if(typeof callback == 'function') callback();
 };
 if(options.animate){
 SL.animate(el, {
 opacity: { to: 0 }
 }, duration, cb);
 }else{
 cb();
 }
 };

 /**
 * Appends an HTML fragment to the given element.
 *
 * @param {String/HTMLElement} el The element to append to
 * @param {String} html The HTML fragment to use
 * @return {HTMLElement} The newly appended element
 * @private
 */
 var appendHTML = function(el, html){
 el = SL.get(el);
 if(el.insertAdjacentHTML){
 el.insertAdjacentHTML('BeforeEnd', html);
 return el.lastChild;
 }
 if(el.lastChild){
 var range = el.ownerDocument.createRange();
 range.setStartAfter(el.lastChild);
 var frag = range.createContextualFragment(html);
 el.appendChild(frag);
 return el.lastChild;
 }else{
 el.innerHTML = html;
 return el.lastChild;
 }
 };

 /**
 * Overwrites the HTML of the given element.
 *
 * @param {String/HTMLElement} el The element to overwrite
 * @param {String} html The new HTML to use
 * @return {HTMLElement} The new firstChild element
 * @private
 */
 var overwriteHTML = function(el, html){
 el = SL.get(el);
 el.innerHTML = html;
 return el.firstChild;
 };

 /**
 * Gets either the offsetHeight or the height of the given element plus
 * padding and borders (when offsetHeight is not available). Based on
 * Ext.Element's getComputedHeight.
 *
 * @return {Number} The computed height of the element
 * @private
 */
 var getComputedHeight = function(el){
 var h = Math.max(el.offsetHeight, el.clientHeight);
 if(!h){
 h = parseInt(SL.getStyle(el, 'height'), 10) || 0;
 if(!isBorderBox){
 h += parseInt(SL.getStyle(el, 'padding-top'), 10)
 + parseInt(SL.getStyle(el, 'padding-bottom'), 10)
 + parseInt(SL.getStyle(el, 'border-top-width'), 10)
 + parseInt(SL.getStyle(el, 'border-bottom-width'), 10);
 }
 }
 return h;
 };

 /**
 * Gets either the offsetWidth or the width of the given element plus
 * padding and borders (when offsetWidth is not available). Based on
 * Ext.Element's getComputedWidth.
 *
 * @return {Number} The computed width of the element
 * @private
 */
 var getComputedWidth = function(el){
 var w = Math.max(el.offsetWidth, el.clientWidth);
 if(!w){
 w = parseInt(SL.getStyle(el, 'width'), 10) || 0;
 if(!isBorderBox){
 w += parseInt(SL.getStyle(el, 'padding-left'), 10)
 + parseInt(SL.getStyle(el, 'padding-right'), 10)
 + parseInt(SL.getStyle(el, 'border-left-width'), 10)
 + parseInt(SL.getStyle(el, 'border-right-width'), 10);
 }
 }
 return w;
 };

 /**
 * Determines the player needed to display the file at the given URL. If
 * the file type is not supported, the return value will be 'unsupported'.
 * If the file type is not supported but the correct player can be
 * determined, the return value will be 'unsupported-*' where * will be the
 * player abbreviation (e.g. 'qt' = QuickTime).
 *
 * @param {String} url The url of the file
 * @return {String} The name of the player to use
 * @private
 */
 var getPlayerType = function(url){
 if(RE.img.test(url)) return 'img';
 var match = url.match(RE.domain);
 var this_domain = match ? document.domain == match[1] : false;
 if(url.indexOf('#') > -1 && this_domain) return 'inline';
 var q_index = url.indexOf('?');
 if(q_index > -1) url = url.substring(0, q_index); // strip query string for player detection purposes
 if(RE.swf.test(url)) return plugins.fla ? 'swf' : 'unsupported-swf';
 if(RE.flv.test(url)) return plugins.fla ? 'flv' : 'unsupported-flv';
 if(RE.qt.test(url)) return plugins.qt ? 'qt' : 'unsupported-qt';
 if(RE.wmp.test(url)){
 if(plugins.wmp){
 return 'wmp';
 }else if(plugins.f4m){
 return 'qt';
 }else{
 return isMac ? (plugins.qt ? 'unsupported-f4m' : 'unsupported-qtf4m') : 'unsupported-wmp';
 }
 }else if(RE.qtwmp.test(url)){
 if(plugins.qt){
 return 'qt';
 }else if(plugins.wmp){
 return 'wmp';
 }else{
 return isMac ? 'unsupported-qt' : 'unsupported-qtwmp';
 }
 }else if(!this_domain || RE.iframe.test(url)){
 return 'iframe';
 }
 return 'unsupported';
 };

 /**
 * Handles all clicks on links that have been set up to work with Shadowbox
 * and cancels the default event behavior when appropriate.
 *
 * @param {Event} ev The click event object
 * @return void
 * @private
 */
 var handleClick = function(ev){
 // get anchor/area element
 var link;
 if(isLink(this)){
 link = this; // jQuery, Prototype, YUI
 }else{
 link = SL.getTarget(ev); // Ext
 while(!isLink(link) && link.parentNode){
 link = link.parentNode;
 }
 }

 Shadowbox.open(link);
 if(current_gallery.length) SL.preventDefault(ev);
 };

 /**
 * Sets up the current gallery for the given object. Modifies the current
 * and current_gallery variables to contain the appropriate information.
 * Also, checks to see if there are any gallery pieces that are not
 * supported by the client's browser/plugins. If there are, they will be
 * handled according to the handleUnsupported option.
 *
 * @param {Object} obj The content to get the gallery for
 * @return void
 * @private
 */
 var setupGallery = function(obj){
 // create a copy so it doesn't get modified later
 var copy = apply({}, obj);

 // is it part of a gallery?
 if(!obj.gallery){ // single item, no gallery
 current_gallery = [copy];
 current = 0;
 }else{
 current_gallery = []; // clear the current gallery
 var index, ci;
 for(var i = 0, len = cache.length; i < len; ++i){
 ci = cache[i];
 if(ci.gallery){
 if(ci.content == obj.content
 && ci.gallery == obj.gallery
 && ci.title == obj.title){ // compare content, gallery, & title
 index = current_gallery.length; // key element found
 }
 if(ci.gallery == obj.gallery){
 current_gallery.push(apply({}, ci));
 }
 }
 }
 // if not found in cache, prepend to front of gallery
 if(index == null){
 current_gallery.unshift(copy);
 index = 0;
 }
 current = index;
 }

 // are any media in the current gallery supported?
 var match, r;
 for(var i = 0, len = current_gallery.length; i < len; ++i){
 r = false;
 if(current_gallery[i].type == 'unsupported'){ // don't support this at all
 r = true;
 }else if(match = RE.unsupported.exec(current_gallery[i].type)){ // handle unsupported elements
 if(options.handleUnsupported == 'link'){
 current_gallery[i].type = 'html';
 // generate a link to the appropriate plugin download page(s)
 var m;
 switch(match[1]){
 case 'qtwmp':
 m = String.format(options.text.errors.either,
 options.errors.qt.url, options.errors.qt.name,
 options.errors.wmp.url, options.errors.wmp.name);
 break;
 case 'qtf4m':
 m = String.format(options.text.errors.shared,
 options.errors.qt.url, options.errors.qt.name,
 options.errors.f4m.url, options.errors.f4m.name);
 break;
 default:
 if(match[1] == 'swf' || match[1] == 'flv') match[1] = 'fla';
 m = String.format(options.text.errors.single,
 options.errors[match[1]].url, options.errors[match[1]].name);
 }
 current_gallery[i] = apply(current_gallery[i], {
 height: 160, // error messages are short so they
 width: 320, // only need a small box to display properly
 content: '<div class="shadowbox_message">' + m + '</div>'
 });
 }else{
 r = true;
 }
 }else if(current_gallery[i].type == 'inline'){ // handle inline elements
 // retrieve the innerHTML of the inline element
 var match = RE.inline.exec(current_gallery[i].content);
 if(match){
 var el;
 if(el = SL.get(match[1])){
 current_gallery[i].content = el.innerHTML;
 }else{
 throw 'No element found with id ' + match[1];
 }
 }else{
 throw 'No element id found for inline content';
 }
 }
 if(r){
 // remove the element from the gallery
 current_gallery.splice(i, 1);
 if(i < current) --current;
 --i;
 }
 }
 };

 /**
 * Hides the title bar and toolbar and populates them with the proper
 * content.
 *
 * @return void
 * @private
 */
 var buildBars = function(){
 var link = current_gallery[current];
 if(!link) return; // nothing to build

 // build the title
 var title_i = SL.get('shadowbox_title_inner');
 title_i.innerHTML = (link.title) ? link.title : '';
 // empty the toolbar
 var tool_i = SL.get('shadowbox_toolbar_inner');
 tool_i.innerHTML = '';

 // build the nav
 if(options.displayNav){
 tool_i.innerHTML = String.format(options.skin.close, options.text.close);
 if(current_gallery.length > 1){
 if(options.continuous){
 // show both
 appendHTML(tool_i, String.format(options.skin.next, options.text.next));
 appendHTML(tool_i, String.format(options.skin.prev, options.text.prev));
 }else{
 // not last in the gallery, show the next link
 if((current_gallery.length - 1) > current){
 appendHTML(tool_i, String.format(options.skin.next, options.text.next));
 }
 // not first in the gallery, show the previous link
 if(current > 0){
 appendHTML(tool_i, String.format(options.skin.prev, options.text.prev));
 }
 }
 }
 }

 // build the counter
 if(current_gallery.length > 1 && options.displayCounter){
 // append the counter div
 var counter = '';
 if(options.counterType == 'skip'){
 for(var i = 0, len = current_gallery.length; i < len; ++i){
 counter += '<a href="javascript:Shadowbox.change(' + i + ');"';
 if(i == current){
 counter += ' class="shadowbox_counter_current"';
 }
 counter += '>' + (i + 1) + '</a>';
 }
 }else{
 counter = (current + 1) + ' of ' + current_gallery.length;
 }
 appendHTML(tool_i, String.format(options.skin.counter, counter));
 }
 };

 /**
 * Hides the title and tool bars.
 *
 * @param {Function} callback A function to call on finish
 * @return void
 * @private
 */
 var hideBars = function(callback){
 var title_m = getComputedHeight(SL.get('shadowbox_title'));
 var tool_m = 0 - getComputedHeight(SL.get('shadowbox_toolbar'));
 var title_i = SL.get('shadowbox_title_inner');
 var tool_i = SL.get('shadowbox_toolbar_inner');

 if(options.animate && callback){
 // animate the transition
 SL.animate(title_i, {
 marginTop: { to: title_m }
 }, 0.2);
 SL.animate(tool_i, {
 marginTop: { to: tool_m }
 }, 0.2, callback);
 }else{
 SL.setStyle(title_i, 'marginTop', title_m + 'px');
 SL.setStyle(tool_i, 'marginTop', tool_m + 'px');
 }
 };

 /**
 * Shows the title and tool bars.
 *
 * @param {Function} callback A callback function to execute after
 * the animation completes
 * @return void
 * @private
 */
 var showBars = function(callback){
 var title_i = SL.get('shadowbox_title_inner');
 if(options.animate){
 if(title_i.innerHTML != ''){
 SL.animate(title_i, { marginTop: { to: 0 } }, 0.35);
 }
 SL.animate(SL.get('shadowbox_toolbar_inner'), {
 marginTop: { to: 0 }
 }, 0.35, callback);
 }else{
 if(title_i.innerHTML != ''){
 SL.setStyle(title_i, 'margin-top', '0px');
 }
 SL.setStyle(SL.get('shadowbox_toolbar_inner'), 'margin-top', '0px');
 callback();
 }
 };

 /**
 * Resets the class drag variable.
 *
 * @return void
 * @private
 */
 var resetDrag = function(){
 drag = {
 x: 0,
 y: 0,
 start_x: null,
 start_y: null
 };
 };

 /**
 * Toggles the drag function on and off.
 *
 * @param {Boolean} on True to toggle on, false to toggle off
 * @return void
 * @private
 */
 var toggleDrag = function(on){
 if(on){
 resetDrag();
 // add drag layer to prevent browser dragging of actual image
 var styles = [
 'position:absolute',
 'cursor:' + (isGecko ? '-moz-grab' : 'move')
 ];
 // make drag layer transparent
 styles.push(isIE ? 'background-color:#fff;filter:alpha(opacity=0)' : 'background-color:transparent');
 appendHTML('shadowbox_body_inner', '<div id="shadowbox_drag_layer" style="' + styles.join(';') + '"></div>');
 SL.addEvent(SL.get('shadowbox_drag_layer'), 'mousedown', listenDrag);
 }else{
 var d = SL.get('shadowbox_drag_layer');
 if(d){
 SL.removeEvent(d, 'mousedown', listenDrag);
 SL.remove(d);
 }
 }
 };

 /**
 * Sets up a drag listener on the document. Called when the mouse button is
 * pressed (mousedown).
 *
 * @param {mixed} ev The mousedown event
 * @return void
 * @private
 */
 var listenDrag = function(ev){
 drag.start_x = ev.clientX;
 drag.start_y = ev.clientY;
 draggable = SL.get('shadowbox_content');
 SL.addEvent(document, 'mousemove', positionDrag);
 SL.addEvent(document, 'mouseup', unlistenDrag);
 if(isGecko) SL.setStyle(SL.get('shadowbox_drag_layer'), 'cursor', '-moz-grabbing');
 };

 /**
 * Removes the drag listener. Called when the mouse button is released
 * (mouseup).
 *
 * @return void
 * @private
 */
 var unlistenDrag = function(){
 SL.removeEvent(document, 'mousemove', positionDrag);
 SL.removeEvent(document, 'mouseup', unlistenDrag); // clean up
 if(isGecko) SL.setStyle(SL.get('shadowbox_drag_layer'), 'cursor', '-moz-grab');
 };

 /**
 * Positions an oversized image on drag.
 *
 * @param {mixed} ev The drag event
 * @return void
 * @private
 */
 var positionDrag = function(ev){
 var move_y = ev.clientY - drag.start_y;
 drag.start_y = drag.start_y + move_y;
 drag.y = Math.max(Math.min(0, drag.y + move_y), current_height - optimal_height); // y boundaries
 SL.setStyle(draggable, 'top', drag.y + 'px');
 var move_x = ev.clientX - drag.start_x;
 drag.start_x = drag.start_x + move_x;
 drag.x = Math.max(Math.min(0, drag.x + move_x), current_width - optimal_width); // x boundaries
 SL.setStyle(draggable, 'left', drag.x + 'px');
 };

 /**
 * Loads the Shadowbox with the current piece.
 *
 * @return void
 * @private
 */
 var loadContent = function(){
 var obj = current_gallery[current];
 if(!obj) return; // invalid

 buildBars();

 switch(obj.type){
 case 'img':
 // preload the image
 preloader = new Image();
 preloader.onload = function(){
 // images default to image height and width
 var h = obj.height ? parseInt(obj.height, 10) : preloader.height;
 var w = obj.width ? parseInt(obj.width, 10) : preloader.width;
 resizeContent(h, w, function(dims){
 showBars(function(){
 setContent({
 tag: 'img',
 height: dims.i_height,
 width: dims.i_width,
 src: obj.content,
 style: 'position:absolute'
 });
 if(dims.enableDrag && options.handleLgImages == 'drag'){
 // listen for drag
 toggleDrag(true);
 SL.setStyle(SL.get('shadowbox_drag_layer'), {
 height: dims.i_height + 'px',
 width: dims.i_width + 'px'
 });
 }
 finishContent();
 });
 });

 preloader.onload = function(){}; // clear onload for IE
 };
 preloader.src = obj.content;
 break;

 case 'swf':
 case 'flv':
 case 'qt':
 case 'wmp':
 var markup = Shadowbox.movieMarkup(obj);
 resizeContent(markup.height, markup.width, function(){
 showBars(function(){
 setContent(markup);
 finishContent();
 });
 });
 break;

 case 'iframe':
 // iframes default to full viewport height and width
 var h = obj.height ? parseInt(obj.height, 10) : SL.getViewportHeight();
 var w = obj.width ? parseInt(obj.width, 10) : SL.getViewportWidth();
 var content = {
 tag: 'iframe',
 name: 'shadowbox_content',
 height: '100%',
 width: '100%',
 frameborder: '0',
 marginwidth: '0',
 marginheight: '0',
 scrolling: 'auto'
 };

 resizeContent(h, w, function(dims){
 showBars(function(){
 setContent(content);
 var win = (isIE)
 ? SL.get('shadowbox_content').contentWindow
 : window.frames['shadowbox_content'];
 win.location = obj.content;
 finishContent();
 });
 });
 break;

 case 'html':
 case 'inline':
 // HTML content defaults to full viewport height and width
 var h = obj.height ? parseInt(obj.height, 10) : SL.getViewportHeight();
 var w = obj.width ? parseInt(obj.width, 10) : SL.getViewportWidth();
 var content = {
 tag: 'div',
 cls: 'html', /* give special class to make scrollable */
 html: obj.content
 };
 resizeContent(h, w, function(){
 showBars(function(){
 setContent(content);
 finishContent();
 });
 });
 break;

 default:
 // should never happen
 throw 'Shadowbox cannot open content of type ' + obj.type;
 }

 // preload neighboring images
 if(current_gallery.length > 0){
 var next = current_gallery[current + 1];
 if(!next){
 next = current_gallery[0];
 }
 if(next.type == 'img'){
 var preload_next = new Image();
 preload_next.src = next.href;
 }

 var prev = current_gallery[current - 1];
 if(!prev){
 prev = current_gallery[current_gallery.length - 1];
 }
 if(prev.type == 'img'){
 var preload_prev = new Image();
 preload_prev.src = prev.href;
 }
 }
 };

 /**
 * Removes old content and sets the new content of the Shadowbox.
 *
 * @param {Object} obj The content to set (appropriate to pass
 * directly to Shadowbox.createHTML())
 * @return {HTMLElement} The newly appended element (or null if
 * none is provided)
 * @private
 */
 var setContent = function(obj){
 var id = 'shadowbox_content';
 var content = SL.get(id);
 if(content){
 // remove old content first
 switch(content.tagName.toUpperCase()){
 case 'OBJECT':
 // if we're in a gallery (i.e. changing and there's a new
 // object) we want the LAST link object
 var link = current_gallery[(obj ? current - 1 : current)];
 if(link.type == 'wmp' && isIE){
 try{
 shadowbox_content.controls.stop(); // stop the movie
 shadowbox_content.URL = 'non-existent.wmv'; // force player refresh
 window.shadowbox_content = function(){}; // remove from window
 }catch(e){}
 }else if(link.type == 'qt' && isSafari){
 try{
 document.shadowbox_content.Stop(); // stop QT movie
 }catch(e){}
 // stop QT audio stream for movies that have not yet loaded
 content.innerHTML = '';
 // console.log(document.shadowbox_content);
 }
 setTimeout(function(){ // using setTimeout prevents browser crashes with WMP
 SL.remove(content);
 }, 10);
 break;
 case 'IFRAME':
 SL.remove(content);
 if(isGecko) delete window.frames[id]; // needed for Firefox
 break;
 default:
 SL.remove(content);
 }
 }
 if(obj){
 if(!obj.id) obj.id = id;
 return appendHTML('shadowbox_body_inner', Shadowbox.createHTML(obj));
 }
 return null;
 };

 /**
 * This function is used as the callback after the Shadowbox has been
 * positioned, resized, and loaded with content.
 *
 * @return void
 * @private
 */
 var finishContent = function(){
 var obj = current_gallery[current];
 if(!obj) return; // invalid
 hideLoading(function(){
 listenKeyboard(true);
 // fire onFinish handler
 if(options.onFinish && typeof options.onFinish == 'function'){
 options.onFinish(obj);
 }
 });
 };

 /**
 * Resizes and positions the content box using the given height and width.
 * If the callback parameter is missing, the transition will not be
 * animated. If the callback parameter is present, it will be passed the
 * new calculated dimensions object as its first parameter. Note: the height
 * and width here should represent the optimal height and width of the box.
 *
 * @param {Function} callback A callback function to use when the
 * resize completes
 * @return void
 * @private
 */
 var resizeContent = function(height, width, callback){
 // update optimal height and width
 optimal_height = height;
 optimal_width = width;
 var resizable = RE.resize.test(current_gallery[current].type);
 var dims = getDimensions(optimal_height, optimal_width, resizable);
 if(callback){
 var cb = function(){ callback(dims); };
 switch(options.animSequence){
 case 'hw':
 adjustHeight(dims.height, dims.top, true, function(){
 adjustWidth(dims.width, true, cb);
 });
 break;
 case 'wh':
 adjustWidth(dims.width, true, function(){
 adjustHeight(dims.height, dims.top, true, cb);
 });
 break;
 default: // sync
 adjustWidth(dims.width, true);
 adjustHeight(dims.height, dims.top, true, cb);
 }
 }else{ // window resize
 adjustWidth(dims.width, false);
 adjustHeight(dims.height, dims.top, false);
 // resize content images & flash in 'resize' mode
 if(options.handleLgImages == 'resize' && resizable){
 var content = SL.get('shadowbox_content');
 if(content){ // may be animating, not present
 content.height = dims.i_height;
 content.width = dims.i_width;
 }
 }
 }
 };

 /**
 * Calculates the dimensions for Shadowbox, taking into account the borders,
 * margins, and surrounding elements of the shadowbox_body. If the image
 * is still to large for Shadowbox, and options.handleLgImages is 'resize',
 * the resized dimensions will be returned (preserving the original aspect
 * ratio). Otherwise, the originally calculated dimensions will be returned.
 * The returned object will have the following properties:
 *
 * - height: The height to use for shadowbox_body_inner
 * - width: The width to use for shadowbox
 * - i_height: The height to use for resizable content
 * - i_width: The width to use for resizable content
 * - top: The top to use for shadowbox
 * - enableDrag: True if dragging should be enabled (image is oversized)
 *
 * @param {Number} o_height The optimal height
 * @param {Number} o_width The optimal width
 * @param {Boolean} resizable True if the content is able to be
 * resized. Defaults to false.
 * @return {Object} The resize dimensions (see above)
 * @private
 */
 var getDimensions = function(o_height, o_width, resizable){
 if(typeof resizable == 'undefined') resizable = false;

 var height = o_height = parseInt(o_height);
 var width = o_width = parseInt(o_width);
 var shadowbox_b = SL.get('shadowbox_body');

 // calculate the max height
 var view_height = SL.getViewportHeight();
 var extra_height = parseInt(SL.getStyle(shadowbox_b, 'border-top-width'), 10)
 + parseInt(SL.getStyle(shadowbox_b, 'border-bottom-width'), 10)
 + parseInt(SL.getStyle(shadowbox_b, 'margin-top'), 10)
 + parseInt(SL.getStyle(shadowbox_b, 'margin-bottom'), 10)
 + getComputedHeight(SL.get('shadowbox_title'))
 + getComputedHeight(SL.get('shadowbox_toolbar'))
 + (2 * options.viewportPadding);
 if((height + extra_height) >= view_height){
 height = view_height - extra_height;
 }

 // calculate the max width
 var view_width = SL.getViewportWidth();
 var extra_body_width = parseInt(SL.getStyle(shadowbox_b, 'border-left-width'), 10)
 + parseInt(SL.getStyle(shadowbox_b, 'border-right-width'), 10)
 + parseInt(SL.getStyle(shadowbox_b, 'margin-left'), 10)
 + parseInt(SL.getStyle(shadowbox_b, 'margin-right'), 10);
 var extra_width = extra_body_width + (2 * options.viewportPadding);
 if((width + extra_width) >= view_width){
 width = view_width - extra_width;
 }

 // handle oversized images & flash
 var enableDrag = false;
 var i_height = o_height;
 var i_width = o_width;
 var handle = options.handleLgImages;
 if(resizable && (handle == 'resize' || handle == 'drag')){
 var change_h = (o_height - height) / o_height;
 var change_w = (o_width - width) / o_width;
 if(handle == 'resize'){
 if(change_h > change_w){
 width = Math.round((o_width / o_height) * height);
 }else if(change_w > change_h){
 height = Math.round((o_height / o_width) * width);
 }
 // adjust image height or width accordingly
 i_width = width;
 i_height = height;
 }else{
 // drag on oversized images only
 var link = current_gallery[current];
 if(link) enableDrag = link.type == 'img' && (change_h > 0 || change_w > 0);
 }
 }

 return {
 height: height,
 width: width + extra_body_width,
 i_height: i_height,
 i_width: i_width,
 top: ((view_height - (height + extra_height)) / 2) + options.viewportPadding,
 enableDrag: enableDrag
 };
 };

 /**
 * Centers Shadowbox vertically in the viewport. Needs to be called on
 * scroll in IE6 because it does not support fixed positioning.
 *
 * @return void
 * @private
 */
 var centerVertically = function(){
 var shadowbox = SL.get('shadowbox');
 var scroll = document.documentElement.scrollTop;
 var s_top = scroll + Math.round((SL.getViewportHeight() - (shadowbox.offsetHeight || 0)) / 2);
 SL.setStyle(shadowbox, 'top', s_top + 'px');
 };

 /**
 * Adjusts the height of shadowbox_body_inner and centers Shadowbox
 * vertically in the viewport.
 *
 * @param {Number} height The height of shadowbox_body_inner
 * @param {Number} top The top of the Shadowbox
 * @param {Boolean} animate True to animate the transition
 * @param {Function} callback A callback to use when the animation completes
 * @return void
 * @private
 */
 var adjustHeight = function(height, top, animate, callback){
 height = parseInt(height);

 // update current_height
 current_height = height;

 // adjust the height
 var sbi = SL.get('shadowbox_body_inner');
 if(animate && options.animate){
 SL.animate(sbi, {
 height: { to: height }
 }, options.resizeDuration, callback);
 }else{
 SL.setStyle(sbi, 'height', height + 'px');
 if(typeof callback == 'function') callback();
 }

 // manually adjust the top because we're using fixed positioning in IE6
 if(absolute_pos){
 // listen for scroll so we can adjust
 centerVertically();
 SL.addEvent(window, 'scroll', centerVertically);

 // add scroll to top
 top += document.documentElement.scrollTop;
 }

 // adjust the top
 var shadowbox = SL.get('shadowbox');
 if(animate && options.animate){
 SL.animate(shadowbox, {
 top: { to: top }
 }, options.resizeDuration);
 }else{
 SL.setStyle(shadowbox, 'top', top + 'px');
 }
 };

 /**
 * Adjusts the width of shadowbox.
 *
 * @param {Number} width The width to use
 * @param {Boolean} animate True to animate the transition
 * @param {Function} callback A callback to use when the animation completes
 * @return void
 * @private
 */
 var adjustWidth = function(width, animate, callback){
 width = parseInt(width);

 // update current_width
 current_width = width;

 var shadowbox = SL.get('shadowbox');
 if(animate && options.animate){
 SL.animate(shadowbox, {
 width: { to: width }
 }, options.resizeDuration, callback);
 }else{
 SL.setStyle(shadowbox, 'width', width + 'px');
 if(typeof callback == 'function') callback();
 }
 };

 /**
 * Sets up a listener on the document for keystrokes.
 *
 * @param {Boolean} on True to enable the listner, false to turn
 * it off
 * @return void
 * @private
 */
 var listenKeyboard = function(on){
 if(!options.enableKeys) return;
 if(on){
 document.onkeydown = handleKey;
 }else{
 document.onkeydown = '';
 }
 };

 /**
 * Asserts the given key or code is present in the array of valid keys.
 *
 * @param {Array} valid An array of valid keys and codes
 * @param {String} key The character that was pressed
 * @param {Number} code The key code that was pressed
 * @return {Boolean} True if the key is valid
 * @private
 */
 var assertKey = function(valid, key, code){
 return (valid.indexOf(key) != -1 || valid.indexOf(code) != -1);
 };

 /**
 * A listener function that will act on a key pressed.
 *
 * @param {Event} e The event object
 * @return void
 * @private
 */
 var handleKey = function(e){
 var code = e ? e.which : event.keyCode;
 var key = String.fromCharCode(code).toLowerCase();
 if(assertKey(options.keysClose, key, code)){
 Shadowbox.close();
 }else if(assertKey(options.keysPrev, key, code)){
 Shadowbox.previous();
 }else if(assertKey(options.keysNext, key, code)){
 Shadowbox.next();
 }
 };

 /**
 * Shows and hides elements that are troublesome for modal overlays.
 *
 * @param {Boolean} on True to show the elements, false otherwise
 * @return void
 * @private
 */
 var toggleTroubleElements = function(on){
 var vis = (on ? 'visible' : 'hidden');
 var selects = document.getElementsByTagName('select');
 for(i = 0, len = selects.length; i < len; ++i){
 selects[i].style.visibility = vis;
 }
 var objects = document.getElementsByTagName('object');
 for(i = 0, len = objects.length; i < len; ++i){
 objects[i].style.visibility = vis;
 }
 var embeds = document.getElementsByTagName('embed');
 for(i = 0, len = embeds.length; i < len; ++i){
 embeds[i].style.visibility = vis;
 }
 };

 /**
 * Fills the Shadowbox with the loading skin.
 *
 * @return void
 * @private
 */
 var showLoading = function(){
 var loading = SL.get('shadowbox_loading');
 overwriteHTML(loading, String.format(options.skin.loading,
 options.assetURL + options.loadingImage,
 options.text.loading,
 options.text.cancel));
 loading.style.visibility = 'visible';
 };

 /**
 * Hides the Shadowbox loading skin.
 *
 * @param {Function} callback The callback function to call after
 * hiding the loading skin
 * @return void
 * @private
 */
 var hideLoading = function(callback){
 var t = current_gallery[current].type;
 var anim = (t == 'img' || t == 'html'); // fade on images & html
 var loading = SL.get('shadowbox_loading');
 if(anim){
 fadeOut(loading, 0.35, callback);
 }else{
 loading.style.visibility = 'hidden';
 callback();
 }
 };

 /**
 * Sets the size of the overlay to the size of the document.
 *
 * @return void
 * @private
 */
 var resizeOverlay = function(){
 var overlay = SL.get('shadowbox_overlay');
 SL.setStyle(overlay, {
 height: '100%',
 width: '100%'
 });
 SL.setStyle(overlay, 'height', SL.getDocumentHeight() + 'px');
 if(!isSafari3){
 // Safari3 includes vertical scrollbar in SL.getDocumentWidth()!
 // Leave overlay width at 100% for now...
 SL.setStyle(overlay, 'width', SL.getDocumentWidth() + 'px');
 }
 };

 /**
 * Used to determine if the pre-made overlay background image is needed
 * instead of using the trasparent background overlay. A pre-made background
 * image is used for all but image pieces in FF Mac because it has problems
 * displaying correctly if the background layer is not 100% opaque. When
 * displaying a gallery, if any piece in the gallery meets these criteria,
 * the pre-made background image will be used.
 *
 * @return {Boolean} Whether or not an overlay image is needed
 * @private
 */
 var checkOverlayImgNeeded = function(){
 if(!(isGecko && isMac)) return false;
 for(var i = 0, len = current_gallery.length; i < len; ++i){
 if(!RE.overlay.exec(current_gallery[i].type)) return true;
 }
 return false;
 };

 /**
 * Activates (or deactivates) the Shadowbox overlay. If a callback function
 * is provided, we know we're activating. Otherwise, deactivate the overlay.
 *
 * @param {Function} callback A callback to call after activation
 * @return void
 * @private
 */
 var toggleOverlay = function(callback){
 var overlay = SL.get('shadowbox_overlay');
 if(overlay_img_needed == null){
 overlay_img_needed = checkOverlayImgNeeded();
 }

 if(callback){
 resizeOverlay(); // size the overlay before showing
 if(overlay_img_needed){
 SL.setStyle(overlay, {
 visibility: 'visible',
 backgroundColor: 'transparent',
 backgroundImage: 'url(' + options.assetURL + options.overlayBgImage + ')',
 backgroundRepeat: 'repeat',
 opacity: 1
 });
 callback();
 }else{
 SL.setStyle(overlay, {
 visibility: 'visible',
 backgroundColor: options.overlayColor,
 backgroundImage: 'none'
 });
 fadeIn(overlay, options.overlayOpacity, options.fadeDuration,
 callback);
 }
 }else{
 if(overlay_img_needed){
 SL.setStyle(overlay, 'visibility', 'hidden');
 }else{
 fadeOut(overlay, options.fadeDuration);
 }

 // reset for next time
 overlay_img_needed = null;
 }
 };

 /**
 * Initializes the Shadowbox environment. Appends Shadowbox' HTML to the
 * document and sets up listeners on the window and overlay element.
 *
 * @param {Object} opts The default options to use
 * @return void
 * @public
 * @static
 */
 Shadowbox.init = function(opts){
 if(initialized) return; // don't initialize twice
 options = apply(options, opts || {});

 // add markup
 appendHTML(document.body, options.skin.main);

 // compile file type regular expressions here for speed
 RE.img = new RegExp('\.(' + options.ext.img.join('|') + ')\s*$', 'i');
 RE.qt = new RegExp('\.(' + options.ext.qt.join('|') + ')\s*$', 'i');
 RE.wmp = new RegExp('\.(' + options.ext.wmp.join('|') + ')\s*$', 'i');
 RE.qtwmp = new RegExp('\.(' + options.ext.qtwmp.join('|') + ')\s*$', 'i');
 RE.iframe = new RegExp('\.(' + options.ext.iframe.join('|') + ')\s*$', 'i');

 // handle window resize events
 var id = null;
 var resize = function(){
 clearInterval(id);
 id = null;
 resizeOverlay();
 resizeContent(optimal_height, optimal_width);
 };
 SL.addEvent(window, 'resize', function(){
 if(activated){
 // use event buffering to prevent jerky window resizing
 if(id){
 clearInterval(id);
 id = null;
 }
 if(!id) id = setInterval(resize, 50);
 }
 });

 if(options.listenOverlay){
 // add a listener to the overlay
 SL.addEvent(SL.get('shadowbox_overlay'), 'click', Shadowbox.close);
 }

 // adjust some positioning if needed
 if(absolute_pos){
 // give the container absolute positioning
 SL.setStyle(SL.get('shadowbox_container'), 'position', 'absolute');
 // give shadowbox_body "layout"...whatever that is
 SL.setStyle('shadowbox_body', 'zoom', 1);
 // need to listen to the container element because it covers the top
 // half of the page
 SL.addEvent(SL.get('shadowbox_container'), 'click', function(e){
 var target = SL.getTarget(e);
 if(target.id && target.id == 'shadowbox_container') Shadowbox.close();
 });
 }

 // skip setup, will need to be done manually later
 if(!options.skipSetup) Shadowbox.setup();
 initialized = true;
 };

 /**
 * Sets up listeners on the given links that will trigger Shadowbox. If no
 * links are given, this method will set up every anchor element on the page
 * with the appropriate rel attribute. Note: Because AREA elements do not
 * support the rel attribute, they must be explicitly passed to this method.
 *
 * @param {Array} links An array (or array-like) list of anchor
 * and/or area elements to set up
 * @param {Object} opts Some options to use for the given links
 * @return void
 * @public
 * @static
 */
 Shadowbox.setup = function(links, opts){
 // get links if none specified
 if(!links){
 var links = [];
 var a = document.getElementsByTagName('a'), rel;
 for(var i = 0, len = a.length; i < len; ++i){
 rel = a[i].getAttribute('rel');
 if(rel && RE.rel.test(rel)) links[links.length] = a[i];
 }
 }else if(!links.length){
 links = [links]; // one link
 }

 var link;
 for(var i = 0, len = links.length; i < len; ++i){
 link = links[i];
 if(typeof link.shadowboxCacheKey == 'undefined'){
 // assign cache key expando
 // use integer primitive to avoid memory leak in IE
 link.shadowboxCacheKey = cache.length;
 SL.addEvent(link, 'click', handleClick); // add listener
 }
 cache[link.shadowboxCacheKey] = this.buildCacheObj(link, opts);
 }
 };

 /**
 * Builds an object from the original link element data to store in cache.
 * These objects contain (most of) the following keys:
 *
 * - el: the link element
 * - title: the linked file title
 * - type: the linked file type
 * - content: the linked file's URL
 * - gallery: the gallery the file belongs to (optional)
 * - height: the height of the linked file (only necessary for movies)
 * - width: the width of the linked file (only necessary for movies)
 * - options: custom options to use (optional)
 *
 * @param {HTMLElement} link The link element to process
 * @return {Object} An object representing the link
 * @public
 * @static
 */
 Shadowbox.buildCacheObj = function(link, opts){
 var href = link.href; // don't use getAttribute() here
 var o = {
 el: link,
 title: link.getAttribute('title'),
 type: getPlayerType(href),
 options: apply({}, opts || {}), // break the reference
 content: href
 };

 // remove link-level options from top-level options
 var opt, l_opts = ['title', 'type', 'height', 'width', 'gallery'];
 for(var i = 0, len = l_opts.length; i < len; ++i){
 opt = l_opts[i];
 if(typeof o.options[opt] != 'undefined'){
 o[opt] = o.options[opt];
 delete o.options[opt];
 }
 }

 // HTML options always trump JavaScript options, so do these last
 var rel = link.getAttribute('rel');
 if(rel){
 // extract gallery name from shadowbox[name] format
 var match = rel.match(RE.gallery);
 if(match) o.gallery = escape(match[2]);

 // other parameters
 var params = rel.split(';');
 for(var i = 0, len = params.length; i < len; ++i){
 match = params[i].match(RE.param);
 if(match){
 if(match[1] == 'options'){
 eval('o.options = apply(o.options, ' + match[2] + ')');
 }else{
 o[match[1]] = match[2];
 }
 }
 }
 }

 return o;
 };

 /**
 * Applies the given set of options to those currently in use. Note: Options
 * will be reset on Shadowbox.open() so this function is only useful after
 * it has already been called (while Shadowbox is open).
 *
 * @param {Object} opts The options to apply
 * @return void
 * @public
 * @static
 */
 Shadowbox.applyOptions = function(opts){
 if(opts){
 // use apply here to break references
 default_options = apply({}, options); // store default options
 options = apply(options, opts); // apply options
 }
 };

 /**
 * Reverts Shadowbox' options to the last default set in use before
 * Shadowbox.applyOptions() was called.
 *
 * @return void
 * @public
 * @static
 */
 Shadowbox.revertOptions = function(){
 if(default_options){
 options = default_options; // revert to default options
 default_options = null; // erase for next time
 }
 };

 /**
 * Opens the given object in Shadowbox. This object may be either an
 * anchor/area element, or an object similar to the one created by
 * Shadowbox.buildCacheObj().
 *
 * @param {mixed} obj The object or link element that defines
 * what to display
 * @return void
 * @public
 * @static
 */
 Shadowbox.open = function(obj, opts){
 if(activated) return; // already open
 activated = true;

 // is it a link?
 if(isLink(obj)){
 if(typeof obj.shadowboxCacheKey == 'undefined' || typeof cache[obj.shadowboxCacheKey] == 'undefined'){
 // link element that hasn't been set up before
 // create an object on-the-fly
 obj = this.buildCacheObj(obj, opts);
 }else{
 // link element that has been set up before, get from cache
 obj = cache[obj.shadowboxCacheKey];
 }
 }

 this.revertOptions();
 if(obj.options || opts){
 // use apply here to break references
 this.applyOptions(apply(apply({}, obj.options || {}), opts || {}));
 }

 // update current & current_gallery
 setupGallery(obj);

 // anything to display?
 if(current_gallery.length){
 // fire onOpen hook
 if(options.onOpen && typeof options.onOpen == 'function'){
 options.onOpen(obj);
 }

 // display:block here helps with correct dimension calculations
 SL.setStyle(SL.get('shadowbox'), 'display', 'block');

 toggleTroubleElements(false);
 var dims = getDimensions(options.initialHeight, options.initialWidth);
 adjustHeight(dims.height, dims.top);
 adjustWidth(dims.width);
 hideBars(false);

 // show the overlay and load the content
 toggleOverlay(function(){
 SL.setStyle(SL.get('shadowbox'), 'visibility', 'visible');
 showLoading();
 loadContent();
 });
 }
 };

 /**
 * Jumps to the piece in the current gallery with index num.
 *
 * @param {Number} num The gallery index to view
 * @return void
 * @public
 * @static
 */
 Shadowbox.change = function(num){
 if(!current_gallery) return; // no current gallery
 if(!current_gallery[num]){ // index does not exist
 if(!options.continuous){
 return;
 }else{
 num = (num < 0) ? (current_gallery.length - 1) : 0; // loop
 }
 }

 // update current
 current = num;

 // stop listening for drag
 toggleDrag(false);
 // empty the content
 setContent(null);
 // turn this back on when done
 listenKeyboard(false);

 // fire onChange handler
 if(options.onChange && typeof options.onChange == 'function'){
 options.onChange(current_gallery[current]);
 }

 showLoading();
 hideBars(loadContent);
 };

 /**
 * Jumps to the next piece in the gallery.
 *
 * @return {Boolean} True if the gallery changed to next item, false
 * otherwise
 * @public
 * @static
 */
 Shadowbox.next = function(){
 return this.change(current + 1);
 };

 /**
 * Jumps to the previous piece in the gallery.
 *
 * @return {Boolean} True if the gallery changed to previous item,
 * false otherwise
 * @public
 * @static
 */
 Shadowbox.previous = function(){
 return this.change(current - 1);
 };

 /**
 * Deactivates Shadowbox.
 *
 * @return void
 * @public
 * @static
 */
 Shadowbox.close = function(){
 if(!activated) return; // already closed

 // stop listening for keys
 listenKeyboard(false);
 // hide
 SL.setStyle(SL.get('shadowbox'), {
 display: 'none',
 visibility: 'hidden'
 });
 // stop listening for scroll on IE
 if(absolute_pos) SL.removeEvent(window, 'scroll', centerVertically);
 // stop listening for drag
 toggleDrag(false);
 // empty the content
 setContent(null);
 // prevent old image requests from loading
 if(preloader){
 preloader.onload = function(){};
 preloader = null;
 }
 // hide the overlay
 toggleOverlay(false);
 // turn on trouble elements
 toggleTroubleElements(true);

 // fire onClose handler
 if(options.onClose && typeof options.onClose == 'function'){
 options.onClose(current_gallery[current]);
 }

 activated = false;
 };

 /**
 * Clears Shadowbox' cache and removes listeners and expandos from all
 * cached link elements. May be used to completely reset Shadowbox in case
 * links on a page change.
 *
 * @return void
 * @public
 * @static
 */
 Shadowbox.clearCache = function(){
 for(var i = 0, len = cache.length; i < len; ++i){
 if(cache[i].el){
 SL.removeEvent(cache[i].el, 'click', handleClick);
 delete cache[i].shadowboxCacheKey;
 }
 }
 cache = [];
 };

 /**
 * Generates the markup necessary to embed the movie file with the given
 * link element. This markup will be browser-specific. Useful for generating
 * the media test suite.
 *
 * @param {HTMLElement} link The link to the media file
 * @return {Object} The proper markup to use (see above)
 * @public
 * @static
 */
 Shadowbox.movieMarkup = function(obj){
 // movies default to 300x300 pixels
 var h = obj.height ? parseInt(obj.height, 10) : 300;
 var w = obj.width ? parseInt(obj.width, 10) : 300;

 var autoplay = options.autoplayMovies;
 var controls = options.showMovieControls;
 if(obj.options){
 if(obj.options.autoplayMovies != null){
 autoplay = obj.options.autoplayMovies;
 }
 if(obj.options.showMovieControls != null){
 controls = obj.options.showMovieControls;
 }
 }

 var markup = {
 tag: 'object',
 name: 'shadowbox_content'
 };

 switch(obj.type){
 case 'swf':
 var dims = getDimensions(h, w, true);
 h = dims.height;
 w = dims.width;
 markup.type = 'application/x-shockwave-flash';
 markup.data = obj.content;
 markup.children = [
 { tag: 'param', name: 'movie', value: obj.content }
 ];
 break;
 case 'flv':
 autoplay = autoplay ? 'true' : 'false';
 var showicons = 'false';
 var a = h/w; // aspect ratio
 if(controls){
 showicons = 'true';
 h += 20; // height of JW FLV player controller
 }
 var dims = getDimensions(h, h/a, true); // resize
 h = dims.height;
 w = (h-(controls?20:0))/a; // maintain aspect ratio
 var flashvars = [
 'file=' + obj.content,
 'height=' + h,
 'width=' + w,
 'autostart=' + autoplay,
 'displayheight=' + (h - (controls?20:0)),
 'showicons=' + showicons,
 'backcolor=0x000000&amp;frontcolor=0xCCCCCC&amp;lightcolor=0x557722'
 ];
 markup.type = 'application/x-shockwave-flash';
 markup.data = options.assetURL + options.flvPlayer;
 markup.children = [
 { tag: 'param', name: 'movie', value: options.assetURL + options.flvPlayer },
 { tag: 'param', name: 'flashvars', value: flashvars.join('&amp;') },
 { tag: 'param', name: 'allowfullscreen', value: 'true' }
 ];
 break;
 case 'qt':
 autoplay = autoplay ? 'true' : 'false';
 if(controls){
 controls = 'true';
 h += 16; // height of QuickTime controller
 }else{
 controls = 'false';
 }
 markup.children = [
 { tag: 'param', name: 'src', value: obj.content },
 { tag: 'param', name: 'scale', value: 'aspect' },
 { tag: 'param', name: 'controller', value: controls },
 { tag: 'param', name: 'autoplay', value: autoplay }
 ];
 if(isIE){
 markup.classid = 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B';
 markup.codebase = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';
 }else{
 markup.type = 'video/quicktime';
 markup.data = obj.content;
 }
 break;
 case 'wmp':
 autoplay = autoplay ? 1 : 0;
 markup.children = [
 { tag: 'param', name: 'autostart', value: autoplay }
 ];
 if(isIE){
 if(controls){
 controls = 'full';
 h += 70; // height of WMP controller in IE
 }else{
 controls = 'none';
 }
 // markup.type = 'application/x-oleobject';
 markup.classid = 'clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6';
 markup.children[markup.children.length] = { tag: 'param', name: 'url', value: obj.content };
 markup.children[markup.children.length] = { tag: 'param', name: 'uimode', value: controls };
 }else{
 if(controls){
 controls = 1;
 h += 45; // height of WMP controller in non-IE
 }else{
 controls = 0;
 }
 markup.type = 'video/x-ms-wmv';
 markup.data = obj.content;
 markup.children[markup.children.length] = { tag: 'param', name: 'showcontrols', value: controls };
 }
 break;
 }

 markup.height = h; // new height includes controller
 markup.width = w;

 return markup;
 };

 /**
 * Creates an HTML string from an object representing HTML elements. Based
 * on Ext.DomHelper's createHtml.
 *
 * @param {Object} obj The HTML definition object
 * @return {String} An HTML string
 * @public
 * @static
 */
 Shadowbox.createHTML = function(obj){
 var html = '<' + obj.tag;
 for(var attr in obj){
 if(attr == 'tag' || attr == 'html' || attr == 'children') continue;
 if(attr == 'cls'){
 html += ' class="' + obj['cls'] + '"';
 }else{
 html += ' ' + attr + '="' + obj[attr] + '"';
 }
 }
 if(RE.empty.test(obj.tag)){
 html += '/>\n';
 }else{
 html += '>\n';
 var cn = obj.children;
 if(cn){
 for(var i = 0, len = cn.length; i < len; ++i){
 html += this.createHTML(cn[i]);
 }
 }
 if(obj.html) html += obj.html;
 html += '</' + obj.tag + '>\n';
 }
 return html;
 };

 /**
 * Gets an object that lists which plugins are supported by the client. The
 * keys of this object will be:
 *
 * - fla: Adobe Flash Player
 * - qt: QuickTime Player
 * - wmp: Windows Media Player
 * - f4m: Flip4Mac QuickTime Player
 *
 * @return {Object} The plugins object
 * @public
 * @static
 */
 Shadowbox.getPlugins = function(){
 return plugins;
 };

 /**
 * Gets the current options object in use.
 *
 * @return {Object} The options object
 * @public
 * @static
 */
 Shadowbox.getOptions = function(){
 return options;
 };

 /**
 * Gets the current gallery object.
 *
 * @return {Object} The current gallery item
 * @public
 * @static
 */
 Shadowbox.getCurrent = function(){
 return current_gallery[current];
 };

 /**
 * Gets the current version number of Shadowbox.
 *
 * @return {String} The current version
 * @public
 * @static
 */
 Shadowbox.getVersion = function(){
 return version;
 };

})();

/**
 * Finds the index of the given object in this array.
 *
 * @param {mixed} o The object to search for
 * @return {Number} The index of the given object
 * @public
 */
Array.prototype.indexOf = Array.prototype.indexOf || function(o){
 for(var i = 0, len = this.length; i < len; ++i){
 if(this[i] == o) return i;
 }
 return -1;
};

/**
 * Formats a string with the given parameters. The string for format must have
 * placeholders that correspond to the numerical index of the arguments passed
 * in surrounded by curly braces (e.g. 'Some {0} string {1}').
 *
 * @param {String} format The string to format
 * @param ... The parameters to put inside the string
 * @return {String} The string with the specified parameters
 * replaced
 * @public
 * @static
 */
String.format = String.format || function(format){
 var args = Array.prototype.slice.call(arguments, 1);
 return format.replace(/\{(\d+)\}/g, function(m, i){
 return args[i];
 });
};

<!--
// -----------------------------------------------------------------------------
// Globals
// Major version of Flash required
var requiredMajorVersion = 9;
// Minor version of Flash required
var requiredMinorVersion = 0;
// Revision of Flash required
var requiredRevision = 0;
// the version of javascript supported
var jsVersion = 1.0;

var flashVars;
var clipName;
// -----------------------------------------------------------------------------
// -->


<!-- // 
// launch code that button calls
function icx_windowopen() {
 
 var launchURL = clientURL +'icovia.aspx'; 
 var querystring = window.location.href.split('?');
 
 if(typeof(_customerID) != "undefined" && _customerID.length > 0)
 {

 launchURL = launchURL + '?' + 'uguid=' + _customerID;
 }
 
 if(typeof(_email) != "undefined" && _email.length > 0)
 {

 launchURL = launchURL + '&' + 'email=' + _email;
 }

 
 var screenWidth = screen.width - 100;
 var screenHeight = screen.height - 100;
 var topPos = (screen.height-screenHeight)/2;
 var lftPos = (screen.width-screenWidth)/2;
 
 newWindow=window.open(launchURL ,'RP','height='+screenHeight+',width='+screenWidth+',top='+topPos+',left='+lftPos+',status=no,toolbar=no,scrollbars=no,resizable=yes,menubar=no'); void(0);

 var popUpMsg = "You appear to have a pop-up blocker that prevents the Room Planner from opening. Please enable pop-ups for this site and try again. Thank you.";
 if(!newWindow){
 alert(popUpMsg);
 }
}


function openCenteredWindow(URLtoOpen,windowName,windowW,windowH,scrollVal){
 var topPos = (screen.height-windowH)/2;
 var lftPos = (screen.width-windowW)/2;
 var scrollBarVal = 1;
 if(scrollVal != undefined) scrollBarVal = scrollVal;
 newWindow=window.open(URLtoOpen,windowName,'height='+windowH+',width='+windowW+',top='+topPos+',left='+lftPos+',toolbar=0,scrollbars='+scrollBarVal+',resizable=1,menubar=0');
 var popUpMsg = "You appear to have a pop-up blocker that prevents a window from opening. Please enable pop-ups for this site and try again. Thank you.";
 if(!newWindow){
 alert(popUpMsg);
 }
};


function init(){
 flashVars = getQuerystring();
 clipName = 'content/_swfs/application/icovia_de_v4';
}


function getQuerystring(){
 var querystring = window.location.href.split('?');
 if (querystring.length==0){
 return '';
 }
 return querystring[1];
 //return 'querystring='+ querystring[1];// removed on 23.apr.2007 by M@ and Phil, not needed anymore
}


function openBrowseWindow(){
 window.open('importFile.aspx','import','height=220,width=400,top='+((screen.height/2)-(110))+',left='+((screen.width/2)-(200))+',toolbar=no,scrollbars=no,resizable=no,menubar=no'); 
}
function loadFileName(svar){
 window.document.icovia_int.SetVariable('MCL_importPanel.TXT_fileName.text',svar);
}
function openNewWindow(URLtoOpen, windowName, windowFeatures) {
 newWindow=window.open(URLtoOpen, windowName, windowFeatures);
}

var movieName = "PassingVars";
 
function checkGUID(args){
 sendGUID(myGUID);
}

function thisMovie(movieName) {
 if (navigator.appName.indexOf ("Microsoft") !=-1) {
 return window[movieName]
 } else {
 return document[movieName]
 }
}
 
function sendGUID(args){
 thisMovie(movieName).SetVariable("UGUID", args);
}

init();



//Detect Client Browser type

var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;
jsVersion = 1.1;
// JavaScript helper required to detect Flash Player PlugIn version information
function JSGetSwfVer(i){
 // NS/Opera version >= 3 check for Flash plugin in plugin array
 if (navigator.plugins != null && navigator.plugins.length > 0) {
 if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
 var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
 var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
 descArray = flashDescription.split(" ");
 tempArrayMajor = descArray[2].split(".");
 versionMajor = tempArrayMajor[0];
 versionMinor = tempArrayMajor[1];
 if ( descArray[3] != "" ) {
 tempArrayMinor = descArray[3].split("r");
 } else {
 tempArrayMinor = descArray[4].split("r");
 }
 versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
 flashVer = versionMajor + "." + versionMinor + "." + versionRevision;
 } else {
 flashVer = -1;
 }
 }
 // MSN/WebTV 2.6 supports Flash 4
 else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4;
 // WebTV 2.5 supports Flash 3
 else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3;
 // older WebTV supports Flash 2
 else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2;
 // Can't detect in all other cases
 else {
 
 flashVer = -1;
 }
 return flashVer;
} 
// If called with no parameters this function returns a floating point value 
// which should be the version of the Flash Player or 0.0 
// ex: Flash Player 7r14 returns 7.14
// If called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available
function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) 
{
 reqVer = parseFloat(reqMajorVer + "." + reqRevision);
 // loop backwards through the versions until we find the newest version 
 for (i=25;i>0;i--) { 
 if (isIE && isWin && !isOpera) {
 versionStr = VBGetSwfVer(i);
 } else {
 versionStr = JSGetSwfVer(i); 
 }
 if (versionStr == -1 ) { 
 return false;
 } else if (versionStr != 0) {
 if(isIE && isWin && !isOpera) {
 tempArray = versionStr.split(" ");
 tempString = tempArray[1];
 versionArray = tempString .split(","); 
 } else {
 versionArray = versionStr.split(".");
 }
 versionMajor = versionArray[0];
 versionMinor = versionArray[1];
 versionRevision = versionArray[2];
 
 versionString = versionMajor + "." + versionRevision; // 7.0r24 == 7.24
 versionNum = parseFloat(versionString);
 // is the major.revision >= requested major.revision AND the minor version >= requested minor
 if ( (versionMajor > reqMajorVer) && (versionNum >= reqVer) ) {
 return true;
 } else {
 return ((versionNum >= reqVer && versionMinor >= reqMinorVer) ? true : false ); 
 }
 }
 } 
 return (reqVer ? false : 0.0);
}


 

 
//-->











//v1.0
//Copyright 2006 Adobe Systems, Inc. All rights reserved.
function AC_AddExtension(src, ext)
{
 if (src.indexOf('?') != -1)
 return src.replace(/\?/, ext+'?'); 
 else
 return src + ext;
}

function AC_Generateobj(objAttrs, params, embedAttrs) 
{ 
 var str = '<object ';
 for (var i in objAttrs)
 str += i + '="' + objAttrs[i] + '" ';
 str += '>';
 for (var i in params)
 str += '<param name="' + i + '" value="' + params[i] + '" /> ';
 str += '<embed ';
 for (var i in embedAttrs)
 str += i + '="' + embedAttrs[i] + '" ';
 str += ' ></embed></object>';

 document.write(str);
}

function AC_FL_RunContent(){
 var ret = 
 AC_GetArgs
 ( arguments, ".swf", "movie", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
 , "application/x-shockwave-flash"
 );
 AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
}

function AC_SW_RunContent(){
 var ret = 
 AC_GetArgs
 ( arguments, ".dcr", "src", "clsid:166B1BCA-3F9C-11CF-8075-444553540000"
 , null
 );
 AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
}

function AC_GetArgs(args, ext, srcParamName, classid, mimeType){
 var ret = new Object();
 ret.embedAttrs = new Object();
 ret.params = new Object();
 ret.objAttrs = new Object();
 for (var i=0; i < args.length; i=i+2){
 var currArg = args[i].toLowerCase(); 

 switch (currArg){ 
 case "classid":
 break;
 case "pluginspage":
 ret.embedAttrs[args[i]] = args[i+1];
 break;
 case "src":
 case "movie": 
 args[i+1] = AC_AddExtension(args[i+1], ext);
 ret.embedAttrs["src"] = args[i+1];
 ret.params[srcParamName] = args[i+1];
 break;
 case "onafterupdate":
 case "onbeforeupdate":
 case "onblur":
 case "oncellchange":
 case "onclick":
 case "ondblClick":
 case "ondrag":
 case "ondragend":
 case "ondragenter":
 case "ondragleave":
 case "ondragover":
 case "ondrop":
 case "onfinish":
 case "onfocus":
 case "onhelp":
 case "onmousedown":
 case "onmouseup":
 case "onmouseover":
 case "onmousemove":
 case "onmouseout":
 case "onkeypress":
 case "onkeydown":
 case "onkeyup":
 case "onload":
 case "onlosecapture":
 case "onpropertychange":
 case "onreadystatechange":
 case "onrowsdelete":
 case "onrowenter":
 case "onrowexit":
 case "onrowsinserted":
 case "onstart":
 case "onscroll":
 case "onbeforeeditfocus":
 case "onactivate":
 case "onbeforedeactivate":
 case "ondeactivate":
 case "type":
 case "codebase":
 ret.objAttrs[args[i]] = args[i+1];
 break;
 case "width":
 case "height":
 case "align":
 case "vspace": 
 case "hspace":
 case "class":
 case "title":
 case "accesskey":
 case "name":
 case "id":
 case "tabindex":
 ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1];
 break;
 default:
 ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1];
 }
 }
 ret.objAttrs["classid"] = classid;
 if (mimeType) ret.embedAttrs["type"] = mimeType;
 return ret;
}




//v1.1
//Copyright 2006 Adobe Systems, Inc. All rights reserved.
function AC_AX_RunContent(){
 var ret = AC_AX_GetArgs(arguments);
 AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
}

function AC_AX_GetArgs(args){
 var ret = new Object();
 ret.embedAttrs = new Object();
 ret.params = new Object();
 ret.objAttrs = new Object();
 for (var i=0; i < args.length; i=i+2){
 var currArg = args[i].toLowerCase(); 

 switch (currArg){ 
 case "pluginspage":
 case "type":
 case "src":
 ret.embedAttrs[args[i]] = args[i+1];
 break;
 case "data":
 case "codebase":
 case "classid":
 case "id":
 case "onafterupdate":
 case "onbeforeupdate":
 case "onblur":
 case "oncellchange":
 case "onclick":
 case "ondblClick":
 case "ondrag":
 case "ondragend":
 case "ondragenter":
 case "ondragleave":
 case "ondragover":
 case "ondrop":
 case "onfinish":
 case "onfocus":
 case "onhelp":
 case "onmousedown":
 case "onmouseup":
 case "onmouseover":
 case "onmousemove":
 case "onmouseout":
 case "onkeypress":
 case "onkeydown":
 case "onkeyup":
 case "onload":
 case "onlosecapture":
 case "onpropertychange":
 case "onreadystatechange":
 case "onrowsdelete":
 case "onrowenter":
 case "onrowexit":
 case "onrowsinserted":
 case "onstart":
 case "onscroll":
 case "onbeforeeditfocus":
 case "onactivate":
 case "onbeforedeactivate":
 case "ondeactivate":
 ret.objAttrs[args[i]] = args[i+1];
 break;
 case "width":
 case "height":
 case "align":
 case "vspace": 
 case "hspace":
 case "class":
 case "title":
 case "accesskey":
 case "name":
 case "tabindex":
 ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1];
 break;
 default:
 ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1];
 }
 }
 return ret;
}


function _icoviaVoid() { return; }

function icoviaTracker(page)
{
 var i=new Image(1,1);
 i.src=page;
 i.onload=function() {_icoviaVoid();}
 }

/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;
