/*
 jQuery delayed observer - 0.8
 http://code.google.com/p/jquery-utils/

 (c) Maxime Haineault <haineault@gmail.com>
 http://haineault.com
 
 MIT License (http://www.opensource.org/licenses/mit-license.php)
 
*/

(function($){
    $.extend($.fn, {
        delayedObserver: function(callback, delay, options){
            return this.each(function(){
                var el = $(this);
                var op = options || {};
                el.data('oldval', el.val())
                    .data('delay', delay || 0.5)
                    .data('condition', op.condition || function() { return ($(this).data('oldval') == $(this).val()); })
                    .data('callback', callback)
                    [(op.event||'keyup')](function(){
                        if (el.data('condition').apply(el)) { return; }
                        else {
                            if (el.data('timer')) { clearTimeout(el.data('timer')); }
                            el.data('timer', setTimeout(function(){
                                el.data('callback').apply(el);
                            }, el.data('delay') * 1000));
                            el.data('oldval', el.val());
                        }
                    });
            });
        }
    });
})(jQuery);

(function($) {
    $.ajaxSettings.accepts._default = "text/javascript, text/html, application/xml, text/xml, */*"
})(jQuery);

(function($) {
    $.fn.reset = function() {
        return this.each(function() {
            if (typeof this.reset == "function" || (typeof this.reset == "object" && !this.reset.nodeType)) {
                this.reset()
            }
        })
    };
    $.fn.enable = function() {
        return this.each(function() {
            this.disabled = false
        })
    };
    $.fn.disable = function() {
        return this.each(function() {
            this.disabled = true
        })
    }
})(jQuery); 

(function($) {
    $.extend({
        fieldEvent: function(el, obs) {
            var field = el[0] || el,
            e = "change";
            if (field.type == "radio" || field.type == "checkbox") {
                e = "click"
            } else {
                if (obs && (field.type == "text" || field.type == "textarea" || field.type == "password")) {
                    e = "keyup"
                }
            }
            return e
        }
    });
    $.fn.extend({
        delayedObserver: function(delay, callback) {
            var el = $(this);
            if (typeof window.delayedObserverStack == "undefined") {
                window.delayedObserverStack = []
            }
            if (typeof window.delayedObserverCallback == "undefined") {
                window.delayedObserverCallback = function(stackPos) {
                    var observed = window.delayedObserverStack[stackPos];
                    if (observed.timer) {
                        clearTimeout(observed.timer)
                    }
                    observed.timer = setTimeout(function() {
                        observed.timer = null;
                        observed.callback(observed.obj, observed.obj.formVal())
                    },
                    observed.delay * 1000);
                    observed.oldVal = observed.obj.formVal()
                }
            }
            window.delayedObserverStack.push({
                obj: el,
                timer: null,
                delay: delay,
                oldVal: el.formVal(),
                callback: callback
            });
            var stackPos = window.delayedObserverStack.length - 1;
            if (el[0].tagName == "FORM") {
                $(":input", el).each(function() {
                    var field = $(this);
                    field.bind($.fieldEvent(field, delay),
                    function() {
                        var observed = window.delayedObserverStack[stackPos];
                        if (observed.obj.formVal() == observed.oldVal) {
                            return
                        } else {
                            window.delayedObserverCallback(stackPos)
                        }
                    })
                })
            } else {
                el.bind($.fieldEvent(el, delay),
                function() {
                    var observed = window.delayedObserverStack[stackPos];
                    if (observed.obj.formVal() == observed.oldVal) {
                        return
                    } else {
                        window.delayedObserverCallback(stackPos)
                    }
                })
            }
        },
        formVal: function() {
            var el = this[0];
            if (el.tagName == "FORM") {
                return this.serialize()
            }
            if (el.type == "checkbox" || el.type == "radio") {
                return this.filter("input:checked").val() || ""
            } else {
                return this.val()
            }
        }
    })
})(jQuery); (function($) {
    $.fn.extend({
        visualEffect: function(o, options) {
            if (options) {
                speed = options.duration * 1000
            } else {
                speed = null
            }
            e = o.replace(/\_(.)/g,
            function(m, l) {
                return l.toUpperCase()
            });
            return eval("$(this)." + e + "(" + speed + ")")
        },
        appear: function(speed, callback) {
            return this.fadeIn(speed, callback)
        },
        blindDown: function(speed, callback) {
            return this.show("blind", {
                direction: "vertical"
            },
            speed, callback)
        },
        blindUp: function(speed, callback) {
            return this.hide("blind", {
                direction: "vertical"
            },
            speed, callback)
        },
        blindRight: function(speed, callback) {
            return this.show("blind", {
                direction: "horizontal"
            },
            speed, callback)
        },
        blindLeft: function(speed, callback) {
            this.hide("blind", {
                direction: "horizontal"
            },
            speed, callback);
            return this
        },
        dropOut: function(speed, callback) {
            return this.hide("drop", {
                direction: "down"
            },
            speed, callback)
        },
        dropIn: function(speed, callback) {
            return this.show("drop", {
                direction: "up"
            },
            speed, callback)
        },
        fade: function(speed, callback) {
            return this.fadeOut(speed, callback)
        },
        fadeToggle: function(speed, callback) {
            return this.animate({
                opacity: "toggle"
            },
            speed, callback)
        },
        fold: function(speed, callback) {
            return this.hide("fold", {},
            speed, callback)
        },
        foldOut: function(speed, callback) {
            return this.show("fold", {},
            speed, callback)
        },
        grow: function(speed, callback) {
            return this.show("scale", {},
            speed, callback)
        },
        highlight: function(speed, callback) {
            return this.show("highlight", {},
            speed, callback)
        },
        puff: function(speed, callback) {
            return this.hide("puff", {},
            speed, callback)
        },
        pulsate: function(speed, callback) {
            return this.show("pulsate", {},
            speed, callback)
        },
        shake: function(speed, callback) {
            return this.show("shake", {},
            speed, callback)
        },
        shrink: function(speed, callback) {
            return this.hide("scale", {},
            speed, callback)
        },
        squish: function(speed, callback) {
            return this.hide("scale", {
                origin: ["top", "left"]
            },
            speed, callback)
        },
        slideUp: function(speed, callback) {
            return this.hide("slide", {
                direction: "up"
            },
            speed, callback)
        },
        slideDown: function(speed, callback) {
            return this.show("slide", {
                direction: "up"
            },
            speed, callback)
        },
        switchOff: function(speed, callback) {
            return this.hide("clip", {},
            speed, callback)
        },
        switchOn: function(speed, callback) {
            return this.show("clip", {},
            speed, callback)
        }
    })
})(jQuery);

//cf. http://github.com/xaviershay/jquery-enumerable

(function ( $ ) {
  var methods = {
    // $([1,2,3]).collect(function() { return this * this }) // => [1, 4, 9]
    collect: function(enumerable, callback) {
      var result = [];
      $.each(enumerable, function(index) {
        result.push(callback.call(this, index));
      });
      return result;
    },

    // $([1,2,3]).inject(0, function(a) { return a + this }) // => 6
    inject: function(enumerable, initialValue, callback) {
      var accumulator = initialValue;

      $.each(enumerable, function (index) {
        accumulator = callback.call(this, accumulator, index);
      });
      return accumulator;
    },

    // FIX: use findAll instead of select wich is alreay used
    // $([1,2,3]).findAll(function() { return this % 2 == 1 }) // => [1, 3]
    findAll: function(enumerable, callback) {
      var result = [];
      $.each(enumerable, function(index) {
        if (callback.call(this, index))
          result.push(this);
      });
      return result;
    },

    // $([1,2,3]).reject(function() { return this % 2 == 1 }) // => [2]
    reject: function(enumerable, callback) {
      return $.findAll(enumerable, negate(callback));
    },

    // $([1,2]).any(function() { return this == 1 }) // => true
    any: function(enumerable, callback) {
      return $.inject(enumerable, false, function(accumulator, index) {
        return accumulator || callback.call(this, index);
      });
    },

    // $([1,1]).any(function() { return this == 1 }) // => true
    all: function(enumerable, callback) {
      return $.inject(enumerable, true, function(accumulator, index) {
        return accumulator && callback.call(this, index);
      });
    },

    // $([1,2,3]).sum() // => 6
    sum: function(enumerable) {
      return $.inject(enumerable, 0, function(accumulator) {
        return accumulator + this;
      });
    }
  };

  var staticFunctions = {};
  var iteratorFunctions = {};
  $.each( methods, function(name, f){ 
    staticFunctions[name]   = makeStaticFunction(f);
    iteratorFunctions[name] = makeIteratorFunction(staticFunctions[name]);
  });
  $.extend(staticFunctions);
  $.fn.extend(iteratorFunctions);

  // Private methods
  function makeStaticFunction(f) {
    return function() {
      if (arguments.length > 1) // The first argument is the enumerable
        validateCallback(arguments[arguments.length - 1]);

      return f.apply(this, arguments);
    }
  }

  function makeIteratorFunction(staticFunction) {
    return function() {
      // arguments isn't a real array, concat doesn't work
      // unless you explicitly convert it
      function toArray() {
        var result = []
        for (var i = 0; i < this.length; i++)
          result.push(this[i])
        return(result)
      }
      return staticFunction.apply(this, [this].concat(toArray.apply(arguments)))
    }
  }

  function validateCallback(callback) {
    if (!jQuery.isFunction(callback))
      throw("callback needs to be a function, it was: " + callback);
  }

  function negate(f) {
    return function() { 
      return !f.apply(this, arguments)
    }
  }
})( jQuery );

/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
 * Licensed under the MIT License (LICENSE.txt).
 *
 * Version 1.0: http://github.com/brandonaaron/jquery-expandable
 *
 * Contributions by:
 *   - Karl Swedberg
 */

(function($) {

$.fn.extend({
    expandable: function(givenOptions) {
        var options = $.extend({
            duration: 'normal',
            interval: 750,
            within: 1,
            by: 2,
            init: false 
        }, givenOptions);
        
        return this.filter('textarea').each(function() {
            var $this = $(this).css({ display: 'block', overflow: 'hidden' }),
                minHeight = $this.height(),
                heightDiff = this.offsetHeight - minHeight,
                rowSize = ( parseInt($this.css('lineHeight'), 10) || parseInt($this.css('fontSize'), 10) ),
                // $mirror is used for determining the height of the text within the textarea
                // it isn't perfect but is pretty close
                // white-space rules from: http://petesbloggerama.blogspot.com/2007/02/firefox-ie-word-wrap-word-break-tables.html
                $mirror = $('<div style="position:absolute;top:-999px;left:-999px;border-color:#000;border-style:solid;overflow-x:hidden;visibility:hidden;z-index:0;white-space: pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;" />').appendTo('body'),
                interval;
            
            // copy styles from textarea to mirror to mirror the textarea as best possible
            $.each('borderTopWidth borderRightWidth borderBottomWidth borderLeftWidth paddingTop paddingRight paddingBottom paddingLeft fontSize fontFamily fontWeight fontStyle fontStretch fontVariant wordSpacing lineHeight width'.split(' '), function(i,prop) {
                $mirror.css(prop, $this.css(prop));
            });
            
            // setup events
            $this
                .bind('keypress', function(event) { if ( event.keyCode == '13' ) check(); })
                .bind('focus blur', function(event) {
                    if ( event.type == 'blur' ) clearInterval( interval );
                    if ( event.type == 'focus' ) interval = setInterval(check, options.interval);
                });

            function check() {
                var text = $this.val(), newHeight, height, usedHeight, usedRows, availableRows;
                // copy textarea value to the $mirror
                // encode any html passed in and replace new lines with a <br>
                // the &nbsp; is to try and normalize browser behavior
                $mirror.html( encodeHTML(text).replace(/\n/g, '&nbsp;<br>') );
                
                height = $this[0].offsetHeight - heightDiff;
                usedHeight = $mirror[0].offsetHeight - heightDiff;
                usedRows = Math.floor(usedHeight / rowSize);
                availableRows = Math.floor((height / rowSize) - usedRows);
                
                // adjust height if needed by either growing or shrinking the text area to within the specified bounds
                if ( availableRows <= options.within ) {
                    newHeight = rowSize * (usedRows + Math.max(availableRows, 0) + options.by);
                    $this.stop().animate({ height: newHeight }, options.duration);
                } else if ( availableRows > options.by + options.within ) {
                    newHeight = Math.max( height - (rowSize * (availableRows - (options.by + options.within))), minHeight );
                    $this.stop().animate({ height: newHeight }, options.duration);
                }
            };
            if ( options.init ) check();
        }).end();
    }
});
    
function encodeHTML(text) {
    var characters = {
        '<' : '&lt;',
        '>' : '&gt;',
        '&' : '&amp;',
        '"' : '&quot;',
        '\'': '&#x27;',
        '/' : '&#x2F;'
    };
    return (text + '').replace(/[<>&"'\/]/g, function(c) {
        return characters[c];
    });
}

})(jQuery);

// ColorBox v1.3.9 - a full featured, light-weight, customizable lightbox based on jQuery 1.3
// c) 2009 Jack Moore - www.colorpowered.com - jack@colorpowered.com
// Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
(function ($, window) {
	
	var
	// ColorBox Default Settings.	
	// See http://colorpowered.com/colorbox for details.
	defaults = {
		transition: "elastic",
		speed: 300,
		width: false,
		initialWidth: "600",
		innerWidth: false,
		maxWidth: false,
		height: false,
		initialHeight: "450",
		innerHeight: false,
		maxHeight: false,
		scalePhotos: true,
		scrolling: true,
		inline: false,
		html: false,
		iframe: false,
		photo: false,
		href: false,
		title: false,
		rel: false,
		opacity: 0.9,
		preloading: true,
		current: "image {current} of {total}",
		previous: "previous",
		next: "next",
		close: "close",
		open: false,
		loop: true,
		slideshow: false,
		slideshowAuto: true,
		slideshowSpeed: 2500,
		slideshowStart: "start slideshow",
		slideshowStop: "stop slideshow",
		onOpen: false,
		onLoad: false,
		onComplete: false,
		onCleanup: false,
		onClosed: false,
		overlayClose: true,		
		escKey: true,
		arrowKey: true
	},
	
	// Abstracting the HTML and event identifiers for easy rebranding
	colorbox = 'colorbox',
	prefix = 'cbox',
	
	// Events	
	event_open = prefix + '_open',
	event_load = prefix + '_load',
	event_complete = prefix + '_complete',
	event_cleanup = prefix + '_cleanup',
	event_closed = prefix + '_closed',
	
	// Special Handling for IE
	isIE = $.browser.msie && !$.support.opacity, // feature detection alone gave a false positive on at least one phone browser and on some development versions of Chrome.
	isIE6 = isIE && $.browser.version < 7,
	event_ie6 = prefix + '_IE6',

	// Cached jQuery Object Variables
	$overlay,
	$box,
	$wrap,
	$content,
	$topBorder,
	$leftBorder,
	$rightBorder,
	$bottomBorder,
	$related,
	$window,
	$loaded,
	$loadingBay,
	$loadingOverlay,
	$title,
	$current,
	$slideshow,
	$next,
	$prev,
	$close,

	// Variables for cached values or use across multiple functions
	interfaceHeight,
	interfaceWidth,
	loadedHeight,
	loadedWidth,
	element,
	bookmark,
	index,
	settings,
	open,
	active,
	
	publicMethod,
	boxElement = prefix + 'Element';
	
	// ****************
	// HELPER FUNCTIONS
	// ****************

	// jQuery object generator to reduce code size
	function $div(id, css) { 
		id = id ? ' id="' + prefix + id + '"' : '';
		css = css ? ' style="' + css + '"' : '';
		return $('<div' + id + css + '/>');
	}

	// Convert % values to pixels
	function setSize(size, dimension) {
		dimension = dimension === 'x' ? $window.width() : $window.height();
		return (typeof size === 'string') ? Math.round((size.match(/%/) ? (dimension / 100) * parseInt(size, 10) : parseInt(size, 10))) : size;
	}

	// Checks an href to see if it is a photo.
	// There is a force photo option (photo: true) for hrefs that cannot be matched by this regex.
	function isImage(url) {
		url = $.isFunction(url) ? url.call(element) : url;
		return settings.photo || url.match(/\.(gif|png|jpg|jpeg|bmp)(?:\?([^#]*))?(?:#(\.*))?$/i);
	}
	
	// Assigns functions results to their respective settings.  This allows functions to be used to set ColorBox options.
	function process() {
		for (var i in settings) {
			if ($.isFunction(settings[i]) && i.substring(0, 2) !== 'on') { // checks to make sure the function isn't one of the callbacks, they will be handled at the appropriate time.
			    settings[i] = settings[i].call(element);
			}
		}
		settings.rel = settings.rel || element.rel || 'nofollow';
		settings.href = settings.href || $(element).attr('href');
		settings.title = settings.title || element.title;
	}

	function launch(elem) {
		
		element = elem;
		
		settings = $.extend({}, $(element).data(colorbox));
		
		process(); // Convert functions to their returned values.
		
		if (settings.rel !== 'nofollow') {
			$related = $('.' + boxElement).filter(function () {
				var relRelated = $(this).data(colorbox).rel || this.rel;
				return (relRelated === settings.rel);
			});
			index = $related.index(element);
			
			// Check direct calls to ColorBox.
			if (index === -1) {
				$related = $related.add(element);
				index = $related.length - 1;
			}
		} else {
			$related = $(element);
			index = 0;
		}
		
		if (!open) {
			open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.
			
			bookmark = element;
			
			try {
				bookmark.blur(); // Remove the focus from the calling element.
			}catch (e) {}
			
			$.event.trigger(event_open);
			if (settings.onOpen) {
				settings.onOpen.call(element);
			}
			
			// +settings.opacity avoids a problem in IE when using non-zero-prefixed-string-values, like '.5'
			$overlay.css({"opacity": +settings.opacity, "cursor": settings.overlayClose ? "pointer" : "auto"}).show();
			
			// Opens inital empty ColorBox prior to content being loaded.
			settings.w = setSize(settings.initialWidth, 'x');
			settings.h = setSize(settings.initialHeight, 'y');
			publicMethod.position(0);
			
			if (isIE6) {
				$window.bind('resize.' + event_ie6 + ' scroll.' + event_ie6, function () {
					$overlay.css({width: $window.width(), height: $window.height(), top: $window.scrollTop(), left: $window.scrollLeft()});
				}).trigger('scroll.' + event_ie6);
			}
		}
		
		$current.add($prev).add($next).add($slideshow).add($title).hide();
		
		$close.html(settings.close).show();
		
		publicMethod.slideshow();
		
		publicMethod.load();
	}

	// ****************
	// PUBLIC FUNCTIONS
	// Usage format: $.fn.colorbox.close();
	// Usage from within an iframe: parent.$.fn.colorbox.close();
	// ****************
	
	publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {
		var $this = this;
		
		if (!$this[0] && $this.selector) { // if a selector was given and it didn't match any elements, go ahead and exit.
			return $this;
		}
		
		options = options || {};
		
		if (callback) {
			options.onComplete = callback;
		}
		
		if (!$this[0] || $this.selector === undefined) { // detects $.colorbox() and $.fn.colorbox()
			$this = $('<a/>');
			options.open = true; // assume an immediate open
		}
		
		$this.each(function () {
			$(this).data(colorbox, $.extend({}, $(this).data(colorbox) || defaults, options)).addClass(boxElement);
		});
		
		if (options.open) {
			launch($this[0]);
		}
		
		return $this;
	};

	// Initialize ColorBox: store common calculations, preload the interface graphics, append the html.
	// This preps colorbox for a speedy open when clicked, and lightens the burdon on the browser by only
	// having to run once, instead of each time colorbox is opened.
	publicMethod.init = function () {
		// Create & Append jQuery Objects
		$window = $(window);
		$box = $div().attr({id: colorbox, 'class': isIE ? prefix + 'IE' : ''});
		$overlay = $div("Overlay", isIE6 ? 'position:absolute' : '').hide();
		
		$wrap = $div("Wrapper");
		$content = $div("Content").append(
			$loaded = $div("LoadedContent", 'width:0; height:0'),
			$loadingOverlay = $div("LoadingOverlay").add($div("LoadingGraphic")),
			$title = $div("Title"),
			$current = $div("Current"),
			$next = $div("Next"),
			$prev = $div("Previous"),
			$slideshow = $div("Slideshow"),
			$close = $div("Close")
		);
		$wrap.append( // The 3x3 Grid that makes up ColorBox
			$div().append(
				$div("TopLeft"),
				$topBorder = $div("TopCenter"),
				$div("TopRight")
			),
			$div().append(
				$leftBorder = $div("MiddleLeft"),
				$content,
				$rightBorder = $div("MiddleRight")
			),
			$div().append(
				$div("BottomLeft"),
				$bottomBorder = $div("BottomCenter"),
				$div("BottomRight")
			)
		).children().children().css({'float': 'left'});
		
		$loadingBay = $div(false, 'position:absolute; width:9999px; visibility:hidden; display:none');
		
		$('body').prepend($overlay, $box.append($wrap, $loadingBay));
		
		$content.children()
		.hover(function () {
			$(this).addClass('hover');
		}, function () {
			$(this).removeClass('hover');
		}).addClass('hover');
		
		// Cache values needed for size calculations
		interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();//Subtraction needed for IE6
		interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
		loadedHeight = $loaded.outerHeight(true);
		loadedWidth = $loaded.outerWidth(true);
		
		// Setting padding to remove the need to do size conversions during the animation step.
		$box.css({"padding-bottom": interfaceHeight, "padding-right": interfaceWidth}).hide();
		
		// Setup button events.
		$next.click(publicMethod.next);
		$prev.click(publicMethod.prev);
		$close.click(publicMethod.close);
		
		// Adding the 'hover' class allowed the browser to load the hover-state
		// background graphics.  The class can now can be removed.
		$content.children().removeClass('hover');
		
		$('.' + boxElement).live('click', function (e) {
			// checks to see if it was a non-left mouse-click and for clicks modified with ctrl, shift, or alt.
			if ((e.button !== 0 && typeof e.button !== 'undefined') || e.ctrlKey || e.shiftKey || e.altKey) {
				return true;
			} else {
				launch(this);			
				return false;
			}
		});
		
		$overlay.click(function () {
			if (settings.overlayClose) {
				publicMethod.close();
			}
		});
		
		// Set Navigation Key Bindings
		$(document).bind("keydown", function (e) {
			if (open && settings.escKey && e.keyCode === 27) {
				e.preventDefault();
				publicMethod.close();
			}
			if (open && settings.arrowKey && !active && $related[1]) {
				if (e.keyCode === 37 && (index || settings.loop)) {
					e.preventDefault();
					$prev.click();
				} else if (e.keyCode === 39 && (index < $related.length - 1 || settings.loop)) {
					e.preventDefault();
					$next.click();
				}
			}
		});
	};
	
	publicMethod.remove = function () {
		$box.add($overlay).remove();
		$('.' + boxElement).die('click').removeData(colorbox).removeClass(boxElement);
	};

	publicMethod.position = function (speed, loadedCallback) {
		var
		animate_speed,
		// keeps the top and left positions within the browser's viewport.
		posTop = Math.max($window.height() - settings.h - loadedHeight - interfaceHeight, 0) / 2 + $window.scrollTop(),
		posLeft = Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2 + $window.scrollLeft();
		
		// setting the speed to 0 to reduce the delay between same-sized content.
		animate_speed = ($box.width() === settings.w + loadedWidth && $box.height() === settings.h + loadedHeight) ? 0 : speed;
		
		// this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
		// but it has to be shrank down around the size of div#colorbox when it's done.  If not,
		// it can invoke an obscure IE bug when using iframes.
		$wrap[0].style.width = $wrap[0].style.height = "9999px";
		
		function modalDimensions(that) {
			// loading overlay height has to be explicitly set for IE6.
			$topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = that.style.width;
			$loadingOverlay[0].style.height = $loadingOverlay[1].style.height = $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = that.style.height;
		}
		
		$box.dequeue().animate({width: settings.w + loadedWidth, height: settings.h + loadedHeight, top: posTop, left: posLeft}, {
			duration: animate_speed,
			complete: function () {
				modalDimensions(this);
				
				active = false;
				
				// shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
				$wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";
				$wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";
				
				if (loadedCallback) {
					loadedCallback();
				}
			},
			step: function () {
				modalDimensions(this);
			}
		});
	};

	publicMethod.resize = function (options) {
		if (open) {
			options = options || {};
			
			if (options.width) {
				settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;
			}
			if (options.innerWidth) {
				settings.w = setSize(options.innerWidth, 'x');
			}
			$loaded.css({width: settings.w});
			
			if (options.height) {
				settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;
			}
			if (options.innerHeight) {
				settings.h = setSize(options.innerHeight, 'y');
			}
			if (!options.innerHeight && !options.height) {				
				var $child = $loaded.wrapInner("<div style='overflow:auto'></div>").children(); // temporary wrapper to get an accurate estimate of just how high the total content should be.
				settings.h = $child.height();
				$child.replaceWith($child.children()); // ditch the temporary wrapper div used in height calculation
			}
			$loaded.css({height: settings.h});
			
			publicMethod.position(settings.transition === "none" ? 0 : settings.speed);
		}
	};

	publicMethod.prep = function (object) {
		if (!open) {
			return;
		}
		
		var photo,
		speed = settings.transition === "none" ? 0 : settings.speed;
		
		$window.unbind('resize.' + prefix);
		$loaded.remove();
		$loaded = $div('LoadedContent').html(object);
		
		function getWidth() {
			settings.w = settings.w || $loaded.width();
			settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
			return settings.w;
		}
		function getHeight() {
			settings.h = settings.h || $loaded.height();
			settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
			return settings.h;
		}
		
		$loaded.hide()
		.appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.
		.css({width: getWidth(), overflow: settings.scrolling ? 'auto' : 'hidden'})
		.css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.
		.prependTo($content);
		
		$loadingBay.hide();
		
		$('#' + prefix + 'Photo').css({cssFloat: 'none'});// floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.
		
		// Hides SELECT elements in IE6 because they would otherwise sit on top of the overlay.
		if (isIE6) {
			$('select').not($box.find('select')).filter(function () {
				return this.style.visibility !== 'hidden';
			}).css({'visibility': 'hidden'}).one(event_cleanup, function () {
				this.style.visibility = 'inherit';
			});
		}
				
		function setPosition(s) {
			var prev, prevSrc, next, nextSrc, total = $related.length, loop = settings.loop;
			publicMethod.position(s, function () {
				function defilter() {
					if (isIE) {
						//IE adds a filter when ColorBox fades in and out that can cause problems if the loaded content contains transparent pngs.
						$box[0].style.removeAttribute("filter");
					}
				}
				
				if (!open) {
					return;
				}
				
				if (isIE) {
					//This fadeIn helps the bicubic resampling to kick-in.
					if (photo) {
						$loaded.fadeIn(100);
					}
				}
				
				//Waited until the iframe is added to the DOM & it is visible before setting the src.
				//This increases compatability with pages using DOM dependent JavaScript.
				if (settings.iframe) {
					$("<iframe frameborder=0" + (settings.scrolling ? "" : " scrolling='no'") + (isIE ? " allowtransparency='true'" : '') + "/>")
					.attr({src: settings.href, name: new Date().getTime()})
					.appendTo($loaded);
				}
				
				$loaded.show();
				
				$title.show().html(settings.title);
				
				if (total > 1) { // handle grouping
					$current.html(settings.current.replace(/\{current\}/, index + 1).replace(/\{total\}/, total)).show();
					
					$next[(loop || index < total - 1) ? "show" : "hide"]().html(settings.next);
					$prev[(loop || index) ? "show" : "hide"]().html(settings.previous);
					
					prev = index ? $related[index - 1] : $related[total - 1];
					next = index < total - 1 ? $related[index + 1] : $related[0];
					
					if (settings.slideshow) {
						$slideshow.show();
						if (index === total - 1 && !loop && $box.is('.' + prefix + 'Slideshow_on')) {
							$slideshow.click();
						}
					}
					
					// Preloads images within a rel group
					if (settings.preloading) {
						nextSrc = $(next).data(colorbox).href || next.href;
						prevSrc = $(prev).data(colorbox).href || prev.href;
						
						if (isImage(nextSrc)) {
							$('<img/>')[0].src = nextSrc;
						}
						
						if (isImage(prevSrc)) {
							$('<img/>')[0].src = prevSrc;
						}
					}
				}
				
				$loadingOverlay.hide();
				
				if (settings.transition === 'fade') {
					$box.fadeTo(speed, 1, function () {
						defilter();
					});
				} else {
					defilter();
				}
				
				$window.bind('resize.' + prefix, function () {
					publicMethod.position(0);
				});
				
				$.event.trigger(event_complete);
				if (settings.onComplete) {
					settings.onComplete.call(element);
				}
			});
		}
		
		if (settings.transition === 'fade') {
			$box.fadeTo(speed, 0, function () {
				setPosition(0);
			});
		} else {
			setPosition(speed);
		}
	};

	publicMethod.load = function () {
		var href, img, setResize, prep = publicMethod.prep;
		
		active = true;
		
		element = $related[index];
		
		settings = $.extend({}, $(element).data(colorbox));
		
		//convert functions to static values
		process();
		
		$.event.trigger(event_load);
		if (settings.onLoad) {
			settings.onLoad.call(element);
		}
		
		settings.h = settings.height ?
				setSize(settings.height, 'y') - loadedHeight - interfaceHeight :
				settings.innerHeight && setSize(settings.innerHeight, 'y');
		
		settings.w = settings.width ?
				setSize(settings.width, 'x') - loadedWidth - interfaceWidth :
				settings.innerWidth && setSize(settings.innerWidth, 'x');
		
		// Sets the minimum dimensions for use in image scaling
		settings.mw = settings.w;
		settings.mh = settings.h;
		
		// Re-evaluate the minimum width and height based on maxWidth and maxHeight values.
		// If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.
		if (settings.maxWidth) {
			settings.mw = setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth;
			settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;
		}
		if (settings.maxHeight) {
			settings.mh = setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight;
			settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;
		}
		
		href = settings.href;
		
		$loadingOverlay.show();
		
		if (settings.inline) {
			// Inserts an empty placeholder where inline content is being pulled from.
			// An event is bound to put inline content back when ColorBox closes or loads new content.
			$div('InlineTemp').hide().insertBefore($(href)[0]).bind(event_load + ' ' + event_cleanup, function () {
				$(this).replaceWith($loaded.children());
			});
			prep($(href));
		} else if (settings.iframe) {
			// IFrame element won't be added to the DOM until it is ready to be displayed,
			// to avoid problems with DOM-ready JS that might be trying to run in that iframe.
			prep(" ");
		} else if (settings.html) {
			prep(settings.html);
		} else if (isImage(href)) {
			img = new Image();
			img.onload = function () {
				var percent;
				
				img.onload = null;
				img.id = prefix + 'Photo';
				$(img).css({margin: 'auto', border: 'none', display: 'block', cssFloat: 'left'});
				
				if (settings.scalePhotos) {
					setResize = function () {
						img.height -= img.height * percent;
						img.width -= img.width * percent;	
					};
					if (settings.mw && img.width > settings.mw) {
						percent = (img.width - settings.mw) / img.width;
						setResize();
					}
					if (settings.mh && img.height > settings.mh) {
						percent = (img.height - settings.mh) / img.height;
						setResize();
					}
				}
				
				if (settings.h) {
					img.style.marginTop = Math.max(settings.h - img.height, 0) / 2 + 'px';
				}
				
				setTimeout(function () { // Chrome will sometimes report a 0 by 0 size if there isn't pause in execution
					prep(img);
				}, 1);
				
				if ($related[1] && (index < $related.length - 1 || settings.loop)) {
					$(img).css({cursor: 'pointer'}).click(publicMethod.next);
				}
				
				if (isIE) {
					img.style.msInterpolationMode = 'bicubic';
				}
			};
			img.src = href;
		} else {
			$div().appendTo($loadingBay).load(href, function (data, status, xhr) {
				prep(status === 'error' ? 'Request unsuccessful: ' + xhr.statusText : this);
			});
		}
	};

	// Navigates to the next page/image in a set.
	publicMethod.next = function () {
		if (!active) {
			index = index < $related.length - 1 ? index + 1 : 0;
			publicMethod.load();
		}
	};
	
	publicMethod.prev = function () {
		if (!active) {
			index = index ? index - 1 : $related.length - 1;
			publicMethod.load();
		}
	};

	publicMethod.slideshow = function () {
		var stop, timeOut, className = prefix + 'Slideshow_';
		
		$slideshow.bind(event_closed, function () {
			$slideshow.unbind();
			clearTimeout(timeOut);
			$box.removeClass(className + "off " + className + "on");
		});
		
		function start() {
			$slideshow
			.text(settings.slideshowStop)
			.bind(event_complete, function () {
				timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed);
			})
			.bind(event_load, function () {
				clearTimeout(timeOut);	
			}).one("click", function () {
				stop();
			});
			$box.removeClass(className + "off").addClass(className + "on");
		}
		
		stop = function () {
			clearTimeout(timeOut);
			$slideshow
			.text(settings.slideshowStart)
			.unbind(event_complete + ' ' + event_load)
			.one("click", function () {
				start();
				timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed);
			});
			$box.removeClass(className + "on").addClass(className + "off");
		};
		
		if (settings.slideshow && $related[1]) {
			if (settings.slideshowAuto) {
				start();
			} else {
				stop();
			}
		}
	};

	// Note: to use this within an iframe use the following format: parent.$.fn.colorbox.close();
	publicMethod.close = function () {
		if (open) {
			open = false;
			
			$.event.trigger(event_cleanup);
			
			if (settings.onCleanup) {
				settings.onCleanup.call(element);
			}
			
			$window.unbind('.' + prefix + ' .' + event_ie6);
			
			$overlay.fadeTo('fast', 0);
			
			$box.stop().fadeTo('fast', 0, function () {
				$box.find('iframe').attr('src', 'about:blank'); // change the location of the iframe to avoid a problem in IE with flash objects not clearing.
				
				$loaded.remove();
				
				$box.add($overlay).css({'opacity': 1, cursor: 'auto'}).hide();
				
				try {
					bookmark.focus();
				} catch (e) {
					// do nothing
				}
				
				setTimeout(function () {
					$.event.trigger(event_closed);
					if (settings.onClosed) {
						settings.onClosed.call(element);
					}
				}, 1);
			});
		}
	};

	// A method for fetching the current element ColorBox is referencing.
	// returns a jQuery object.
	publicMethod.element = function () {
		return $(element);
	};

	publicMethod.settings = defaults;

	// Initializes ColorBox when the DOM has loaded
	$(publicMethod.init);

}(jQuery, this));


/**
 * Farbtastic Color Picker 1.2
 * © 2008 Steven Wittens
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

jQuery.fn.farbtastic = function (callback) {
  $.farbtastic(this, callback);
  return this;
};

jQuery.farbtastic = function (container, callback) {
  var container = $(container).get(0);
  return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback));
}

jQuery._farbtastic = function (container, callback) {
  // Store farbtastic object
  var fb = this;

  // Insert markup
  $(container).html('<div class="farbtastic"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>');
  var e = $('.farbtastic', container);
  fb.wheel = $('.wheel', container).get(0);
  // Dimensions
  fb.radius = 84;
  fb.square = 100;
  fb.width = 194;

  // Fix background PNGs in IE6
  if (navigator.appVersion.match(/MSIE [0-6]\./)) {
    $('*', e).each(function () {
      if (this.currentStyle.backgroundImage != 'none') {
        var image = this.currentStyle.backgroundImage;
        image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
        $(this).css({
          'backgroundImage': 'none',
          'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
        });
      }
    });
  }

  /**
   * Link to the given element(s) or callback.
   */
  fb.linkTo = function (callback) {
    // Unbind previous nodes
    if (typeof fb.callback == 'object') {
      $(fb.callback).unbind('keyup', fb.updateValue);
    }

    // Reset color
    fb.color = null;

    // Bind callback or elements
    if (typeof callback == 'function') {
      fb.callback = callback;
    }
    else if (typeof callback == 'object' || typeof callback == 'string') {
      fb.callback = $(callback);
      fb.callback.bind('keyup', fb.updateValue);
      if (fb.callback.get(0).value) {
        fb.setColor(fb.callback.get(0).value);
      }
    }
    return this;
  }
  fb.updateValue = function (event) {
    if (this.value && this.value != fb.color) {
      fb.setColor(this.value);
    }
  }

  /**
   * Change color with HTML syntax #123456
   */
  fb.setColor = function (color) {
    var unpack = fb.unpack(color);
    if (fb.color != color && unpack) {
      fb.color = color;
      fb.rgb = unpack;
      fb.hsl = fb.RGBToHSL(fb.rgb);
      fb.updateDisplay();
    }
    return this;
  }

  /**
   * Change color with HSL triplet [0..1, 0..1, 0..1]
   */
  fb.setHSL = function (hsl) {
    fb.hsl = hsl;
    fb.rgb = fb.HSLToRGB(hsl);
    fb.color = fb.pack(fb.rgb);
    fb.updateDisplay();
    return this;
  }

  /////////////////////////////////////////////////////

  /**
   * Retrieve the coordinates of the given event relative to the center
   * of the widget.
   */
  fb.widgetCoords = function (event) {
    var x, y;
    var el = event.target || event.srcElement;
    var reference = fb.wheel;

    if (typeof event.offsetX != 'undefined') {
      // Use offset coordinates and find common offsetParent
      var pos = { x: event.offsetX, y: event.offsetY };

      // Send the coordinates upwards through the offsetParent chain.
      var e = el;
      while (e) {
        e.mouseX = pos.x;
        e.mouseY = pos.y;
        pos.x += e.offsetLeft;
        pos.y += e.offsetTop;
        e = e.offsetParent;
      }

      // Look for the coordinates starting from the wheel widget.
      var e = reference;
      var offset = { x: 0, y: 0 }
      while (e) {
        if (typeof e.mouseX != 'undefined') {
          x = e.mouseX - offset.x;
          y = e.mouseY - offset.y;
          break;
        }
        offset.x += e.offsetLeft;
        offset.y += e.offsetTop;
        e = e.offsetParent;
      }

      // Reset stored coordinates
      e = el;
      while (e) {
        e.mouseX = undefined;
        e.mouseY = undefined;
        e = e.offsetParent;
      }
    }
    else {
      // Use absolute coordinates
      var pos = fb.absolutePosition(reference);
      x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x;
      y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y;
    }
    // Subtract distance to middle
    return { x: x - fb.width / 2, y: y - fb.width / 2 };
  }

  /**
   * Mousedown handler
   */
  fb.mousedown = function (event) {
    // Capture mouse
    if (!document.dragging) {
      $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
      document.dragging = true;
    }

    // Check which area is being dragged
    var pos = fb.widgetCoords(event);
    fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;

    // Process
    fb.mousemove(event);
    return false;
  }

  /**
   * Mousemove handler
   */
  fb.mousemove = function (event) {
    // Get coordinates relative to color picker center
    var pos = fb.widgetCoords(event);

    // Set new HSL parameters
    if (fb.circleDrag) {
      var hue = Math.atan2(pos.x, -pos.y) / 6.28;
      if (hue < 0) hue += 1;
      fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
    }
    else {
      var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
      var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
      fb.setHSL([fb.hsl[0], sat, lum]);
    }
    return false;
  }

  /**
   * Mouseup handler
   */
  fb.mouseup = function () {
    // Uncapture mouse
    $(document).unbind('mousemove', fb.mousemove);
    $(document).unbind('mouseup', fb.mouseup);
    document.dragging = false;
  }

  /**
   * Update the markers and styles
   */
  fb.updateDisplay = function () {
    // Markers
    var angle = fb.hsl[0] * 6.28;
    $('.h-marker', e).css({
      left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
      top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
    });

    $('.sl-marker', e).css({
      left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
      top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
    });

    // Saturation/Luminance gradient
    $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));

    // Linked elements or callback
    if (typeof fb.callback == 'object') {
      // Set background/foreground color
      $(fb.callback).css({
        backgroundColor: fb.color,
        color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
      });

      // Change linked value
      $(fb.callback).each(function() {
        if (this.value && this.value != fb.color) {
          this.value = fb.color;
        }
      });
    }
    else if (typeof fb.callback == 'function') {
      fb.callback.call(fb, fb.color);
    }
  }

  /**
   * Get absolute position of element
   */
  fb.absolutePosition = function (el) {
    var r = { x: el.offsetLeft, y: el.offsetTop };
    // Resolve relative to offsetParent
    if (el.offsetParent) {
      var tmp = fb.absolutePosition(el.offsetParent);
      r.x += tmp.x;
      r.y += tmp.y;
    }
    return r;
  };

  /* Various color utility functions */
  fb.pack = function (rgb) {
    var r = Math.round(rgb[0] * 255);
    var g = Math.round(rgb[1] * 255);
    var b = Math.round(rgb[2] * 255);
    return '#' + (r < 16 ? '0' : '') + r.toString(16) +
           (g < 16 ? '0' : '') + g.toString(16) +
           (b < 16 ? '0' : '') + b.toString(16);
  }

  fb.unpack = function (color) {
    if (color.length == 7) {
      return [parseInt('0x' + color.substring(1, 3)) / 255,
        parseInt('0x' + color.substring(3, 5)) / 255,
        parseInt('0x' + color.substring(5, 7)) / 255];
    }
    else if (color.length == 4) {
      return [parseInt('0x' + color.substring(1, 2)) / 15,
        parseInt('0x' + color.substring(2, 3)) / 15,
        parseInt('0x' + color.substring(3, 4)) / 15];
    }
  }

  fb.HSLToRGB = function (hsl) {
    var m1, m2, r, g, b;
    var h = hsl[0], s = hsl[1], l = hsl[2];
    m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
    m1 = l * 2 - m2;
    return [this.hueToRGB(m1, m2, h+0.33333),
        this.hueToRGB(m1, m2, h),
        this.hueToRGB(m1, m2, h-0.33333)];
  }

  fb.hueToRGB = function (m1, m2, h) {
    h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
    if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
    if (h * 2 < 1) return m2;
    if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
    return m1;
  }

  fb.RGBToHSL = function (rgb) {
    var min, max, delta, h, s, l;
    var r = rgb[0], g = rgb[1], b = rgb[2];
    min = Math.min(r, Math.min(g, b));
    max = Math.max(r, Math.max(g, b));
    delta = max - min;
    l = (min + max) / 2;
    s = 0;
    if (l > 0 && l < 1) {
      s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
    }
    h = 0;
    if (delta > 0) {
      if (max == r && max != g) h += (g - b) / delta;
      if (max == g && max != b) h += (2 + (b - r) / delta);
      if (max == b && max != r) h += (4 + (r - g) / delta);
      h /= 6;
    }
    return [h, s, l];
  }

  // Install mousedown handler (the others are set on the document on-demand)
  $('*', e).mousedown(fb.mousedown);

    // Init color
  fb.setColor('#000000');

  // Set linked elements/callback
  if (callback) {
    fb.linkTo(callback);
  }
}


var Forms = {
  toggle_sp: function(check) {
    if ($(check) != null) {
      var checked = $(check).is(':checked');
      $('#items li.item div.service_personne').each(function() {
        if (checked) $(this).show();
        else $(this).hide();
      });
    }
    return true;
  },
  normalize_float: function(val) {
    if (m=val.match(/^(.*)[\.\,]([0-9]*)$/im)) {
      return parseFloat(m[1].replace(/[^0-9-]+/, '') + "." + m[2]);
    }
    else {
      return parseFloat(val.replace(/[^0-9-]+/, ''));
    }
  },
  update_price: function(dom_id) {
    var blk = $(dom_id).closest('li');
    var unit = Forms.normalize_float($(blk).find('input.unit_price').val());
    var qty = Forms.normalize_float($(blk).find('input.quantity').val());
    try { $(blk).find('div.total').html((qty * unit).toFixed(2)); } catch(e) {};
    Forms.update_total();
  },
  update_total:function() {
    var total = $('#items li.item').inject(0, function(acc) { 
      if ($(this).hasClass('destroyed')) return acc;
      try {
        var unit = Forms.normalize_float($(this).find('input.unit_price').val());
        var qty = Forms.normalize_float($(this).find('input.quantity').val());
        return (acc + (qty * unit));
      }
      catch(e) {
        return acc;
      }
    });
    try {
      var reduc = Forms.normalize_float($('#rebate').find('input').val());
      $('#sub_total').html(total.toFixed(2));
      $('#grand_total').html((total * (1-reduc/100)).toFixed(2));
    } catch(e) {};
  },
  quick_invoice: function() {
    var unit = Forms.normalize_float($('#quick_unit').val());
    var qty = Forms.normalize_float($('#quick_quantity').val());
    try {$('#quick_total').html((qty * unit).toFixed(2));} catch(e) {}; 
  },
  set_quick_data: function(customer_id) {
    var cid = parseInt($('#bill_customer_id option:selected').val());
    var item = QuickMode[cid];
    try {
      $('#quick_title').val(item['title']);
      $('#quick_unit').val(item['unit'].toFixed(2));
      if (item['product_id']) $('#quick_product').val(item['product_id']);
    } catch(e) {
      $('#quick_title').val('');
      $('#quick_unit').val(0.0);
      $('#quick_product').val(0);
    }
    
    try { $('#quick_nature').attr("selectedIndex", parseInt(item['nature']) - 1);} catch(e) {}
    Forms.quick_invoice();
    Data.set_penalties('#invoice');
    return true;
  },
  reset_quick_title: function(item) {
    if ($(item).attr("selectedIndex")!=0) {
      var pid = parseInt($(item).val());
      var data = Products[pid];
      $('#customer_quick_title').val(data['title']);
      $('#customer_quick_price').val(data['price']);
      $('#customer_quick_nature_'+data['nature']).att("checked", true);
    }
    else {
      $('#customer_quick_title').val('');
      $('#customer_quick_price').val(0);
    }
  },
  reset_quick_product: function(item) {
    if (item.val() !='') $('#customer_product_id').attr("selectedIndex", 0);
  },
  delete_item: function(el) {
    if (hidden_input = $(el).prev("input[type=hidden]")) {
      hidden_input.val('1');
      var item = $(el).closest('li.item');
      item.addClass("destroyed");
      item.hide();
    }
    Forms.update_total();
  },
  ask_ttc: function(dom_id) {
    var blk = $(dom_id).closest('li');
    var item = blk.find('select.vat');
    console.log(item);
    var vat = Forms.normalize_float(item.val());
    var ht = Forms.normalize_float(blk.find('input.unit_price').val());

    var ttc = prompt("Vous pouvez saisir le P.U. TTC, il sera converti en P.U. HT\n(Pensez à saisir le taux de TVA au préalable)", (ht * (1+vat)).toFixed(2));
    if (ttc != null) {
      ttc = Forms.normalize_float(ttc);
      var vat = Forms.normalize_float(item.val());
      if (vat>0) {
        blk.find('input.unit_price').val((ttc/(1+vat)).toFixed(5));
      }
      else {
        blk.find('input.unit_price').val(ttc);
      }
      Forms.update_price(dom_id);
    }
  },
  acompte_ttc: function(dom_id) {
    var blk = $(dom_id).closest('.inline_form');
    var item = blk.find('select#partial_vat');
    var vat = Forms.normalize_float(item.val());
    var ht = Forms.normalize_float(blk.find('input#partial_amount').val());

    var ttc = prompt("Vous pouvez saisir le P.U. TTC, il sera converti en P.U. HT\n(Pensez à saisir le taux de TVA au préalable)", (ht * (1+vat)).toFixed(2));
    if (ttc != null) {
      ttc = Forms.normalize_float(ttc);
      var vat = Forms.normalize_float(item.val());
      if (vat>0) {
        blk.find('input#partial_amount').val((ttc/(1+vat)).toFixed(5));
      }
      else {
        blk.find('input#partial_amount').val(ttc);
      }
    }
  }
}

var Data = {
  set_or_select_value: function(item, value) {
    if (item.attr("tagName") == 'INPUT') item.val(value);
    else if (item.attr("tagName") == 'SELECT'){
      options = item.attr("options");
      for (var i = 0, length = options.length; i < length; i++) {
        if (options[i].value == value) {
          item.attr("selectedIndex", i);
          break;
        }
      }
    }
    return true;
  },
  set_penalties: function(dom_id) {
    var cid = parseInt($('#bill_customer_id').val());
    var cust = Customers[cid];
    if (typeof(cust) != 'undefined') {
      if (cust['penalty'] != null) value = cust['penalty']
      else value = Account['penalty'];
      $(dom_id + "_penalty").val(value);

      if (cust['discount'] != null) value = cust['discount']
      else value = Account['discount'];
      $(dom_id + "_discount").val(value);

      if (cust['pay_before'] != null) value = cust['pay_before']
      else value = Account['pay_before'];
      var pb = $(dom_id + '_pay_before').first();
      Data.set_or_select_value(pb, value);

      if (cust['currency'] != null) value = cust['currency']
      else value = 'EUR';
      var pb = $(dom_id + '_currency').first();
      Data.set_or_select_value(pb, value);

      if (cust['language'] != null) value = cust['language']
      else value = 'fr';
      var pb = $(dom_id + '_language').first();
      Data.set_or_select_value(pb, value);
    }
  },
  add_product: function() {
    var select = $('#product_id');
    if (select.attr("selectedIndex") == 0) return true;
    
    var pid = parseInt(select.val());
    var data = Products[pid]; 
    var item = $('ul#items li.item').findAll(function() { 
      var title = $(this).find('textarea.title');
      return ($(title).is(':visible') && ($(title).val() == ''));
    });
    
    if (item.length == 0) {
      // we add a line
      $('#new_bill_line').click();
      item = $($('ul#items li.item').last());
    }
    else {
      item = $($(item).first());
    }
    var title = item.find('textarea.title');
    title.hide();
    title.val(data['title']);
    title.after('<span>'+ data['title'].replace(/([\r\n]+)/, '<br/>') +'</span>');

    item.find('input.product').val(pid);
    item.find('input.unit_price').val(data['price']);
    item.find('select.nature').attr("selectedIndex", parseInt(data['nature'])-1);
    
    Forms.update_price(item.find('input.unit_price'));
    
    select.attr("selectedIndex", 0);
    return false;
  },
  reset_positions: function() {
    $('#items li.item').inject(0, function(acc) { 
      try {
        $(this).find('input.position').val(acc);
        return (acc + 1); 
      }
      catch(e) { return acc; }
    });
  }
}

var Enterprise = {
  configure: function(item) {
    var klass = '';
    value = parseInt($(item).val());
    if (value == 1) klass = "me";
    else if (value == 2) klass = "entreprise";
    else if (value == 3) klass = "asso";
    else klass = 'ae';
    
    if (klass != 'ae') {
      var micro = $('#firm_with_micro_social').is(':checked');
      if (micro) klass = 'me_micro'
    }
    
    $('div.conditional').each(function() { 
      if ($(this).hasClass(klass)) $(this).show();
      else $(this).hide();
    });
  },
  immatriculation: function(ok) {
    if (ok) {
      $('#immatriculation').show();
    }
    else {
      $('#firm_siret_city').val('');
      $('#immatriculation').hide();
    }
  }
}

/* messages for firebug console */
var dmsg = (function(){
  if (typeof(console)!="undefined" && typeof(console.log)=="function") {
    return function(msg) { console.log(msg); };
  }
  return function (msg) { }
})();

$(document).ready(function() {
  $('textarea.expand').expandable();
});

