var SITE_COUNTRY = 'RO';
BECurrencySymbol = '';
BECurrencyAfter = true;
BEDecimalSeparator = ',';
BEThousandSeparator = '.'; 


$.ajaxSetup ({
    // Disable caching of AJAX responses */
    cache: false
});

jQuery.preloadImages = function()
{
  for(var i = 0; i<arguments.length; i++)
  {
    jQuery("<img>").attr("src", arguments[i]);
  }
};

function populateElement(selector, defvalue) {
    $(selector).each(function() {
        if($.trim(this.value) == "") {
            this.value = defvalue;
        }
    });
  
    $(selector).focus(function() {
        if(this.value == defvalue) {
            this.value = "";
        }
    });
    
    $(selector).blur(function() {
        if($.trim(this.value) == "") {
            this.value = defvalue;
        }
    });
};


var timeout         = 500;
var closetimer		= 0;
var ddmenuitem      = 0;

function jsddm_open(){
	jsddm_canceltimer();
    jsddm_close();
    var a = $(this).find('a:eq(0)');
    var p = a.position();
    ddmenuitem = $(this).find('ul:eq(0)').css({'visibility': 'visible'});
    ddmenuitem.css({'left': (p.left+a.outerWidth(false)-ddmenuitem.outerWidth(false))+'px', 'top': (p.top+a.outerHeight(true)-1)+'px'});
};

function jsddm_close(){
	if(ddmenuitem) ddmenuitem.css('visibility', 'hidden');
};

function jsddm_timer(){
	closetimer = window.setTimeout(jsddm_close, timeout);
};

function jsddm_canceltimer(){	
	if(closetimer){
		window.clearTimeout(closetimer);
		closetimer = null;
	}
};
	
var cp_timeout      = 500;
var cp_closetimer	= 0;
var cp   = 0;

function cp_open()
{	cp_canceltimer();
	if(!cp && $("#cart-items").text() > 0){
		$('#cp-body').html('<p style="text-align: center;padding: 10px 0;">Se încarcă...</p>');
    	cp = $("#cart-preview").css({'visibility': 'visible'});
    	$.post("/shop/previewCart.html", {}, function(data) { // Do an AJAX call
			$('#cp-body').html(data);
		});
	}
};

function cp_close()
{
	if(cp){
		cp.css('visibility', 'hidden');
		cp_canceltimer();
		cp = null;
	}
};

function cp_timer()
{
	cp_closetimer = window.setTimeout(cp_close, cp_timeout);
};

function cp_canceltimer()
{	if(cp_closetimer){
		window.clearTimeout(cp_closetimer);
		cp_closetimer = null;
	}
};

function addToCart(e)
{
	var id = e.target.id.substring(3);
	var qty = $("#qty-"+id).attr("value");
	if(qty == undefined){
		qty = 1;
	}
	var src = $(e.target);
	$.post("/shop/cart/add.html",{id:id, qty: qty}, addToCartDone, "json");
	return false;
};

function addToCartDone(data){
	if(data.success){
		$.jGrowl("Cartea a fost adăugată în coș.", { life: 5000, theme: 'normal'});
		$("#cart-items").text(data.count);
		$("#cart-amount").text(data.total);
	}else{
		$.jGrowl("Nu s-a putut adăuga cartea în coș.", { life: 10000, header: 'Eroare', theme: 'error'});
	}
};

function addToDefaultList(e)
{
	var id = e.target.id.substring(3);
	var btnType = e.target.id.substring(0, 2);
	if(btnType == 'al'){ 
	var src = $(e.target);
	$.post("/user/list/add.html",{id:id}, addToListDone, "json");
	}
	return false;
};

function addToListDone(data){
	if(data.success){
		$.jGrowl("Cartea a fost adăugată în listă.", { life: 5000, theme: 'normal'});
		$("#cart-items").text(data.count);
		$("#cart-amount").text(data.total);
	}else{
		var err = "Nu s-a putut adăuga cartea în listă.";
		if(data.error){
			err = data.error;
		}
		$.jGrowl(err, { life: 10000, header: 'Eroare', theme: 'error'});
	}
};


var hasGPImg = '<img src="http://www.google.com/intl/en/googlebooks/images/gbs_preview_sticker1.gif" style="float: right" ';
function setGPreviewList(data){
	var title = '';
	for (i in data) {
		var book = data[i];
		if(book.preview != 'noview'){
			title = book.preview == 'full' ? 'Full view':'Limited preview'+' is available for this book'; 
      		$('#b' + book.bib_key.substring(4) + ' > .s').prepend(hasGPImg+ ' title="'+title+'" />');
		}
	}
}
function initGPreview()
{
	var isbns = [];
	var i = 0;
	$("div#bll > div").each(function() {
        isbns[i++] = 'ISBN'+this.id.substring(1);     
    });
    if(isbns.length>0){
    var api_url ="http://books.google.com/books?jscmd=viewapi&callback=setGPreviewList&bibkeys=" + isbns.join(",");
    
	var scriptElement = document.createElement("script");
  	scriptElement.setAttribute("id", "jsonScript");
  	scriptElement.setAttribute("src", api_url);
  	scriptElement.setAttribute("type", "text/javascript");
  	document.documentElement.firstChild.appendChild(scriptElement);
    }
};


function initializeGPV() {
	var viewer = new google.books.DefaultViewer(document.getElementById('preview'), {showLinkChrome: false});
	viewer.load('ISBN:'+ean);
}
var lists = null;
function addToList(e){
	var list_id = e.target.id.substring(5);
	var id = $('.btn-list').attr("id").substring(3);
	$.post("/user/list/add.html",{id:id, list: list_id}, addToListDone, "json");
	lists.hide();
	lists = null;
	return false;
}
function gPreview(e){
	var v = Boxy._viewport();
	$('#preview').height(v.height - 100);
	$('#preview').width(990);
	var preview = new Boxy('#preview', {fixed: false, modal: true, title: 'Book Preview'});
	initializeGPV();
	return false;
}
var img = '<a href="#" id="gprev" style="float: right; margin-right: 10px;"><img src="http://www.google.com/intl/en/googlebooks/images/gbs_preview_button1.gif" ';
function setGPreview(data){
	for (i in data) {
		var book = data[i];
		if(book.preview != 'noview'){
			//title = 'Limited preview'+' is available for this book';
			var title = book.preview == 'full' ? 'Full view':'Limited preview'+' is available for this book'; 
      		$('#wgp').prepend(img+ ' title="'+title+'" /></a>');
		}
	}
}

$(document).ready(function()
{
    populateElement("#search", "Caută după ISBN, titlu, autor, etc...");
    $('#search').bind('blur', function(){$('#suggestions').fadeOut()});
    $('#search').bind('keyup', lookup);
    $('.sort-by').bind('mouseover', jsddm_open);
    $('.sort-by').bind('mouseout',  jsddm_timer);
    $('#cart-items, #cart-amount').bind('mouseenter', cp_open);
    $('#cart-preview').bind('mouseleave',  cp_timer);
    $('.btn-cart').bind('click', addToCart);
	$("select.linkselect").linkselect({classLink: 'srcat',
		classLinkOpen: 'srcat-active',
		classLinkFocus: '',
		classContainer: 'srcat-cont',
		afterChange: function(src, code, value){
			if(value.length > 22)
				$('#sc_link').html(value.substr(0, 22)+'…');
		}});
	$(function(){
		$('form.jqt').jqTransform({imgPath:'/jqt/img/'});
	});
	initGPreview();
    if(typeof(ean) !== 'undefined' && ean > 0){
    	$('.btn-list').bind('click', addToDefaultList);
    	$('.drop-list').bind('click', function(){
    		if(lists == null){
    			lists = new Boxy('#lists', {fixed: false, title: 'Pick a list', afterHide: function(){lists = null;}});
    		}
    	});
    	$('.user-list').bind('click', addToList);
    	$('#gprev').bind('click', gPreview);
     }
});

var ac_timeout;
var ac_value;

function lookup(event){
	clearTimeout(ac_timeout);
	if(event.keyCode == 27){
		$('#suggestions').fadeOut();
		return;
	}
	ac_value = event.target.value;
	ac_timeout = setTimeout(doLookup, 500); 
};

function doLookup() {
	if(ac_value.length < 3) {
		$('#suggestions').fadeOut(); // Hide the suggestions box
	} else {
		$.post("/search/suggest.html", {queryString: ""+ac_value+""}, function(data) { // Do an AJAX call
			$('#suggestions').fadeIn(); // Show the suggestions box
			$('#suggestions').html(data); // Fill the suggestions box
		});
	}
};

function phoneDlg(e){
	$('#phonedlg').height(300);
	$('#phonedlg').width(700);
	var preview = new Boxy('#preview', {fixed: false, modal: true, title: 'Formular contact telefonic'});
	initialize();
	return false;
}

formatMoney = function(v){
    v = roundMoney(v);
    v = String(v);
    var ps = v.split('.');
    var whole = ps[0];
    var sub = ps[1] ? BEDecimalSeparator+ ps[1] : BEDecimalSeparator+'00';
    var r = /(\d+)(\d{3})/;
    while (r.test(whole)) {
        whole = whole.replace(r, '$1' + BEThousandSeparator + '$2');
    }
    v = whole + sub;
    if(v.charAt(0) == '-' && !BECurrencyAfter){
        return '-'+ BECurrencySymbol + v.substr(1);
    }
	if(BECurrencyAfter){
		return v + BECurrencySymbol;
	}
    return BECurrencySymbol + v;
};
roundMoney = function(v){
    v = (Math.round((v-0)*100))/100;
    v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
    return v;
};

document.onclick = jsddm_close;
/*!
 * Linkselect jQuery Plug-in
 *
 * Copyright 2008 Giva, Inc. (http://www.givainc.com/labs/) 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * 	http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Date: 2009-02-10
 * Rev:  1.2.06
 */
;(function($){
	// set the version of the link select
	$.linkselect = {version: "1.2.06"};
	
	$.fn.linkselect = function(options) {
		var method = typeof arguments[0] == "string" && arguments[0];
		var args = method && Array.prototype.slice.call(arguments, 1) || arguments;

		// if a method is supplied, execute it for non-empty results
		if( method && this.length ){
			// get a reference to the first linkselect found
			var self = $.data(this[0], "linkselect");

			// if request a copy of the object, return it			
			if( method.toLowerCase() == "object" ) return self;
			// if method is defined, run it and return either it's results or the chain
			else if( self[method] ){
				// define a result variable to return to the jQuery chain
				var result;
				this.each(function (i){
					// apply the method to the current element
					var r = $.data(this, "linkselect")[method].apply(self, args);
					// if first iteration we need to check if we're done processing or need to add it to the jquery chain
					if( i == 0 && r ){
						// if this is a jQuery item, we need to store them in a collection
						if( !!r.jquery ){
							result = $([]).add(r);
						// otherwise, just store the result and stop executing
						} else {
							result = r;
							// since we're a non-jQuery item, just cancel processing further items
							return false;
						};
					// keep adding jQuery objects to the results
					} else if( !!r && !!r.jquery ){
						result = result.add(r);
					};
				});

				// return either the results (which could be a jQuery object) or the original chain
				return result || this;
			// everything else, return the chain
			} else return this;
		// initializing request
		} else {
			// create a new linkselect for each object found
			return this.each(function (){
				new $.LinkSelect(this, options);
			});
		};
	};

	$.LinkSelect = function (el, options){
		options = $.extend({}, $.LinkSelect.defaults, options);
		
		var self = this, select = el, $select = $(el), shortcuts = {}, disabled = false, current_char_pos = 0, last_char_code, is_open = false;
		
		// store the global properties
		this.id = $select.attr("id");
		
		// get/set the value of the field
		this.val = function (value, doCallback){
			// update the selected value
			if( arguments.length > 0 ){
				setSelectedItem(value, doCallback);
				return $a;
			} 
			else return $input.val();
		};

		// set the focus to the field		
		this.focus = function (){
			// place focus asynchronously to avoid click collisions
			setTimeout(function(){$a.focus();}, 1);
			return $a;
		};
		
		// set the blur to the field		
		this.blur = function (){
			// place focus asynchronously to avoid click collisions
			setTimeout(function(){$a.blur();}, 1);
			return $a;
		};
		
		// place focus and open the menu
		this.open = function (callback, bDoFocus){
			// if disabled, skip processing
			if( disabled ) return $a;
			// close any open linkselects
			$(document).triggerHandler("click.linkselect");
			// place focus
			if( bDoFocus !== false ) $a.trigger("focus");
			// show the options asynchronously to avoid click collisions
			setTimeout(function(){ showOptions(callback); }, 1);
			return $a;
		};
		
		// disable the link
		this.disable = function (status){
			disabled = status;
			// remove any existing disabled label
			$a.parent().find("span." + options.classDisabled).remove();
			// show/hide the anchor depending on the disabled status
			$a[disabled ? "hide" : "show"]();
			// if disabled, add a span			
			if( disabled ) $a.after('<span class="' + options.classDisabled + '">' + $a.html() + '</span>');
			return $a;
		};
		
		// replace the options
		this.replaceOptions = function (options, doCallback){
			// remove the current options
			$select.children('option').remove();

			// add each new item
			$.each(options, function (i){
				// create the new option
				var $option = $("<option/>").attr("value", this.value).html(this.text);
				// check to see if the option should be selected
				if( this.selected == true ) $option.attr("selected", "selected");
				// if any classes were specified, add them
				if( this.className ) $option.addClass(this.className);
				// add the new option to the array
				$option.appendTo($select);
			});
			
			// we need to repaint the dropdown so the widht/height all get recalculated based on the new properties
			repaint();
			// bind the new triggers
			bindItems();
			// update the selected value
			getSelectedItem().trigger("click.linkselect", [true, doCallback]);
		};
		
		var $html = createHtml();

		// insert the new html and remove the old stuff
		$select.after($html).remove();
		// get the hidden input field
		var $input = $html.filter("input");
		// get anchor
		var $a = $html.filter("a");
		// get container
		var $container = $html.filter("div");
		// get scrollable list
		var $scrollable = $html.find(".scrollable");
		// get the title
		var $title = $html.find(".title");
		// get the list
		var $ul = $container.find("ul");
		// track last event
		var lastCurrentEvent;
		
		// copy the class statements to the input field (this is so class based selectors still work)
		$input.addClass($select.attr("className"));
		
		// store a reference to this link select
		$.data($input[0], "linkselect", this);
		
		// move the container to the main body so it can be correctly positioned absolutely
		$container
			// add the container to the body (this is so we can correctly absolutely position it)
			.appendTo("body")
			// if user is moving the mouse, we want to make sure to trigger the mouseover event
			.bind("mousemove.linkselect", function (e){
				lastCurrentEvent = e;
			});
		
		// this function will bind the elements
		function bindItems(){
			$ul.find("li")
				.bind("mouseover.linkselect", function (e){
					// if we're moving via the keyboard, then kill processing
					if( lastCurrentEvent && lastCurrentEvent.type == "keydown" ) return;
					// highlight the current option
					setHighlightedItem($(this));
					lastCurrentEvent = e;
				})
				.bind("click.linkselect", function (e, nofocus, doCallback){
					// stop the default behavior
					e.preventDefault();
					// remove the selected class from the previous option
					var $previous = getSelectedItem().removeClass(options.classSelected);
					// get the currently selected item and remove the class
					var $current = $(this).addClass(options.classSelected);
					var value = $current.attr("rel") || "";
					var text = $current.find("." + options.classValue).html();
					// hide the container
					hideOptions(nofocus);

					// trigger the change callback if it's false, stop processing
					if( (doCallback !== false) && (($.isFunction(options.change) && (options.change.apply(self, [this, value, text, doCallback]) === false)) || ($.isFunction($select[0].onchange) && ($select[0].onchange.apply(self, [this, value, text, doCallback]) === false))) ){
						// restore the selected classes (since we're not selecting this option)
						$previous.addClass(options.classSelected);
						$current.removeClass(options.classSelected);
						return;
					};
					// update the hidden value
					$input.val(value);
					// update the text of the anchor and trigger the focus handler
					$a.html(text)[(nofocus !== true)?"trigger":"triggerHandler"]("focus", [nofocus]);
					// if the field is disabled, update the disabled label
					if( disabled ) $a.parent().find("span." + options.classDisabled).html(text);
					if($.isFunction(options.afterChange)){
						options.afterChange.apply(self, [this, value, text, doCallback]);
					};
				});
		};
		// bind events to the list items
		bindItems();
			
		$a.bind("click.linkselect", function(e){
			e.preventDefault();
			toggleOptions();
			// make sure the link has focus for IE6
			if( $.browser.msie ){
				setTimeout(function (){
					$a.trigger("focus.linkselect");
				}, 0);
			};
		})
		.bind("focus.linkselect", function (e, nofocus){
			// we need to make sure not to re-add the class for IE6 since we have to reset the focus
			if( !$container.is(":visible") && (nofocus !== true) ){
				$a.addClass(options.classLinkFocus);
			};
		})
		.bind("blur.linkselect", function (e){
			// if not coming from a live user event, then hide the options
			if( isJQueryEvent(e) ) hideOptions();
			$a.removeClass(options.classLinkFocus);
		})
		.bind(($.browser.safari ? "keydown" : "keypress" ) + ".linkselect", function(e, e2){
			// if we've passed a copy of an event object, use that instead
			if( !!e2 ) var e = e2;
			
			var key = e.keyCode || e.charCode, cur_char = String.fromCharCode(key).toLowerCase();

			switch(key) {
				case 38: // up
				case 40: // down
					e.preventDefault();
					moveSelect((key == 38) ? -1 : 1);
					lastCurrentEvent = e;
					break;
				case 13: // return
					e.preventDefault();
					// only select the item if the menu is visible
					if( $container.is(":visible") ){
						$container.find('li.' + options.classCurrent).trigger('click.linkselect');
					} else {
						$a.trigger('click.linkselect');
					};
					break;
				case 9: // tab
				case 27: // escape
					hideOptions();
				  break;
				case 35: // end
					e.preventDefault();
					moveLast();
					lastCurrentEvent = e;
				  break;
				case 36: // home
					e.preventDefault();
					moveFirst();
					lastCurrentEvent = e;
				  break;
				case 33: // page up
				case 34: // page down
					e.preventDefault();
					var isVisible = $container.is(":visible");
					// show the container so we can get heights
					if( !isVisible ) $container.show();
					var iItemsPerPage = parseInt($scrollable.height()/$ul.find("li:first").outerHeight(), 10);
					// now hide the container
					if( !isVisible ) $container.hide();
					// move up/down the total number of items visible
					moveSelect((key == 33) ? iItemsPerPage * -1 : iItemsPerPage);
				  break;
			};
			
			// if we're pressed a different key, then restart the array position
			if( cur_char != last_char_code ) current_char_pos = 0;
			// store the current character
			last_char_code = cur_char;
			
			// check to see if there's a keyboard shortcut configured for the key press
			if( typeof shortcuts[cur_char] != "undefined" ){
				// if we're outside the bounds of the array, go back to zero
				if( current_char_pos >= shortcuts[cur_char].length ) current_char_pos = 0;

				// if there is, trigger the click event
				$ul.find('#' + self.id + '_li_' + shortcuts[cur_char][current_char_pos]).trigger("click.linkselect");
				e.preventDefault();
				e.stopPropagation();

				// increase the array position
				current_char_pos++;
			};
		});

		// IE6 doesn't register certain keypress events, so we must catch them during the keydown event
		if( $.browser.msie ) $a.bind("keydown.linkselect", function (e){
			// check to see if a key was pressed that IE6 doesn't trigger a keypress event for
			if( ",8,9,33,34,35,36,37,38,39,40,".indexOf("," + e.keyCode + ",") > -1 ) return $(this).triggerHandler("keypress.linkselect", [e]);
		});

		// we need to close the menu if we don't click on it
		$(document).bind("click.linkselect", function (e){
			if( (e.target !== $a[0]) && (e.target !== $scrollable[0]) && $container.is(":visible") ){
				hideOptions();
				// make sure we remove the focus class
				$a.removeClass(options.classLinkFocus);
			};
		});
		
		// move the layer on a resize
		$(window).resize(function (){
			if( is_open )
				anchorTo($a, $container, true);
		});

		// create the replacement html
		function createHtml(){
			var id = self.id;
			var title = $select.attr("title");
			// get the selected text
			var text = select.selectedIndex == -1 ? "" : select[select.selectedIndex].text;
			var value = select.selectedIndex == -1 ? "" : select[select.selectedIndex][($.browser.msie && $.browser.version <= 7 && !(select[select.selectedIndex].attributes['value'].specified)) ? "text" : "value"];
			// get the current tab index and make sure to copy it
			var tabindex = $select.attr("tabindex");
			
			var aHtml = [
				'<a href="#' + self.id + '" id="' + self.id + '_link" class="' + options.classLink + '"' + (tabindex ? ' tabindex="' + tabindex + '"' : '') + '>' + text + '</a>'
				, '<input type="hidden" name="' + self.id + '" id="' + self.id + '" value="' + value + '" />'
				, '<div class="' + options.classContainer + '">'
					, (title) ? '<div class="title"><span>' + title + '</span></div>' : ''
					, '<div class="scrollable"><ul id="' + self.id + '_list">'
					, generateOptions($select.children('option'))
					, '</ul></div>'
				, '</div>'
			];

			// generate and return the new HTML			
			return $(aHtml.join(""));
		};
		
		function generateOptions($options){
			// purge the shortcut list
			shortcuts = [];
			// an array to store the <li/> tags we're creating
			var lis = [];
			$options.each(function(i){
				var $option = $(this);
				var bSelected = $option.is(":selected");
				var label = $.trim($option.text());
				var html = '<span class="' + options.classValue + '">' + label + '</span>';
				var value = $.browser.msie && $.browser.version <= 7 && !(this.attributes['value'].specified) ? this.text : this.value;
				
				// if a special format renderer has been specified, use it (will use original HTML if format function returns false or undefined)
				if( $.isFunction(options.format) ) html = options.format.apply(self, [html, value, label, i, $option, options]) || html;
				
				var first_char = (label.length > 1) ? label.substring(0, 1).toLowerCase() : "";
				
				// create an array of shortcut keys
				if( !shortcuts[first_char] ) shortcuts[first_char] = [];
				// push the position into the array
				shortcuts[first_char].push(i);
				
				// get the current class statement				
				var cn = $.trim(this.className + ' ' + (bSelected ? options.classSelected : ''));
				
				lis.push('<li id="' + self.id + '_li_' + i + '" rel="' + value + (cn.length > 0 ? '" class="' + cn : '') + '">' + html + '</li>');
			});
			
			return lis.join("");
		};
		
		function repaint(){
			// make sure we re-init the menu width on first show
			bFixedWidth = false;
			// clear styles that will effect recalculating the width of the drop down
			$container[0].style.width = "";
			$title[0].style.width = "";
			$title.css("float", "");
			
			// re-generate get the html making up all the new options and update the cache
			$ul.html(generateOptions($select.children('option')));
		};;

		// set the currently selected item
		function setSelectedItem(value, doCallback){
			// look for the currently selected item
			var $selected = $ul.find("li[rel=" + value + "]");
			
			// if nothing is selected, get the first item
			if( $selected.length == 0 ) $selected = $ul.find("li:eq(0)");

			// return the selected item			
			return $selected.trigger("click.linkselect", [true, doCallback]);
		};

		// get the currently selected item
		function getSelectedItem(){
			// look for the currently selected item
			var $selected = $ul.find("li.selected");

			// if nothing is selected, get the first item
			if( $selected.length == 0 ) $selected = $ul.find("li:eq(0)");

			// return the selected item			
			return $selected;
		};
		
		// get the currently selected item
		function getHighlightedItem(){
			// look for the currently selected item
			var $selected = $ul.find("li.current");

			// if nothing is selected, get the first item
			if( $selected.length == 0 ) $selected = getSelectedItem();

			// return the selected item			
			return $selected;
		};
		
		function setHighlightedItem($el){
			// remove the currently selected item
			$container.find(".current").removeClass(options.classCurrent);
			// highlight the current row
			$el.addClass(options.classCurrent);
			return $el;
		};

		// move the selected item
		function moveSelect(step){
			// get the currently selected item
			var $current = getHighlightedItem();
			var pos = parseInt($current.attr("id").replace(/(.+)(_(\d+$))/gi, "$3"), 10);

			moveTo(pos + step);
		};

		// move the selected item
		function moveTo(pos){
			var $li = $("li", $container), $next;
			// if the options are empty, cancel request
			if( !$li || $li.length == 0 ) return false;
			
			// get the currently selected item
			var $current = getHighlightedItem().removeClass(options.classCurrent);

			// don't go lower than first item	
			if( isNaN(pos) || pos < 0 ){
				$next = $li.eq(0);
			// if greater than last position	
			} else if( pos > $li.length - 1 ){
				$next = $li.eq($li.length - 1);
			// get the first item
			} else {
				$next = $li.eq(pos);
			};
			
			// if the container is open
			if( $container.is(":visible") ){
				// change highlighted option
				$next.addClass(options.classCurrent);
				// make sure the item is in the viewable area
				scrollIntoView($next);
			} else {
				// only trigger the click if we've moved positions
				if( $current[0] !== $next[0] ) $next.trigger("click.linkselect");
			};
		};
		
		function moveFirst(){
			moveTo(0);
		};

		function moveLast(){
			moveTo($select.children('option').length-1);
		};

		function scrollIntoView($el, center){
			var el = $el[0];
			var scrollable = $scrollable[0];
			// get the padding which is need to adjust the scrollTop
			var s = {pTop: parseInt($scrollable.css("paddingTop"), 10)||0, pBottom: parseInt($scrollable.css("paddingBottom"), 10)||0, bTop: parseInt($scrollable.css("borderTopWidth"), 10)||0, bBottom: parseInt($scrollable.css("borderBottomWidth"), 10)||0};
	
			// scrolling down
			if( (el.offsetTop + el.offsetHeight) > (scrollable.scrollTop + scrollable.clientHeight) ){
				scrollable.scrollTop = $el.offset().top + (scrollable.scrollTop - $scrollable.offset().top) - ((scrollable.clientHeight/((center == true) ? 2 : 1)) - ($el.outerHeight() + s.pBottom));
			// scrolling up
			} else if( el.offsetTop - s.bTop - s.bBottom <= (scrollable.scrollTop + s.pTop + s.pBottom) ){
				scrollable.scrollTop = $el.offset().top + (scrollable.scrollTop - $scrollable.offset().top) - s.pTop;
			};
		};
	
		function toggleOptions(){
			if( $container.is(":visible") ) hideOptions();
			else showOptions();
		};
		
		var bFixedWidth = false;
		function showOptions(callback){
			// get the currently selected item
			var $selected = getSelectedItem();
			// add the a class to the anchor showing we're open
			$a.removeClass(options.classLinkFocus).addClass(options.classLinkOpen);
			// display the options
			$container.show();
			// fix the width of the container
			if( !bFixedWidth ){
				// get the width of the anchor link unless inline, then grab width of parent
				var aw = ($a.css("display").indexOf("inline") > -1) ? $a.parent().outerWidth() : $a.outerWidth();
				// get the original width of the container
				var width = options.fixedWidth ? aw : $container.width();
				// make sure the width of the drop down is at least as wide as the link
				if( width < aw ) width = aw;
				
				// get the list element
				var maxHeight = parseInt($scrollable.css("max-height"), 10);

				// if IE6, we need to apply max-width/max-height rules (which are not support in IE)
				if( $.browser.msie && $.browser.version <= 6 ){
					if( (maxHeight > 0) && ($scrollable.height() > maxHeight) ) $scrollable.height(maxHeight);
				};
				
				// if scrolling list, adjust the width for the scrollbars
				if( $ul.height() > maxHeight ) width += 25;

				// make sure the width of everything isn't greater than the max-width CSS property
				var maxWidth = parseInt("0" + $container.css("max-width"), 10);
				if( (maxWidth > 0) && (width > maxWidth) ) width = aw = maxWidth;
				
				// adjust the width of the dropdown
				$container.width(width);

				// webkit has a bug with detecting "max-width", so we must double check after setting the container width
				if( $.browser.safari ){
					var cw = $container.width();
					if( aw > cw ) width = aw = cw;
				};
				
				// make the title bar the width of the anchor
				$title.width(aw);

				// adjust the width for any padding in the title bar				
				if( $title.outerWidth() > aw ) $title.width(aw - ($title.outerWidth()-aw));

				// check to see if we should right-align the title
				if( options.titleAlign.toLowerCase() == "right" && !options.fixedWidth ) $title.css("float", "right");

				// mark that we've fixed the width
				bFixedWidth = true;
			};
			// anchor the options to the link
			anchorTo($a, $container, true);
			// if the bgIframe exists, use the plug-in
			if( !!$.fn.bgIframe ) $container.bgIframe();
			// scroll the selected item into view
			scrollIntoView($selected, true);
			// highlight the current option
			setHighlightedItem($selected);
			// run the open callback
			if( $.isFunction(options.open) ) options.open.apply(this, [$container, $a, $selected, $title]);
			// run any manual callback
			if( $.isFunction(callback) ) callback.apply(this, [$container, $a, $selected, $title]);
			is_open = true;
		};

		function hideOptions(nofocus){
			// tell the anchor we're no longer open
			if( nofocus !== true ) $a.addClass(options.classLinkFocus).removeClass(options.classLinkOpen);
			$container.hide();
			if( $.isFunction(options.close) ) options.close.apply(this, [$container, $a, $selected, $title]);
			is_open = false;
		};

		function position($el){
			var bHidden = false;
			// if the element is hidden we must make it visible to the DOM to get
			if ($el.is(":hidden")) {
				bHidden = !!$el.css("visibility", "hidden").show();
			};
			
			// use offset to get the actual viewport position of the element (and not it's relative position)
			var pos = $.extend($el.offset(),{
				  width: $el.outerWidth()
				, height: $el.outerHeight()
				, marginLeft: parseInt($.curCSS($el[0], "marginLeft", true), 10) || 0
				, marginRight: parseInt($.curCSS($el[0], "marginRight", true), 10) || 0
				, marginTop: parseInt($.curCSS($el[0], "marginTop", true), 10) || 0
				, marginBottom: parseInt($.curCSS($el[0], "marginBottom", true), 10) || 0
			});
			if( pos.marginTop < 0 ) pos.top += pos.marginTop;
			if( pos.marginLeft < 0 ) pos.left += pos.marginLeft;
			
			pos["bottom"] = pos.top + pos.height;
			pos["right"] = pos.left + pos.width;
			
			// hide the element again
			if( bHidden ) $el.hide().css("visibility", "visible");
	
			return pos;
		};
		
		function anchorTo($anchor, $target){
			var pos = position($anchor);
			// get the screen dimensions
			var sd = getScreenDimensions();

			// get the far right edge of the option container
			var farRight = $container.outerWidth() + pos.left;
			
			// if we're going to be off the screen, adjust the position
			if( farRight > sd.x ){
				// adjust to the left by subtracting the list width and then adding the width of the title (which will cover up the anchor text)
				pos.left = (pos.left - $container.outerWidth()) + $title.outerWidth();
			} else {
				// since the container isn't offscreen, see if we need to expand the width of the title bar
				var cow = $container.outerWidth(), tow = $title.outerWidth();
				// expand the title bar to the width of the container, subtracting the difference in padding
				if( cow > tow ) $title.width(cow - (tow - $title.width()));
			};

			$target.css({
				  position: "absolute"
				, top: pos[options.yAxis]
				, left: pos.left
			});
			
			return pos.bottom;
		};

		function getScreenDimensions(){
			var d = {
				  scrollLeft: $(window).scrollLeft()
				, scrollTop:  $(window).scrollTop()
				, width:      $("body").width()     // changed from innerWidth
				, height:     $("body").height()    // changed from innerHeight			
			};
			
			// calculate the correct x/y positions
			d.x = d.scrollLeft + d.width;
			d.y = d.scrollTop + d.height;
			
			return d;
		};
		
		function isJQueryEvent(e){
			return !("bubbles" in e || "cancelBubble" in e);
		};
		
		// invoke the init callback
		if( $.isFunction(options.init) ) options.init.apply(this, [$select, $input, $a, $container, $scrollable, $title, $ul]);
	};

	$.LinkSelect.defaults = {
		  classLink: "linkselectLink"             // the class to use for the anchor tag
		, classLinkOpen: "linkselectLinkOpen"     // the anchor's class when the dropdown is shown
		, classLinkFocus: "linkselectLinkFocus"   // the anchor's class when it has focus
		, classContainer: "linkselectContainer"   // the class to the container that holds the options
		, classSelected: "selected"               // the class of the currently selected item
		, classCurrent: "current"                 // the class of the highlighted item
		, classDisabled: "linkselectDisabled"     // the class used on the text when the linkselect is disabled
		, classValue: "linkselectValue"           // the class used for each item in the dropdown
		, yAxis: "top"                            // the position of the dropdown relative to the link (can be either "top" or "bottom")
		, titleAlign: "right"                     // location of dropdown's title bar if dropdown is on right edge of the screen (can be either "right" or "left")
		, fixedWidth: false                       // false = dropdown sizes to width of options, true = dropdown uses width of link
		, init: null                              // callback that occurs when a linkselect menu is initialized
		, change: null                            // callback that occurs when an option is selected
		, format: null                            // callback that occurs when rendering the HTML to use for an item in the dropdown
		, open: null                              // callback that occurs when the menu is opened
		, close: null                             // callback that occurs when the menu is closed
		, afterChange: null
	};

})(jQuery);
/**
 * jGrowl 1.1.2
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Written by Stan Lemon <stanlemon@mac.com>
 * Last updated: 2008.08.17
 *
 * jGrowl is a jQuery plugin implementing unobtrusive userland notifications.  These 
 * notifications function similarly to the Growl Framework available for
 * Mac OS X (http://growl.info).
 *
 * To Do:
 * - Move library settings to containers and allow them to be changed per container
 *
 * Changes in 1.1.2
 * - Added iPhone styled example
 * - Fixed possible IE7 bug when determining if the ie6 class shoudl be applied.
 * - Added template for the close button, so that it's content could be customized.
 *
 * Changes in 1.1.1
 * - Fixed CSS styling bug for ie6 caused by a mispelling
 * - Changes height restriction on default notifications to min-height
 * - Added skinned examples using a variety of images
 * - Added the ability to customize the content of the [close all] box
 * - Added jTweet, an example of using jGrowl + Twitter
 *
 * Changes in 1.1.0
 * - Multiple container and instances.
 * - Standard $.jGrowl() now wraps $.fn.jGrowl() by first establishing a generic jGrowl container.
 * - Instance methods of a jGrowl container can be called by $.fn.jGrowl(methodName)
 * - Added glue preferenced, which allows notifications to be inserted before or after nodes in the container
 * - Added new log callback which is called before anything is done for the notification
 * - Corner's attribute are now applied on an individual notification basis.
 *
 * Changes in 1.0.4
 * - Various CSS fixes so that jGrowl renders correctly in IE6.
 *
 * Changes in 1.0.3
 * - Fixed bug with options persisting across notifications
 * - Fixed theme application bug
 * - Simplified some selectors and manipulations.
 * - Added beforeOpen and beforeClose callbacks
 * - Reorganized some lines of code to be more readable
 * - Removed unnecessary this.defaults context
 * - If corners plugin is present, it's now customizable.
 * - Customizable open animation.
 * - Customizable close animation.
 * - Customizable animation easing.
 * - Added customizable positioning (top-left, top-right, bottom-left, bottom-right, center)
 *
 * Changes in 1.0.2
 * - All CSS styling is now external.
 * - Added a theme parameter which specifies a secondary class for styling, such
 *   that notifications can be customized in appearance on a per message basis.
 * - Notification life span is now customizable on a per message basis.
 * - Added the ability to disable the global closer, enabled by default.
 * - Added callbacks for when a notification is opened or closed.
 * - Added callback for the global closer.
 * - Customizable animation speed.
 * - jGrowl now set itself up and tears itself down.
 *
 * Changes in 1.0.1:
 * - Removed dependency on metadata plugin in favor of .data()
 * - Namespaced all events
 */
(function($) {

	/** jGrowl Wrapper - Establish a base jGrowl Container for compatibility with older releases. **/
	$.jGrowl = function( m , o ) {
		// To maintain compatibility with older version that only supported one instance we'll create the base container.
		if ( $('#jGrowl').size() == 0 ) $('<div id="jGrowl"></div>').addClass($.jGrowl.defaults.position).appendTo('body');
		// Create a notification on the container.
		$('#jGrowl').jGrowl(m,o);
	};


	/** Raise jGrowl Notification on a jGrowl Container **/
	$.fn.jGrowl = function( m , o ) {
		if ( $.isFunction(this.each) ) {
			var args = arguments;

			return this.each(function() {
				var self = this;

				/** Create a jGrowl Instance on the Container if it does not exist **/
				if ( $(this).data('jGrowl.instance') == undefined ) {
					$(this).data('jGrowl.instance', new $.fn.jGrowl());
					$(this).data('jGrowl.instance').startup( this );
				}

				/** Optionally call jGrowl instance methods, or just raise a normal notification **/
				if ( $.isFunction($(this).data('jGrowl.instance')[m]) ) {
					$(this).data('jGrowl.instance')[m].apply( $(this).data('jGrowl.instance') , $.makeArray(args).slice(1) );
				} else {
					$(this).data('jGrowl.instance').notification( m , o );
				}
			});
		};
	};

	$.extend( $.fn.jGrowl.prototype , {

		/** Default JGrowl Settings **/
		defaults: {
			header: 		'',
			sticky: 		false,
			position: 		'top-right', // Is this still needed?
			glue: 			'after',
			theme: 			'default',
			corners: 		'10px',
			check: 			500,
			life: 			3000,
			speed: 			'normal',
			easing: 		'swing',
			closer: 		true,
			closeTemplate: '&times;',
			closerTemplate: '<div>[ close all ]</div>',
			log: 			function(e,m,o) {},
			beforeOpen: 	function(e,m,o) {},
			open: 			function(e,m,o) {},
			beforeClose: 	function(e,m,o) {},
			close: 			function(e,m,o) {},
			animateOpen: 	{
				opacity: 	'show'
			},
			animateClose: 	{
				opacity: 	'hide'
			}
		},
		
		/** jGrowl Container Node **/
		element: 	null,
	
		/** Interval Function **/
		interval:   null,
		
		/** Create a Notification **/
		notification: 	function( message , o ) {
			var self = this;
			var o = $.extend({}, this.defaults, o);

			o.log.apply( this.element , [this.element,message,o] );

			var notification = $('<div class="jGrowl-notification"><div class="close">' + o.closeTemplate + '</div><div class="header">' + o.header + '</div><div class="message">' + message + '</div></div>')
				.data("jGrowl", o).addClass(o.theme).children('div.close').bind("click.jGrowl", function() {
					$(this).unbind('click.jGrowl').parent().trigger('jGrowl.beforeClose').animate(o.animateClose, o.speed, o.easing, function() {
						$(this).trigger('jGrowl.close').remove();
					});
				}).parent();
				
			( o.glue == 'after' ) ? $('div.jGrowl-notification:last', this.element).after(notification) : $('div.jGrowl-notification:first', this.element).before(notification);

			/** Notification Actions **/
			$(notification).bind("mouseover.jGrowl", function() {
				$(this).data("jGrowl").pause = true;
			}).bind("mouseout.jGrowl", function() {
				$(this).data("jGrowl").pause = false;
			}).bind('jGrowl.beforeOpen', function() {
				o.beforeOpen.apply( self.element , [self.element,message,o] );
			}).bind('jGrowl.open', function() {
				o.open.apply( self.element , [self.element,message,o] );
			}).bind('jGrowl.beforeClose', function() {
				o.beforeClose.apply( self.element , [self.element,message,o] );
			}).bind('jGrowl.close', function() {
				o.close.apply( self.element , [self.element,message,o] );
			}).trigger('jGrowl.beforeOpen').animate(o.animateOpen, o.speed, o.easing, function() {
				$(this).data("jGrowl").created = new Date();
			}).trigger('jGrowl.open');
		
			/** Optional Corners Plugin **/
			if ( $.fn.corner != undefined ) $(notification).corner( o.corners );

			/** Add a Global Closer if more than one notification exists **/
			if ( $('div.jGrowl-notification:parent', this.element).size() > 1 && $('div.jGrowl-closer', this.element).size() == 0 && this.defaults.closer != false ) {
				$(this.defaults.closerTemplate).addClass('jGrowl-closer').addClass(this.defaults.theme).appendTo(this.element).animate(this.defaults.animateOpen, this.defaults.speed, this.defaults.easing).bind("click.jGrowl", function() {
					$(this).siblings().children('div.close').trigger("click.jGrowl");

					if ( $.isFunction( self.defaults.closer ) ) self.defaults.closer.apply( $(this).parent()[0] , [$(this).parent()[0]] );
				});
			};
		},

		/** Update the jGrowl Container, removing old jGrowl notifications **/
		update:	 function() {
			$(this.element).find('div.jGrowl-notification:parent').each( function() {
				if ( $(this).data("jGrowl") != undefined && $(this).data("jGrowl").created != undefined && ($(this).data("jGrowl").created.getTime() + $(this).data("jGrowl").life)  < (new Date()).getTime() && $(this).data("jGrowl").sticky != true && 
					 ($(this).data("jGrowl").pause == undefined || $(this).data("jGrowl").pause != true) ) {
					$(this).children('div.close').trigger('click.jGrowl');
				}
			});

			if ( $(this.element).find('div.jGrowl-notification:parent').size() < 2 ) {
				$(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose, this.defaults.speed, this.defaults.easing, function() {
					$(this).remove();
				});
			};
		},

		/** Setup the jGrowl Notification Container **/
		startup:	function(e) {
			this.element = $(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>');
			this.interval = setInterval( function() { jQuery(e).data('jGrowl.instance').update(); }, this.defaults.check);
			
			if ($.browser.msie && parseInt($.browser.version) < 7 && !window["XMLHttpRequest"]) $(this.element).addClass('ie6');
		},

		/** Shutdown jGrowl, removing it and clearing the interval **/
		shutdown:   function() {
			$(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove();
			clearInterval( this.interval );
		}
	});
	
	/** Reference the Defaults Object for compatibility with older versions of jGrowl **/
	$.jGrowl.defaults = $.fn.jGrowl.prototype.defaults;

})(jQuery);/*
 * UPDATED: 25.09.08
 *
 * jqTransform
 * by mathieu vilaplana mvilaplana@dfc-e.com
 * Designer ghyslain armand garmand@dfc-e.com
 *
 *
 * Version 1.0
 *
 ******************************************** */
 
(function($){
	var defaultOptions = {preloadImg:true};
	var jqTransformImgPreloaded = false;

	var jqTransformPreloadHoverFocusImg = function(strImgUrl) {
		//guillemets to remove for ie
		strImgUrl = strImgUrl.replace(/^url\((.*)\)/,'$1').replace(/^\"(.*)\"$/,'$1');
		var imgHover = new Image();
		imgHover.src = strImgUrl.replace(/\.([a-zA-Z]*)$/,'-hover.$1');
		var imgFocus = new Image();
		imgFocus.src = strImgUrl.replace(/\.([a-zA-Z]*)$/,'-focus.$1');				
	};

	
	/***************************
	  Labels
	***************************/
	var jqTransformGetLabel = function(objfield){
		var selfForm = $(objfield.get(0).form);
		var oLabel = objfield.next();
		if(!oLabel.is('label')) {
			oLabel = objfield.prev();
			if(oLabel.is('label')){
				var inputname = objfield.attr('id');
				if(inputname){
					oLabel = selfForm.find('label[for="'+inputname+'"]');
				} 
			}
		}
		if(oLabel.is('label')){return oLabel.css('cursor','pointer');}
		return false;
	};
	
	/* Hide all open selects */
	var jqTransformHideSelect = function(oTarget){
		var ulVisible = $('.jqTransformSelectWrapper ul:visible');
		ulVisible.each(function(){
			var $select = $(this).parents(".jqTransformSelectWrapper:first").find("select").get(0);
			//do not hide if clicke on the label object associated to the select
			if( !(oTarget && $select.oLabel && $select.oLabel.get(0) == oTarget.get(0)) ){$(this).hide();}
		});
	};
	/* Check for an external click */
	var jqTransformCheckExternalClick = function(event) {
		if ($(event.target).parents('.jqTransformSelectWrapper').length === 0) { jqTransformHideSelect($(event.target)); }
	};

	/* Apply document listener */
	var jqTransformAddDocumentListener = function (){
		$(document).mousedown(jqTransformCheckExternalClick);
	};	
			
	/* Add a new handler for the reset action */
	var jqTransformReset = function(f){
		var sel;
		$('.jqTransformSelectWrapper select', f).each(function(){sel = (this.selectedIndex<0) ? 0 : this.selectedIndex; $('ul', $(this).parent()).each(function(){$('a:eq('+ sel +')', this).click();});});
		$('a.jqTransformCheckbox, a.jqTransformRadio', f).removeClass('jqTransformChecked');
		$('input:checkbox, input:radio', f).each(function(){if(this.checked){$('a', $(this).parent()).addClass('jqTransformChecked');}});
	};

	/***************************
	  Buttons
	 ***************************/
	$.fn.jqTransInputButton = function(){
		return this.each(function(){
			$(this).replaceWith('<button id="'+ this.id +'" name="'+ this.name +'" type="'+ this.type +'" class="'+ this.className +' jqTransformButton"><span><span>'+ $(this).attr('value') +'</span></span>');
		});
	};
	
	/***************************
	  Text Fields 
	 ***************************/
	$.fn.jqTransInputText = function(){
		return this.each(function(){
			var safari = $.browser.safari; /* We need to check for safari to fix the input:text problem */
			var $input = $(this);
	
			if($input.hasClass('jqtranformdone') || !$input.is('input')) {return;}
			$input.addClass('jqtranformdone');
	
			var oLabel = jqTransformGetLabel($(this));
			oLabel && oLabel.bind('click',function(){$input.focus();});
	
			var inputSize=$input.width();
			/*if($input.attr('size')){
				inputSize = $input.attr('size')*10;
				$input.css('width',inputSize);
			}*/
			
			$input.addClass("jqTransformInput").wrap('<div class="jqTransformInputWrapper"><div class="jqTransformInputInner"><div></div></div></div>');
			var $wrapper = $input.parent().parent().parent();
			$wrapper.css("width", '100%');
			$input
				.focus(function(){$wrapper.addClass("jqTransformInputWrapper_focus");})
				.blur(function(){$wrapper.removeClass("jqTransformInputWrapper_focus");})
				.hover(function(){$wrapper.addClass("jqTransformInputWrapper_hover");},function(){$wrapper.removeClass("jqTransformInputWrapper_hover");})
			;
	
			/* If this is safari we need to add an extra class */
			safari && $wrapper.addClass('jqTransformSafari');
			safari && $input.css('width',$wrapper.width()+16);
			this.wrapper = $wrapper;
			
		});
	};
	
	/***************************
	  Check Boxes 
	 ***************************/	
	$.fn.jqTransCheckBox = function(){
		return this.each(function(){
			var $input = $(this);
			var inputSelf = this;
			
			if($input.hasClass('jqTransformHidden')) {return;}
	
			var oLabel=jqTransformGetLabel($input);
			$input.addClass('jqTransformHidden').wrap('<span class="jqTransformCheckboxWrapper"></span>');
			var $wrapper = $input.parent();
			var aLink = $('<a href="#" class="jqTransformCheckbox"></a>');
			$wrapper.prepend(aLink);
			// Click Handler
			aLink.click(function(){
					var $a = $(this);
					if (inputSelf.checked == true ){
						inputSelf.checked = false;
						$a.removeClass('jqTransformChecked');
					}
					else {
						inputSelf.checked = true;
						$a.addClass('jqTransformChecked');
					}
					
					inputSelf.onchange && inputSelf.onchange();
					return false;
			});
			oLabel && oLabel.click(function(){aLink.trigger('click'); return false;});
			// set the default state
			this.checked && aLink.addClass('jqTransformChecked');		
		});
	};
	/***************************
	  Radio Buttons 
	 ***************************/	
	$.fn.jqTransRadio = function(){
		return this.each(function(){
			var $input = $(this);
			var inputSelf = this;
				
			if($input.hasClass('jqTransformHidden')) {return;}
	
			oLabel = jqTransformGetLabel($input);
			$input.addClass('jqTransformHidden').wrap('<span class="jqTransformRadioWrapper"></span>');
			var $wrapper = $input.parent();
			var aLink = $('<a href="#" class="jqTransformRadio" rel="'+ this.name +'"></a>');
			$wrapper.prepend(aLink);
			// Click Handler
			aLink
				.each(function(){
					this.radioElem = inputSelf;
					$(this).click(function(){
						var $a = $(this).addClass('jqTransformChecked');
						inputSelf.checked = true;

						// uncheck all others of same name
						$('a.jqTransformRadio[rel="'+ $a.attr('rel') +'"]',inputSelf.form).not($a).each(function(){
							$(this).removeClass('jqTransformChecked');
							this.radioElem.checked = false;
						});
						
						inputSelf.onchange && inputSelf.onchange();
						return false;					
					});
				});
			oLabel && oLabel.click(function(){aLink.trigger('click');return false;});
			// set the default state
			inputSelf.checked && aLink.addClass('jqTransformChecked');
		});
	};
	
	/***************************
	  TextArea 
	 ***************************/	
	$.fn.jqTransTextarea = function(){
		return this.each(function(){
			var textarea = $(this);
	
			if(textarea.hasClass('jqtransformdone')) {return;}
			textarea.addClass('jqtransformdone');
			
	
			oLabel = jqTransformGetLabel(textarea);
			oLabel && oLabel.click(function(){textarea.focus();});
			
			var strTable = '<table cellspacing="0" cellpadding="0" border="0" class="jqTransformTextarea">';
			strTable +='<tr><td id="jqTransformTextarea-tl">&nbsp;</td><td id="jqTransformTextarea-tm">&nbsp;</td><td id="jqTransformTextarea-tr">&nbsp;</td></tr>';
			strTable +='<tr><td id="jqTransformTextarea-ml">&nbsp;</td><td id="jqTransformTextarea-mm"><div></div></td><td id="jqTransformTextarea-mr">&nbsp;</td></tr>';	
			strTable +='<tr><td id="jqTransformTextarea-bl">&nbsp;</td><td id="jqTransformTextarea-bm">&nbsp;</td><td id="jqTransformTextarea-br">&nbsp;</td></tr>';
			strTable +='</table>';					
			var oTable = $(strTable)
					.insertAfter(textarea)
					.hover(function(){
						!oTable.hasClass('jqTransformTextarea-focus') && oTable.addClass('jqTransformTextarea-hover');
					},function(){
						oTable.removeClass('jqTransformTextarea-hover');					
					})
				;
				
			textarea
				.focus(function(){oTable.removeClass('jqTransformTextarea-hover').addClass('jqTransformTextarea-focus');})
				.blur(function(){oTable.removeClass('jqTransformTextarea-focus');})
				.appendTo($('#jqTransformTextarea-mm div',oTable))
			;
			var newWidth = (oTable.width() - 10);
			$('#jqTransformTextarea-mm',oTable)
				.css('width', newWidth+'px')
			;
			textarea.css('width', newWidth+'px');
			this.oTable = oTable;
			if($.browser.safari){
				$('#jqTransformTextarea-mm',oTable)
					.addClass('jqTransformSafariTextarea')
					.find('div')
						.css('height',textarea.height())
						.css('width',textarea.width())
				;
			}
		});
	};
	
	/***************************
	  Select 
	 ***************************/	
	$.fn.jqTransSelect = function(){
		return this.each(function(index){
			var $select = $(this);
			$select.css('width', '100%');
			if($select.hasClass('jqTransformHidden')) {return;}
	
			var oLabel  =  jqTransformGetLabel($select);
			/* First thing we do is Wrap it */
			$select
				.addClass('jqTransformHidden')
				.wrap('<div class="jqTransformSelectWrapper" style="width: 100%"></div>')
			;
			var $wrapper = $select.parent().css({zIndex: 10-index});
			
			/* Now add the html for the select */
			$wrapper.prepend('<div><span></span><a href="#" class="jqTransformSelectOpen"></a></div><ul></ul>');
			var $ul = $('ul', $wrapper).css('width',"100%");
			/* Now we add the options */
			$('option', this).each(function(i){
				var oLi = $('<li><a href="#" index="'+ i +'">'+ $(this).html() +'</a></li>');
				$ul.append(oLi);
			});
			/* Hide the ul and add click handler to the a */
			$ul.hide().find('a').click(function(){
					$('a.selected', $wrapper).removeClass('selected');
					$(this).addClass('selected');	
					/* Fire the onchange event */
					if ($select[0].selectedIndex != $(this).attr('index') && $select[0].onchange) { $select[0].selectedIndex = $(this).attr('index'); $select[0].onchange(); }
					$select[0].selectedIndex = $(this).attr('index');
					$('span:eq(0)', $wrapper).html($(this).html());
					$ul.hide();
					return false;
			});
			/* Set the default */
			$('a:eq('+ this.selectedIndex +')', $ul).click();
			$('span:first', $wrapper).click(function(){$("a.jqTransformSelectOpen",$wrapper).trigger('click');});
			oLabel && oLabel.click(function(){$("a.jqTransformSelectOpen",$wrapper).trigger('click');});
			this.oLabel = oLabel;
			
			/* Apply the click handler to the Open */
			var oLinkOpen = $('a.jqTransformSelectOpen', $wrapper)
				.click(function(){
					//Check if box is already open to still allow toggle, but close all other selects
					if( $ul.css('display')=='none' ) {jqTransformHideSelect();} 
					$ul.slideToggle('normal', function(){					
						var offSet = ($('a.selected', $ul).offset().top - $ul.offset().top);
						$ul.animate({scrollTop: offSet});
					});
					return false;
				})
			;
			//set the new width
			var iSelectWidth = $select.width();
			var oSpan = $('span:first',$wrapper);
			var newWidth = (iSelectWidth > oSpan.innerWidth())?iSelectWidth+oLinkOpen.outerWidth():$wrapper.width();
			//$wrapper.css('width',newWidth);
			//$ul.css('width',newWidth-2);
			oSpan.css('width',"100%");
			
		});
	};
	$.fn.jqTransform = function(options){
		var self = this;
		var safari = $.browser.safari; /* We need to check for safari to fix the input:text problem */
		var opt = $.extend({},defaultOptions,options);
		
		/* each form */
		 return this.each(function(){
			var selfForm = $(this);
			if(selfForm.hasClass('jqtransformdone')) {return;}
			selfForm.addClass('jqtransformdone');
			
			$('input:submit, input:reset, input[type="button"]', this).jqTransInputButton();			
			$('input:text, input:password', this).jqTransInputText();			
			$('input:checkbox', this).jqTransCheckBox();
			$('input:radio', this).jqTransRadio();
			$('textarea', this).jqTransTextarea();
			
			if( $('select', this).jqTransSelect().length > 0 ){jqTransformAddDocumentListener();}
			selfForm.bind('reset',function(){var action = function(){jqTransformReset(this);}; window.setTimeout(action, 10);});
			
			//preloading
			if(opt.preloadImg && !jqTransformImgPreloaded){
				jqTransformImgPreloaded = true;
				var oInputText = $('input:text:first', selfForm);
				if(oInputText.length > 0){
					//pour ie on eleve les ""
					var strWrapperImgUrl = oInputText.get(0).wrapper.css('background-image');
					jqTransformPreloadHoverFocusImg(strWrapperImgUrl);					
					var strInnerImgUrl = $('div.jqTransformInputInner',$(oInputText.get(0).wrapper)).css('background-image');
					jqTransformPreloadHoverFocusImg(strInnerImgUrl);
				}
				
				var oTextarea = $('textarea',selfForm);
				if(oTextarea.length > 0){
					var oTable = oTextarea.get(0).oTable;
					$('td',oTable).each(function(){
						var strImgBack = $(this).css('background-image');
						jqTransformPreloadHoverFocusImg(strImgBack);
					});
				}
			}
			
			
		}); /* End Form each */
				
	};/* End the Plugin */

})(jQuery);
				   /**
 * Boxy 0.1.4 - Facebook-style dialog, with frills
 *
 * (c) 2008 Jason Frame
 * Licensed under the MIT License (LICENSE)
 */
 
/*
 * jQuery plugin
 *
 * Options:
 *   message: confirmation message for form submit hook (default: "Please confirm:")
 * 
 * Any other options - e.g. 'clone' - will be passed onto the boxy constructor (or
 * Boxy.load for AJAX operations)
 */
jQuery.fn.boxy = function(options) {
    options = options || {};
    return this.each(function() {      
        var node = this.nodeName.toLowerCase(), self = this;
        if (node == 'a') {
            jQuery(this).click(function() {
                var active = Boxy.linkedTo(this),
                    href = this.getAttribute('href'),
                    localOptions = jQuery.extend({actuator: this, title: this.title}, options);
                    
                if (active) {
                    active.show();
                } else if (href.indexOf('#') >= 0) {
                    var content = jQuery(href.substr(href.indexOf('#'))),
                        newContent = content.clone(true);
                    content.remove();
                    localOptions.unloadOnHide = false;
                    new Boxy(newContent, localOptions);
                } else { // fall back to AJAX; could do with a same-origin check
                    if (!localOptions.cache) localOptions.unloadOnHide = true;
                    Boxy.load(this.href, localOptions);
                }
                
                return false;
            });
        } else if (node == 'form') {
            jQuery(this).bind('submit.boxy', function() {
                Boxy.confirm(options.message || 'Please confirm:', function() {
                    jQuery(self).unbind('submit.boxy').submit();
                });
                return false;
            });
        }
    });
};

//
// Boxy Class

function Boxy(element, options) {
    
    this.boxy = jQuery(Boxy.WRAPPER);
    jQuery.data(this.boxy[0], 'boxy', this);
    
    this.visible = false;
    this.options = jQuery.extend({}, Boxy.DEFAULTS, options || {});
    
    if (this.options.modal) {
        this.options = jQuery.extend(this.options, {center: true, draggable: false});
    }
    
    // options.actuator == DOM element that opened this boxy
    // association will be automatically deleted when this boxy is remove()d
    if (this.options.actuator) {
        jQuery.data(this.options.actuator, 'active.boxy', this);
    }
    
    this.setContent(element || "<div></div>");
    this._setupTitleBar();
    
    this.boxy.css('display', 'none').appendTo(document.body);
    this.toTop();

    if (this.options.fixed) {
        if (jQuery.browser.msie && jQuery.browser.version < 7) {
            this.options.fixed = false; // IE6 doesn't support fixed positioning
        } else {
            this.boxy.addClass('fixed');
        }
    }
    
    if (this.options.center && Boxy._u(this.options.x, this.options.y)) {
        this.center();
    } else {
        this.moveTo(
            Boxy._u(this.options.x) ? this.options.x : Boxy.DEFAULT_X,
            Boxy._u(this.options.y) ? this.options.y : Boxy.DEFAULT_Y
        );
    }
    
    if (this.options.show) this.show();

};

Boxy.EF = function() {};

jQuery.extend(Boxy, {
    
    WRAPPER:    "<table cellspacing='0' cellpadding='0' border='0' class='boxy-wrapper'>" +
                "<tr><td class='top-left'></td><td class='top'></td><td class='top-right'></td></tr>" +
                "<tr><td class='left'></td><td class='boxy-inner'></td><td class='right'></td></tr>" +
                "<tr><td class='bottom-left'></td><td class='bottom'></td><td class='bottom-right'></td></tr>" +
                "</table>",
    
    DEFAULTS: {
        title:                  null,           // titlebar text. titlebar will not be visible if not set.
        closeable:              true,           // display close link in titlebar?
        draggable:              true,           // can this dialog be dragged?
        clone:                  false,          // clone content prior to insertion into dialog?
        actuator:               null,           // element which opened this dialog
        center:                 true,           // center dialog in viewport?
        show:                   true,           // show dialog immediately?
        modal:                  false,          // make dialog modal?
        fixed:                  true,           // use fixed positioning, if supported? absolute positioning used otherwise
        closeText:              '[close]',      // text to use for default close link
        unloadOnHide:           false,          // should this dialog be removed from the DOM after being hidden?
        clickToFront:           false,          // bring dialog to foreground on any click (not just titlebar)?
        behaviours:             Boxy.EF,        // function used to apply behaviours to all content embedded in dialog.
        afterDrop:              Boxy.EF,        // callback fired after dialog is dropped. executes in context of Boxy instance.
        afterShow:              Boxy.EF,        // callback fired after dialog becomes visible. executes in context of Boxy instance.
        afterHide:              Boxy.EF,        // callback fired after dialog is hidden. executed in context of Boxy instance.
        beforeUnload:           Boxy.EF         // callback fired after dialog is unloaded. executed in context of Boxy instance.
    },
    
    DEFAULT_X:          50,
    DEFAULT_Y:          50,
    zIndex:             1337,
    dragConfigured:     false, // only set up one drag handler for all boxys
    resizeConfigured:   false,
    dragging:           null,
    
    // load a URL and display in boxy
    // url - url to load
    // options keys (any not listed below are passed to boxy constructor)
    //   type: HTTP method, default: GET
    //   cache: cache retrieved content? default: false
    //   filter: jQuery selector used to filter remote content
    load: function(url, options) {
        
        options = options || {};
        
        var ajax = {
            url: url, type: 'GET', dataType: 'html', cache: false, success: function(html) {
                html = jQuery(html);
                if (options.filter) html = jQuery(options.filter, html);
                new Boxy(html, options);
            }
        };
        
        jQuery.each(['type', 'cache'], function() {
            if (this in options) {
                ajax[this] = options[this];
                delete options[this];
            }
        });
        
        jQuery.ajax(ajax);
        
    },
    
    // allows you to get a handle to the containing boxy instance of any element
    // e.g. <a href='#' onclick='alert(Boxy.get(this));'>inspect!</a>.
    // this returns the actual instance of the boxy 'class', not just a DOM element.
    // Boxy.get(this).hide() would be valid, for instance.
    get: function(ele) {
        var p = jQuery(ele).parents('.boxy-wrapper');
        return p.length ? jQuery.data(p[0], 'boxy') : null;
    },
    
    // returns the boxy instance which has been linked to a given element via the
    // 'actuator' constructor option.
    linkedTo: function(ele) {
        return jQuery.data(ele, 'active.boxy');
    },
    
    // displays an alert box with a given message, calling optional callback
    // after dismissal.
    alert: function(message, callback, options) {
        return Boxy.ask(message, ['OK'], callback, options);
    },
    
    // displays an alert box with a given message, calling after callback iff
    // user selects OK.
    confirm: function(message, after, options) {
        return Boxy.ask(message, ['OK', 'Cancel'], function(response) {
            if (response == 'OK') after();
        }, options);
    },
    
    // asks a question with multiple responses presented as buttons
    // selected item is returned to a callback method.
    // answers may be either an array or a hash. if it's an array, the
    // the callback will received the selected value. if it's a hash,
    // you'll get the corresponding key.
    ask: function(question, answers, callback, options) {
        
        options = jQuery.extend({modal: true, closeable: false},
                                options || {},
                                {show: true, unloadOnHide: true});
        
        var body = jQuery('<div></div>').append(jQuery('<div class="question"></div>').html(question));
        
        // ick
        var map = {}, answerStrings = [];
        if (answers instanceof Array) {
            for (var i = 0; i < answers.length; i++) {
                map[answers[i]] = answers[i];
                answerStrings.push(answers[i]);
            }
        } else {
            for (var k in answers) {
                map[answers[k]] = k;
                answerStrings.push(answers[k]);
            }
        }
        
        var buttons = jQuery('<form class="answers"></form>');
        buttons.html(jQuery.map(answerStrings, function(v) {
            return "<input type='button' value='" + v + "' />";
        }).join(' '));
        
        jQuery('input[type=button]', buttons).click(function() {
            var clicked = this;
            Boxy.get(this).hide(function() {
                if (callback) callback(map[clicked.value]);
            });
        });
        
        body.append(buttons);
        
        new Boxy(body, options);
        
    },
    
    // returns true if a modal boxy is visible, false otherwise
    isModalVisible: function() {
        return jQuery('.boxy-modal-blackout').length > 0;
    },
    
    _u: function() {
        for (var i = 0; i < arguments.length; i++)
            if (typeof arguments[i] != 'undefined') return false;
        return true;
    },
    
    _handleResize: function(evt) {
        var d = jQuery(document);
        jQuery('.boxy-modal-blackout').css('display', 'none').css({
            width: d.width(), height: d.height()
        }).css('display', 'block');
    },
    
    _handleDrag: function(evt) {
        var d;
        if (d = Boxy.dragging) {
            d[0].boxy.css({left: evt.pageX - d[1], top: evt.pageY - d[2]});
        }
    },
    
    _nextZ: function() {
        return Boxy.zIndex++;
    },
    
    _viewport: function() {
        var d = document.documentElement, b = document.body, w = window;
        return jQuery.extend(
            jQuery.browser.msie ?
                { left: b.scrollLeft || d.scrollLeft, top: b.scrollTop || d.scrollTop } :
                { left: w.pageXOffset, top: w.pageYOffset },
            !Boxy._u(w.innerWidth) ?
                { width: w.innerWidth, height: w.innerHeight } :
                (!Boxy._u(d) && !Boxy._u(d.clientWidth) && d.clientWidth != 0 ?
                    { width: d.clientWidth, height: d.clientHeight } :
                    { width: b.clientWidth, height: b.clientHeight }) );
    }

});

Boxy.prototype = {
    
    // Returns the size of this boxy instance without displaying it.
    // Do not use this method if boxy is already visible, use getSize() instead.
    estimateSize: function() {
        this.boxy.css({visibility: 'hidden', display: 'block'});
        var dims = this.getSize();
        this.boxy.css('display', 'none').css('visibility', 'visible');
        return dims;
    },
                
    // Returns the dimensions of the entire boxy dialog as [width,height]
    getSize: function() {
        return [this.boxy.width(), this.boxy.height()];
    },
    
    // Returns the dimensions of the content region as [width,height]
    getContentSize: function() {
        var c = this.getContent();
        return [c.width(), c.height()];
    },
    
    // Returns the position of this dialog as [x,y]
    getPosition: function() {
        var b = this.boxy[0];
        return [b.offsetLeft, b.offsetTop];
    },
    
    // Returns the center point of this dialog as [x,y]
    getCenter: function() {
        var p = this.getPosition();
        var s = this.getSize();
        return [Math.floor(p[0] + s[0] / 2), Math.floor(p[1] + s[1] / 2)];
    },
                
    // Returns a jQuery object wrapping the inner boxy region.
    // Not much reason to use this, you're probably more interested in getContent()
    getInner: function() {
        return jQuery('.boxy-inner', this.boxy);
    },
    
    // Returns a jQuery object wrapping the boxy content region.
    // This is the user-editable content area (i.e. excludes titlebar)
    getContent: function() {
        return jQuery('.boxy-content', this.boxy);
    },
    
    // Replace dialog content
    setContent: function(newContent) {
        newContent = jQuery(newContent).css({display: 'block'}).addClass('boxy-content');
        if (this.options.clone) newContent = newContent.clone(true);
        this.getContent().remove();
        this.getInner().append(newContent);
        this._setupDefaultBehaviours(newContent);
        this.options.behaviours.call(this, newContent);
        return this;
    },
    
    // Move this dialog to some position, funnily enough
    moveTo: function(x, y) {
        this.moveToX(x).moveToY(y);
        return this;
    },
    
    // Move this dialog (x-coord only)
    moveToX: function(x) {
        if (typeof x == 'number') this.boxy.css({left: x});
        else this.centerX();
        return this;
    },
    
    // Move this dialog (y-coord only)
    moveToY: function(y) {
        if (typeof y == 'number') this.boxy.css({top: y});
        else this.centerY();
        return this;
    },
    
    // Move this dialog so that it is centered at (x,y)
    centerAt: function(x, y) {
        var s = this[this.visible ? 'getSize' : 'estimateSize']();
        if (typeof x == 'number') this.moveToX(x - s[0] / 2);
        if (typeof y == 'number') this.moveToY(y - s[1] / 2);
        return this;
    },
    
    centerAtX: function(x) {
        return this.centerAt(x, null);
    },
    
    centerAtY: function(y) {
        return this.centerAt(null, y);
    },
    
    // Center this dialog in the viewport
    // axis is optional, can be 'x', 'y'.
    center: function(axis) {
        var v = Boxy._viewport();
        var o = this.options.fixed ? [0, 0] : [v.left, v.top];
        if (!axis || axis == 'x') this.centerAt(o[0] + v.width / 2, null);
        if (!axis || axis == 'y') this.centerAt(null, o[1] + v.height / 2);
        return this;
    },
    
    // Center this dialog in the viewport (x-coord only)
    centerX: function() {
        return this.center('x');
    },
    
    // Center this dialog in the viewport (y-coord only)
    centerY: function() {
        return this.center('y');
    },
    
    // Resize the content region to a specific size
    resize: function(width, height, after) {
        if (!this.visible) return;
        var bounds = this._getBoundsForResize(width, height);
        this.boxy.css({left: bounds[0], top: bounds[1]});
        this.getContent().css({width: bounds[2], height: bounds[3]});
        if (after) after(this);
        return this;
    },
    
    // Tween the content region to a specific size
    tween: function(width, height, after) {
        if (!this.visible) return;
        var bounds = this._getBoundsForResize(width, height);
        var self = this;
        this.boxy.stop().animate({left: bounds[0], top: bounds[1]});
        this.getContent().stop().animate({width: bounds[2], height: bounds[3]}, function() {
            if (after) after(self);
        });
        return this;
    },
    
    // Returns true if this dialog is visible, false otherwise
    isVisible: function() {
        return this.visible;    
    },
    
    // Make this boxy instance visible
    show: function() {
        if (this.visible) return;
        if (this.options.modal) {
            var self = this;
            if (!Boxy.resizeConfigured) {
                Boxy.resizeConfigured = true;
                jQuery(window).resize(function() { Boxy._handleResize(); });
            }
            this.modalBlackout = jQuery('<div class="boxy-modal-blackout"></div>')
                .css({zIndex: Boxy._nextZ(),
                      opacity: 0.7,
                      width: jQuery(document).width(),
                      height: jQuery(document).height()})
                .appendTo(document.body);
            this.toTop();
            if (this.options.closeable) {
                jQuery(document.body).bind('keypress.boxy', function(evt) {
                    var key = evt.which || evt.keyCode;
                    if (key == 27) {
                        self.hide();
                        jQuery(document.body).unbind('keypress.boxy');
                    }
                });
            }
        }
        this.boxy.stop().css({opacity: 1}).show();
        this.visible = true;
        this._fire('afterShow');
        return this;
    },
    
    // Hide this boxy instance
    hide: function(after) {
        if (!this.visible) return;
        var self = this;
        if (this.options.modal) {
            jQuery(document.body).unbind('keypress.boxy');
            this.modalBlackout.animate({opacity: 0}, function() {
                jQuery(this).remove();
            });
        }
        this.boxy.stop().animate({opacity: 0}, 300, function() {
            self.boxy.css({display: 'none'});
            self.visible = false;
            self._fire('afterHide');
            if (after) after(self);
            if (self.options.unloadOnHide) self.unload();
        });
        return this;
    },
    
    toggle: function() {
        this[this.visible ? 'hide' : 'show']();
        return this;
    },
    
    hideAndUnload: function(after) {
        this.options.unloadOnHide = true;
        this.hide(after);
        return this;
    },
    
    unload: function() {
        this._fire('beforeUnload');
        this.boxy.remove();
        if (this.options.actuator) {
            jQuery.data(this.options.actuator, 'active.boxy', false);
        }
    },
    
    // Move this dialog box above all other boxy instances
    toTop: function() {
        this.boxy.css({zIndex: Boxy._nextZ()});
        return this;
    },
    
    // Returns the title of this dialog
    getTitle: function() {
        return jQuery('> .title-bar h2', this.getInner()).html();
    },
    
    // Sets the title of this dialog
    setTitle: function(t) {
        jQuery('> .title-bar h2', this.getInner()).html(t);
        return this;
    },
    
    //
    // Don't touch these privates
    
    _getBoundsForResize: function(width, height) {
        var csize = this.getContentSize();
        var delta = [width - csize[0], height - csize[1]];
        var p = this.getPosition();
        return [Math.max(p[0] - delta[0] / 2, 0),
                Math.max(p[1] - delta[1] / 2, 0), width, height];
    },
    
    _setupTitleBar: function() {
        if (this.options.title) {
            var self = this;
            var tb = jQuery("<div class='title-bar'></div>").html("<h2>" + this.options.title + "</h2>");
            if (this.options.closeable) {
                tb.append(jQuery("<a href='#' class='close'></a>").html(this.options.closeText));
            };
            if (this.options.draggable) {
                tb[0].onselectstart = function() { return false; };
                tb[0].unselectable = 'on';
                tb[0].style.MozUserSelect = 'none';
                if (!Boxy.dragConfigured) {
                    jQuery(document).mousemove(Boxy._handleDrag);
                    Boxy.dragConfigured = true;
                }
                tb.mousedown(function(evt) {
                    self.toTop();
                    Boxy.dragging = [self, evt.pageX - self.boxy[0].offsetLeft, evt.pageY - self.boxy[0].offsetTop];
                    jQuery(this).addClass('dragging');
                }).mouseup(function() {
                    jQuery(this).removeClass('dragging');
                    Boxy.dragging = null;
                    self._fire('afterDrop');
                });
            };
            this.getInner().prepend(tb);
            this._setupDefaultBehaviours(tb);
        }
    },
    
    _setupDefaultBehaviours: function(root) {
        var self = this;
        if (this.options.clickToFront) {
            root.click(function() { self.toTop(); });
        }
        jQuery('.close', root).click(function() {
            self.hide();
            return false;
        }).mousedown(function(evt) { evt.stopPropagation(); });
    },
    
    _fire: function(event) {
        this.options[event].call(this);
    }
    
};
/**
 * jCarousel - Riding carousels with jQuery
 *   http://sorgalla.com/jcarousel/
 *
 * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Built on top of the jQuery library
 *   http://jquery.com
 *
 * Inspired by the "Carousel Component" by Bill Scott
 *   http://billwscott.com/carousel/
 */

(function($) {
    /**
     * Creates a carousel for all matched elements.
     *
     * @example $("#mycarousel").jcarousel();
     * @before <ul id="mycarousel" class="jcarousel-skin-name"><li>First item</li><li>Second item</li></ul>
     * @result
     *
     * <div class="jcarousel-skin-name">
     *   <div class="jcarousel-container">
     *     <div disabled="disabled" class="jcarousel-prev jcarousel-prev-disabled"></div>
     *     <div class="jcarousel-next"></div>
     *     <div class="jcarousel-clip">
     *       <ul class="jcarousel-list">
     *         <li class="jcarousel-item-1">First item</li>
     *         <li class="jcarousel-item-2">Second item</li>
     *       </ul>
     *     </div>
     *   </div>
     * </div>
     *
     * @name jcarousel
     * @type jQuery
     * @param Hash o A set of key/value pairs to set as configuration properties.
     * @cat Plugins/jCarousel
     */
    $.fn.jcarousel = function(o) {
        return this.each(function() {
            new $jc(this, o);
        });
    };

    // Default configuration properties.
    var defaults = {
        vertical: false,
        start: 1,
        offset: 1,
        size: null,
        scroll: 3,
        visible: null,
        animation: 'normal',
        easing: 'swing',
        auto: 0,
        wrap: null,
        initCallback: null,
        reloadCallback: null,
        itemLoadCallback: null,
        itemFirstInCallback: null,
        itemFirstOutCallback: null,
        itemLastInCallback: null,
        itemLastOutCallback: null,
        itemVisibleInCallback: null,
        itemVisibleOutCallback: null,
        buttonNextHTML: '<div></div>',
        buttonPrevHTML: '<div></div>',
        buttonNextEvent: 'click',
        buttonPrevEvent: 'click',
        buttonNextCallback: null,
        buttonPrevCallback: null
    };

    /**
     * The jCarousel object.
     *
     * @constructor
     * @name $.jcarousel
     * @param Object e The element to create the carousel for.
     * @param Hash o A set of key/value pairs to set as configuration properties.
     * @cat Plugins/jCarousel
     */
    $.jcarousel = function(e, o) {
        this.options    = $.extend({}, defaults, o || {});

        this.locked     = false;

        this.container  = null;
        this.clip       = null;
        this.list       = null;
        this.buttonNext = null;
        this.buttonPrev = null;

        this.wh = !this.options.vertical ? 'width' : 'height';
        this.lt = !this.options.vertical ? 'left' : 'top';

        // Extract skin class
        var skin = '', split = e.className.split(' ');

        for (var i = 0; i < split.length; i++) {
            if (split[i].indexOf('jcarousel-skin') != -1) {
                $(e).removeClass(split[i]);
                var skin = split[i];
                break;
            }
        }

        if (e.nodeName == 'UL' || e.nodeName == 'OL') {
            this.list = $(e);
            this.container = this.list.parent();

            if (this.container.hasClass('jcarousel-clip')) {
                if (!this.container.parent().hasClass('jcarousel-container'))
                    this.container = this.container.wrap('<div></div>');

                this.container = this.container.parent();
            } else if (!this.container.hasClass('jcarousel-container'))
                this.container = this.list.wrap('<div></div>').parent();
        } else {
            this.container = $(e);
            this.list = $(e).find('>ul,>ol,div>ul,div>ol');
        }

        if (skin != '' && this.container.parent()[0].className.indexOf('jcarousel-skin') == -1)
        	this.container.wrap('<div class=" '+ skin + '"></div>');

        this.clip = this.list.parent();

        if (!this.clip.length || !this.clip.hasClass('jcarousel-clip'))
            this.clip = this.list.wrap('<div></div>').parent();

        this.buttonPrev = $('.jcarousel-prev', this.container);

        if (this.buttonPrev.size() == 0 && this.options.buttonPrevHTML != null)
            this.buttonPrev = this.clip.before(this.options.buttonPrevHTML).prev();

        this.buttonPrev.addClass(this.className('jcarousel-prev'));

        this.buttonNext = $('.jcarousel-next', this.container);

        if (this.buttonNext.size() == 0 && this.options.buttonNextHTML != null)
            this.buttonNext = this.clip.before(this.options.buttonNextHTML).prev();

        this.buttonNext.addClass(this.className('jcarousel-next'));

        this.clip.addClass(this.className('jcarousel-clip'));
        this.list.addClass(this.className('jcarousel-list'));
        this.container.addClass(this.className('jcarousel-container'));

        var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
        var li = this.list.children('li');

        var self = this;

        if (li.size() > 0) {
            var wh = 0, i = this.options.offset;
            li.each(function() {
                self.format(this, i++);
                wh += self.dimension(this, di);
            });

            this.list.css(this.wh, wh + 'px');

            // Only set if not explicitly passed as option
            if (!o || o.size === undefined)
                this.options.size = li.size();
        }

        // For whatever reason, .show() does not work in Safari...
        this.container.css('display', 'block');
        this.buttonNext.css('display', 'block');
        this.buttonPrev.css('display', 'block');

        this.funcNext   = function() { self.next(); };
        this.funcPrev   = function() { self.prev(); };
        this.funcResize = function() { self.reload(); };

        if (this.options.initCallback != null)
            this.options.initCallback(this, 'init');

        if ($.browser.safari) {
            this.buttons(false, false);
            $(window).bind('load', function() { self.setup(); });
        } else
            this.setup();
    };

    // Create shortcut for internal use
    var $jc = $.jcarousel;

    $jc.fn = $jc.prototype = {
        jcarousel: '0.2.3'
    };

    $jc.fn.extend = $jc.extend = $.extend;

    $jc.fn.extend({
        /**
         * Setups the carousel.
         *
         * @name setup
         * @type undefined
         * @cat Plugins/jCarousel
         */
        setup: function() {
            this.first     = null;
            this.last      = null;
            this.prevFirst = null;
            this.prevLast  = null;
            this.animating = false;
            this.timer     = null;
            this.tail      = null;
            this.inTail    = false;

            if (this.locked)
                return;

            this.list.css(this.lt, this.pos(this.options.offset) + 'px');
            var p = this.pos(this.options.start);
            this.prevFirst = this.prevLast = null;
            this.animate(p, false);

            $(window).unbind('resize', this.funcResize).bind('resize', this.funcResize);
        },

        /**
         * Clears the list and resets the carousel.
         *
         * @name reset
         * @type undefined
         * @cat Plugins/jCarousel
         */
        reset: function() {
            this.list.empty();

            this.list.css(this.lt, '0px');
            this.list.css(this.wh, '10px');

            if (this.options.initCallback != null)
                this.options.initCallback(this, 'reset');

            this.setup();
        },

        /**
         * Reloads the carousel and adjusts positions.
         *
         * @name reload
         * @type undefined
         * @cat Plugins/jCarousel
         */
        reload: function() {
            if (this.tail != null && this.inTail)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + this.tail);

            this.tail   = null;
            this.inTail = false;

            if (this.options.reloadCallback != null)
                this.options.reloadCallback(this);

            if (this.options.visible != null) {
                var self = this;
                var di = Math.ceil(this.clipping() / this.options.visible), wh = 0, lt = 0;
                $('li', this.list).each(function(i) {
                    wh += self.dimension(this, di);
                    if (i + 1 < self.first)
                        lt = wh;
                });

                this.list.css(this.wh, wh + 'px');
                this.list.css(this.lt, -lt + 'px');
            }

            this.scroll(this.first, false);
        },

        /**
         * Locks the carousel.
         *
         * @name lock
         * @type undefined
         * @cat Plugins/jCarousel
         */
        lock: function() {
            this.locked = true;
            this.buttons();
        },

        /**
         * Unlocks the carousel.
         *
         * @name unlock
         * @type undefined
         * @cat Plugins/jCarousel
         */
        unlock: function() {
            this.locked = false;
            this.buttons();
        },

        /**
         * Sets the size of the carousel.
         *
         * @name size
         * @type undefined
         * @param Number s The size of the carousel.
         * @cat Plugins/jCarousel
         */
        size: function(s) {
            if (s != undefined) {
                this.options.size = s;
                if (!this.locked)
                    this.buttons();
            }

            return this.options.size;
        },

        /**
         * Checks whether a list element exists for the given index (or index range).
         *
         * @name get
         * @type bool
         * @param Number i The index of the (first) element.
         * @param Number i2 The index of the last element.
         * @cat Plugins/jCarousel
         */
        has: function(i, i2) {
            if (i2 == undefined || !i2)
                i2 = i;

            if (this.options.size !== null && i2 > this.options.size)
            	i2 = this.options.size;

            for (var j = i; j <= i2; j++) {
                var e = this.get(j);
                if (!e.length || e.hasClass('jcarousel-item-placeholder'))
                    return false;
            }

            return true;
        },

        /**
         * Returns a jQuery object with list element for the given index.
         *
         * @name get
         * @type jQuery
         * @param Number i The index of the element.
         * @cat Plugins/jCarousel
         */
        get: function(i) {
            return $('.jcarousel-item-' + i, this.list);
        },

        /**
         * Adds an element for the given index to the list.
         * If the element already exists, it updates the inner html.
         * Returns the created element as jQuery object.
         *
         * @name add
         * @type jQuery
         * @param Number i The index of the element.
         * @param String s The innerHTML of the element.
         * @cat Plugins/jCarousel
         */
        add: function(i, s) {
            var e = this.get(i), old = 0, add = 0;

            if (e.length == 0) {
                var c, e = this.create(i), j = $jc.intval(i);
                while (c = this.get(--j)) {
                    if (j <= 0 || c.length) {
                        j <= 0 ? this.list.prepend(e) : c.after(e);
                        break;
                    }
                }
            } else
                old = this.dimension(e);

            e.removeClass(this.className('jcarousel-item-placeholder'));
            typeof s == 'string' ? e.html(s) : e.empty().append(s);

            var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
            var wh = this.dimension(e, di) - old;

            if (i > 0 && i < this.first)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - wh + 'px');

            this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) + wh + 'px');

            return e;
        },

        /**
         * Removes an element for the given index from the list.
         *
         * @name remove
         * @type undefined
         * @param Number i The index of the element.
         * @cat Plugins/jCarousel
         */
        remove: function(i) {
            var e = this.get(i);

            // Check if item exists and is not currently visible
            if (!e.length || (i >= this.first && i <= this.last))
                return;

            var d = this.dimension(e);

            if (i < this.first)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + d + 'px');

            e.remove();

            this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) - d + 'px');
        },

        /**
         * Moves the carousel forwards.
         *
         * @name next
         * @type undefined
         * @cat Plugins/jCarousel
         */
        next: function() {
            this.stopAuto();

            if (this.tail != null && !this.inTail)
                this.scrollTail(false);
            else
                this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'last') && this.options.size != null && this.last == this.options.size) ? 1 : this.first + this.options.scroll);
        },

        /**
         * Moves the carousel backwards.
         *
         * @name prev
         * @type undefined
         * @cat Plugins/jCarousel
         */
        prev: function() {
            this.stopAuto();

            if (this.tail != null && this.inTail)
                this.scrollTail(true);
            else
                this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'first') && this.options.size != null && this.first == 1) ? this.options.size : this.first - this.options.scroll);
        },

        /**
         * Scrolls the tail of the carousel.
         *
         * @name scrollTail
         * @type undefined
         * @param Bool b Whether scroll the tail back or forward.
         * @cat Plugins/jCarousel
         */
        scrollTail: function(b) {
            if (this.locked || this.animating || !this.tail)
                return;

            var pos  = $jc.intval(this.list.css(this.lt));

            !b ? pos -= this.tail : pos += this.tail;
            this.inTail = !b;

            // Save for callbacks
            this.prevFirst = this.first;
            this.prevLast  = this.last;

            this.animate(pos);
        },

        /**
         * Scrolls the carousel to a certain position.
         *
         * @name scroll
         * @type undefined
         * @param Number i The index of the element to scoll to.
         * @param Bool a Flag indicating whether to perform animation.
         * @cat Plugins/jCarousel
         */
        scroll: function(i, a) {
            if (this.locked || this.animating)
                return;

            this.animate(this.pos(i), a);
        },

        /**
         * Prepares the carousel and return the position for a certian index.
         *
         * @name pos
         * @type Number
         * @param Number i The index of the element to scoll to.
         * @cat Plugins/jCarousel
         */
        pos: function(i) {
            if (this.locked || this.animating)
                return;

            i = $jc.intval(i);
            if (this.options.wrap != 'circular')
                i = i < 1 ? 1 : (this.options.size && i > this.options.size ? this.options.size : i);

            var back = this.first > i;
            var pos  = $jc.intval(this.list.css(this.lt));

            // Create placeholders, new list width/height
            // and new list position
            var f = this.options.wrap != 'circular' && this.first <= 1 ? 1 : this.first;
            var c = back ? this.get(f) : this.get(this.last);
            var j = back ? f : f - 1;
            var e = null, l = 0, p = false, d = 0;

            while (back ? --j >= i : ++j < i) {
                e = this.get(j);
                p = !e.length;
                if (e.length == 0) {
                    e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
                    c[back ? 'before' : 'after' ](e);
                }

                c = e;
                d = this.dimension(e);

                if (p)
                    l += d;

                if (this.first != null && (this.options.wrap == 'circular' || (j >= 1 && (this.options.size == null || j <= this.options.size))))
                    pos = back ? pos + d : pos - d;
            }

            // Calculate visible items
            var clipping = this.clipping();
            var cache = [];
            var visible = 0, j = i, v = 0;
            var c = this.get(i - 1);

            while (++visible) {
                e = this.get(j);
                p = !e.length;
                if (e.length == 0) {
                    e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
                    // This should only happen on a next scroll
                    c.length == 0 ? this.list.prepend(e) : c[back ? 'before' : 'after' ](e);
                }

                c = e;
                var d = this.dimension(e);
                if (d == 0) {
                    alert('jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...');
                    return 0;
                }

                if (this.options.wrap != 'circular' && this.options.size !== null && j > this.options.size)
                    cache.push(e);
                else if (p)
                    l += d;

                v += d;

                if (v >= clipping)
                    break;

                j++;
            }

             // Remove out-of-range placeholders
            for (var x = 0; x < cache.length; x++)
                cache[x].remove();

            // Resize list
            if (l > 0) {
                this.list.css(this.wh, this.dimension(this.list) + l + 'px');

                if (back) {
                    pos -= l;
                    this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - l + 'px');
                }
            }

            // Calculate first and last item
            var last = i + visible - 1;
            if (this.options.wrap != 'circular' && this.options.size && last > this.options.size)
                last = this.options.size;

            if (j > last) {
                visible = 0, j = last, v = 0;
                while (++visible) {
                    var e = this.get(j--);
                    if (!e.length)
                        break;
                    v += this.dimension(e);
                    if (v >= clipping)
                        break;
                }
            }

            var first = last - visible + 1;
            if (this.options.wrap != 'circular' && first < 1)
                first = 1;

            if (this.inTail && back) {
                pos += this.tail;
                this.inTail = false;
            }

            this.tail = null;
            if (this.options.wrap != 'circular' && last == this.options.size && (last - visible + 1) >= 1) {
                var m = $jc.margin(this.get(last), !this.options.vertical ? 'marginRight' : 'marginBottom');
                if ((v - m) > clipping)
                    this.tail = v - clipping - m;
            }

            // Adjust position
            while (i-- > first)
                pos += this.dimension(this.get(i));

            // Save visible item range
            this.prevFirst = this.first;
            this.prevLast  = this.last;
            this.first     = first;
            this.last      = last;

            return pos;
        },

        /**
         * Animates the carousel to a certain position.
         *
         * @name animate
         * @type undefined
         * @param mixed p Position to scroll to.
         * @param Bool a Flag indicating whether to perform animation.
         * @cat Plugins/jCarousel
         */
        animate: function(p, a) {
            if (this.locked || this.animating)
                return;

            this.animating = true;

            var self = this;
            var scrolled = function() {
                self.animating = false;

                if (p == 0)
                    self.list.css(self.lt,  0);

                if (self.options.wrap == 'both' || self.options.wrap == 'last' || self.options.size == null || self.last < self.options.size)
                    self.startAuto();

                self.buttons();
                self.notify('onAfterAnimation');
            };

            this.notify('onBeforeAnimation');

            // Animate
            if (!this.options.animation || a == false) {
                this.list.css(this.lt, p + 'px');
                scrolled();
            } else {
                var o = !this.options.vertical ? {'left': p} : {'top': p};
                this.list.animate(o, this.options.animation, this.options.easing, scrolled);
            }
        },

        /**
         * Starts autoscrolling.
         *
         * @name auto
         * @type undefined
         * @param Number s Seconds to periodically autoscroll the content.
         * @cat Plugins/jCarousel
         */
        startAuto: function(s) {
            if (s != undefined)
                this.options.auto = s;

            if (this.options.auto == 0)
                return this.stopAuto();

            if (this.timer != null)
                return;

            var self = this;
            this.timer = setTimeout(function() { self.next(); }, this.options.auto * 1000);
        },

        /**
         * Stops autoscrolling.
         *
         * @name stopAuto
         * @type undefined
         * @cat Plugins/jCarousel
         */
        stopAuto: function() {
            if (this.timer == null)
                return;

            clearTimeout(this.timer);
            this.timer = null;
        },

        /**
         * Sets the states of the prev/next buttons.
         *
         * @name buttons
         * @type undefined
         * @cat Plugins/jCarousel
         */
        buttons: function(n, p) {
            if (n == undefined || n == null) {
                var n = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'first') || this.options.size == null || this.last < this.options.size);
                if (!this.locked && (!this.options.wrap || this.options.wrap == 'first') && this.options.size != null && this.last >= this.options.size)
                    n = this.tail != null && !this.inTail;
            }

            if (p == undefined || p == null) {
                var p = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'last') || this.first > 1);
                if (!this.locked && (!this.options.wrap || this.options.wrap == 'last') && this.options.size != null && this.first == 1)
                    p = this.tail != null && this.inTail;
            }

            var self = this;

            this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent, this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);
            this.buttonPrev[p ? 'bind' : 'unbind'](this.options.buttonPrevEvent, this.funcPrev)[p ? 'removeClass' : 'addClass'](this.className('jcarousel-prev-disabled')).attr('disabled', p ? false : true);

            if (this.buttonNext.length > 0 && (this.buttonNext[0].jcarouselstate == undefined || this.buttonNext[0].jcarouselstate != n) && this.options.buttonNextCallback != null) {
                this.buttonNext.each(function() { self.options.buttonNextCallback(self, this, n); });
                this.buttonNext[0].jcarouselstate = n;
            }

            if (this.buttonPrev.length > 0 && (this.buttonPrev[0].jcarouselstate == undefined || this.buttonPrev[0].jcarouselstate != p) && this.options.buttonPrevCallback != null) {
                this.buttonPrev.each(function() { self.options.buttonPrevCallback(self, this, p); });
                this.buttonPrev[0].jcarouselstate = p;
            }
        },

        notify: function(evt) {
            var state = this.prevFirst == null ? 'init' : (this.prevFirst < this.first ? 'next' : 'prev');

            // Load items
            this.callback('itemLoadCallback', evt, state);

            if (this.prevFirst !== this.first) {
                this.callback('itemFirstInCallback', evt, state, this.first);
                this.callback('itemFirstOutCallback', evt, state, this.prevFirst);
            }

            if (this.prevLast !== this.last) {
                this.callback('itemLastInCallback', evt, state, this.last);
                this.callback('itemLastOutCallback', evt, state, this.prevLast);
            }

            this.callback('itemVisibleInCallback', evt, state, this.first, this.last, this.prevFirst, this.prevLast);
            this.callback('itemVisibleOutCallback', evt, state, this.prevFirst, this.prevLast, this.first, this.last);
        },

        callback: function(cb, evt, state, i1, i2, i3, i4) {
            if (this.options[cb] == undefined || (typeof this.options[cb] != 'object' && evt != 'onAfterAnimation'))
                return;

            var callback = typeof this.options[cb] == 'object' ? this.options[cb][evt] : this.options[cb];

            if (!$.isFunction(callback))
                return;

            var self = this;

            if (i1 === undefined)
                callback(self, state, evt);
            else if (i2 === undefined)
                this.get(i1).each(function() { callback(self, this, i1, state, evt); });
            else {
                for (var i = i1; i <= i2; i++)
                    if (i !== null && !(i >= i3 && i <= i4))
                        this.get(i).each(function() { callback(self, this, i, state, evt); });
            }
        },

        create: function(i) {
            return this.format('<li></li>', i);
        },

        format: function(e, i) {
            var $e = $(e).addClass(this.className('jcarousel-item')).addClass(this.className('jcarousel-item-' + i));
            $e.attr('jcarouselindex', i);
            return $e;
        },

        className: function(c) {
            return c + ' ' + c + (!this.options.vertical ? '-horizontal' : '-vertical');
        },

        dimension: function(e, d) {
            var el = e.jquery != undefined ? e[0] : e;

            var old = !this.options.vertical ?
                el.offsetWidth + $jc.margin(el, 'marginLeft') + $jc.margin(el, 'marginRight') :
                el.offsetHeight + $jc.margin(el, 'marginTop') + $jc.margin(el, 'marginBottom');

            if (d == undefined || old == d)
                return old;

            var w = !this.options.vertical ?
                d - $jc.margin(el, 'marginLeft') - $jc.margin(el, 'marginRight') :
                d - $jc.margin(el, 'marginTop') - $jc.margin(el, 'marginBottom');

            $(el).css(this.wh, w + 'px');

            return this.dimension(el);
        },

        clipping: function() {
            return !this.options.vertical ?
                this.clip[0].offsetWidth - $jc.intval(this.clip.css('borderLeftWidth')) - $jc.intval(this.clip.css('borderRightWidth')) :
                this.clip[0].offsetHeight - $jc.intval(this.clip.css('borderTopWidth')) - $jc.intval(this.clip.css('borderBottomWidth'));
        },

        index: function(i, s) {
            if (s == undefined)
                s = this.options.size;

            return Math.round((((i-1) / s) - Math.floor((i-1) / s)) * s) + 1;
        }
    });

    $jc.extend({
        /**
         * Gets/Sets the global default configuration properties.
         *
         * @name defaults
         * @descr Gets/Sets the global default configuration properties.
         * @type Hash
         * @param Hash d A set of key/value pairs to set as configuration properties.
         * @cat Plugins/jCarousel
         */
        defaults: function(d) {
            return $.extend(defaults, d || {});
        },

        margin: function(e, p) {
            if (!e)
                return 0;

            var el = e.jquery != undefined ? e[0] : e;

            if (p == 'marginRight' && $.browser.safari) {
                var old = {'display': 'block', 'float': 'none', 'width': 'auto'}, oWidth, oWidth2;

                $.swap(el, old, function() { oWidth = el.offsetWidth; });

                old['marginRight'] = 0;
                $.swap(el, old, function() { oWidth2 = el.offsetWidth; });

                return oWidth2 - oWidth;
            }

            return $jc.intval($.css(el, p));
        },

        intval: function(v) {
            v = parseInt(v);
            return isNaN(v) ? 0 : v;
        }
    });

})(jQuery);
