/* ------------------------------------------------------------------------
	Finnair public jQuery plugin library
	We Love jQuery
------------------------------------------------------------------------- */
(function($){

	/* ------------------------------------------------------------------------
	* Copyright (c) 2007 Tom Deater (http://www.tomdeater.com)
	* Licensed under the MIT License:
	* http://www.opensource.org/licenses/mit-license.php
	* http://www.tomdeater.com/jquery/character_counter/

	$("#myTextArea, #myTextArea2").charCounter(1000);
	$("#myTextArea").charCounter(20, {	container: "<em></em>",	classname: "counter", format: "%1 characters to go!", pulse: false, delay: 100	});
	$("#myTextArea").charCounter();
	$("#myTextArea").charCounter(50, {	container: "#counter5" });
	------------------------------------------------------------------------- */

	$.fn.charCounter = function (max, settings) {
		max = max || 100;
		settings = $.extend({
			container: "<span></span>",
			classname: "charcounter",
			format: "(%1 characters remaining)",
			pulse: true,
			delay: 0
		}, settings);
		var p, timeout;
		
		function count(el, container) {
			var tmpChars1 = "";
			var tmpChars2 = "";
			var chars = 2000;

			el = $(el);
			
			// characters left in integer
			chars = (max - el.val().length);
			// convert it to string
			chars = chars + "";
			// give it a whitespace if 4 numbers long
			if ((max - el.val().length) > 999) {
				// shift the chars one step right with whitespace after first char
				tmpChars1 = chars.charAt(0);
				tmpChars2 = tmpChars2 + chars.charAt(1);
				tmpChars2 = tmpChars2 + chars.charAt(2);
				tmpChars2 = tmpChars2 + chars.charAt(3);
				chars = tmpChars1 + "&nbsp;" + tmpChars2;
			};

			if (el.val().length > max) {
			    el.val(el.val().substring(0, max));
			    if (settings.pulse && !p) {
			    	pulse(container, true);
			    };
			};
			if (settings.delay > 0) {
				if (timeout) {
					window.clearTimeout(timeout);
				}
				timeout = window.setTimeout(function () {
					container.html(settings.format.replace(/%1/, chars));
				}, settings.delay);
			} else {
				container.html(settings.format.replace(/%1/, chars));
			}
		};
		
		function pulse(el, again) {
			if (p) {
				window.clearTimeout(p);
				p = null;
			};
			el.animate({ opacity: 0.1 }, 100, function () {
				$(this).animate({ opacity: 1.0 }, 100);
			});
			if (again) {
				p = window.setTimeout(function () { pulse(el) }, 200);
			};
		};
		
		return this.each(function () {
			var container = (!settings.container.match(/^<.+>$/)) 
				? $(settings.container) 
				: $(settings.container)
					.insertAfter(this)
					.addClass(settings.classname);
			$(this)
				.bind("keydown", function () { count(this, container); })
				.bind("keypress", function () { count(this, container); })
				.bind("keyup", function () { count(this, container); })
				.bind("focus", function () { count(this, container); })
				.bind("mouseover", function () { count(this, container); })
				.bind("mouseout", function () { count(this, container); })
				.bind("paste", function () { 
					var me = this;
					setTimeout(function () { count(me, container); }, 10);
				});
			if (this.addEventListener) {
				this.addEventListener('input', function () { count(this, container); }, false);
			};
			count(this, container);
		});
	};

	/* ------------------------------------------------------------------------
	*	VERSION: Drop Shadow jQuery Plugin 1.6  12-13-2007
	*	REQUIRES: jquery.js (1.2.1 or later) and jquery.dimensions.js
	*	SYNTAX: $(selector).dropShadow(options);  // Creates new drop shadows
	*			$(selector).redrawShadow();       // Redraws shadows on elements
	*			$(selector).removeShadow();       // Removes shadows from elements
	*			$(selector).shadowId();           // Returns an existing shadow's ID
	*	OPTIONS:
	*		left    : integer (default = 4)
	*		top     : integer (default = 4)
	*		blur    : integer (default = 2)
	*		opacity : decimal (default = 0.5)
	*		color   : string (default = "black")
	*		swap    : boolean (default = false)
	------------------------------------------------------------------------- */	
	var dropShadowZindex = 10;  //z-index counter
	$.fn.dropShadow = function(options)
	{
		// Default options
		var opt = $.extend({
			left: ($.browser.msie && $.browser.version < 7) ? 3 : 5,
			top: ($.browser.msie && $.browser.version < 7) ? 3 : 5,
			blur: ($.browser.msie && $.browser.version < 7) ? 0 : 5,
			opacity: .3,
			color: "black",
			swap: false
			}, options);
		var jShadows = $([]);  //empty jQuery collection
		
		// Loop through original elements
		this.not(".dropShadow").each(function()
		{
			var jthis = $(this);
			var shadows = [];
			var blur = (opt.blur <= 0) ? 0 : opt.blur;
			var opacity = (blur == 0) ? opt.opacity : opt.opacity / (blur * 8);
			var zOriginal = (opt.swap) ? dropShadowZindex : dropShadowZindex + 1;
			var zShadow = (opt.swap) ? dropShadowZindex + 1 : dropShadowZindex;
			
			// Create ID for shadow
			var shadowId;
			if (this.id) {
				shadowId = this.id + "_dropShadow";
			}
			else {
				shadowId = "ds" + (1 + Math.floor(9999 * Math.random()));
			}

			// Modify original element
			$.data(this, "shadowId", shadowId); //store id in expando
			$.data(this, "shadowOptions", options); //store options in expando
			jthis
				.attr("shadowId", shadowId)
				.css("zIndex", zOriginal);
			if (jthis.css("position") != "absolute") {
				jthis.css({
					position: "relative",
					zoom: 1 //for IE layout
				});
			}

			// Create first shadow layer
			bgColor = jthis.css("backgroundColor");
			if (bgColor == "rgba(0, 0, 0, 0)") bgColor = "transparent";  //Safari
			if (bgColor != "transparent" || jthis.css("backgroundImage") != "none" 
					|| this.nodeName == "SELECT" 
					|| this.nodeName == "INPUT"
					|| this.nodeName == "TEXTAREA") {		
				shadows[0] = $("<div></div>")
					.css("background", opt.color);								
			}
			else {
				shadows[0] = jthis
					.clone()
					.removeAttr("id")
					.removeAttr("name")
					.removeAttr("shadowId")
					.css("color", opt.color);
			}
			shadows[0]
				.addClass("dropShadow")
				.css({
					height: jthis.outerHeight(),
					left: blur,
					opacity: opacity,
					position: "absolute",
					top: blur,
					width: jthis.outerWidth(),
					zIndex: zShadow
				});
				
			// Create other shadow layers
			var layers = (8 * blur) + 1;
			for (i = 1; i < layers; i++) {
				shadows[i] = shadows[0].clone();
			}

			// Position layers
			var i = 1;			
			var j = blur;
			while (j > 0) {
				shadows[i].css({left: j * 2, top: 0});           //top
				shadows[i + 1].css({left: j * 4, top: j * 2});   //right
				shadows[i + 2].css({left: j * 2, top: j * 4});   //bottom
				shadows[i + 3].css({left: 0, top: j * 2});       //left
				shadows[i + 4].css({left: j * 3, top: j});       //top-right
				shadows[i + 5].css({left: j * 3, top: j * 3});   //bottom-right
				shadows[i + 6].css({left: j, top: j * 3});       //bottom-left
				shadows[i + 7].css({left: j, top: j});           //top-left
				i += 8;
				j--;
			}

			// Create container
			var divShadow = $("<div></div>")
				.attr("id", shadowId) 
				.addClass("dropShadow")
				.css({
					left: jthis.position().left + opt.left - blur,
					marginTop: jthis.css("marginTop"),
					marginRight: jthis.css("marginRight"),
					marginBottom: jthis.css("marginBottom"),
					marginLeft: jthis.css("marginLeft"),
					position: "absolute",
					top: jthis.position().top + opt.top - blur,
					zIndex: zShadow
				});

			// Add layers to container	
			for (i = 0; i < layers; i++) {
				divShadow.append(shadows[i]);
			}
			
			// Add container to DOM
			jthis.after(divShadow);

			// Add shadow to return set
			jShadows = jShadows.add(divShadow);

			// Re-align shadow on window resize
			$(window).resize(function()
			{
				try {
					divShadow.css({
						left: jthis.position().left + opt.left - blur,
						top: jthis.position().top + opt.top - blur
					});
				}
				catch(e){}
			});
			
			// Increment z-index counter
			dropShadowZindex += 2;

		});  //end each
		
		return this.pushStack(jShadows);
	};


	$.fn.redrawShadow = function()
	{
		// Remove existing shadows
		this.removeShadow();
		
		// Draw new shadows
		return this.each(function()
		{
			var shadowOptions = $.data(this, "shadowOptions");
			$(this).dropShadow(shadowOptions);
		});
	};


	$.fn.removeShadow = function()
	{
		return this.each(function()
		{
			var shadowId = $(this).shadowId();
			$("div#" + shadowId).remove();
		});
	};


	$.fn.shadowId = function()
	{
		return $.data(this[0], "shadowId");
	};


	$(function()  
	{
		// Suppress printing of shadows
		var noPrint = "<style type='text/css' media='print'>";
		noPrint += ".dropShadow{visibility:hidden;}</style>";
		$("head").append(noPrint);
	});

	/* ------------------------------------------------------------------------
	*	Pretty Comments	
	*	Developped By: Stephane Caron (http://www.no-margin-for-errors.com/projects/prettyComments/)
	*	Inspired By: The facebook textarea :)
	*	Version: 1.4
	*	Copyright: Feel free to redistribute the script/modify it, as as you leave my infos at the top.
	------------------------------------------------------------------------- */
	$.fn.prettyComments = function(settings) {
			settings = jQuery.extend({
						animate: false, /* If you set it to true, cursor will dissapear in FF3 */
						animationSpeed: 'fast', /* fast/slow/normal */
						maxHeight : 500,
						alreadyAnimated: false, /* DONT CHANGE */
						init: true /* DONT CHANGE */
					}, settings);
	
			// Create the div in which the content will be copied
			$('body').append('<div id="comment_hidden"></div>');
	
			var setCSS = function(which){
				// Init the div for the current textarea
				$("#comment_hidden").css({
					'position':'absolute',
					'top': -10000,
					'left': -10000,
					'width': $(which).width(),
					'min-height': $(which).height(),
					'font-family': $(which).css('font-family'),
					'font-size': $(which).css('font-size'),
					'line-height': $(which).css('line-height')
				});
				
				if($.browser.msie && parseFloat($.browser.version) < 7){
					$("#comment_hidden").css('height',$(which).height());
				};
			};
			
			var copyContent = function(which){
				// Convert the line feeds into BRs
				theValue = $(which).attr('value') || "";
				theValue = theValue.replace(/\n/g,'<br />');
				
				$("#comment_hidden").html(theValue + '<br />');
				
				if(!settings.init){
					if($("#comment_hidden").height() > $(which).height()){
						if($('#comment_hidden').height() > settings.maxHeight){
							$(which).css('overflow-y','scroll');
						}else{
							$(which).css('overflow-y','hidden');
							expand(which);
						};
					}else if($("#comment_hidden").height() < $(which).height()){
						if($('#comment_hidden').height() > settings.maxHeight){
							$(which).css('overflow-y','scroll');
						}else{
							$(which).css('overflow-y','hidden');
							shrink(which);
						};
					};
				};
			};
			
			var expand = function(which){
				if(settings.animate && !settings.alreadyAnimated){
					settings.alreadyAnimated = true;
					$(which).animate({'height':$("#comment_hidden").height()},settings.animationSpeed,function(){
						settings.alreadyAnimated = false;
					});
				}else if(!settings.animate && !settings.alreadyAnimated){
					$(which).height($("#comment_hidden").height());
				};
			};
			
			var shrink = function(which){
				if(settings.animate && !settings.alreadyAnimated){
					settings.alreadyAnimated = true;
					$(which).animate({'height':$("#comment_hidden").height()},settings.animationSpeed,function(){
						settings.alreadyAnimated = false;
					});
				}else{
					$(which).height($("#comment_hidden").height());
				};
			};
			
			$(this).each(function(){
				$(this).css({
					'overflow':'hidden'
				})
				.bind('keyup',function(){
					copyContent($(this));
				});
				
				// Make sure all the content in the textarea is visible
				setCSS(this);
				copyContent($(this));
				
				if($("#comment_hidden").height() > settings.maxHeight){
					$(this).css({
						'overflow-y':'scroll',
						'height':settings.maxHeight
					});
				}else{
					$(this).height($("#comment_hidden").height());
				};
				
				settings.init = false;
			});
	};
	
	/* ------------------------------------------------------------------------	
	 * jQuery Media Plugin for converting elements into rich media content.
	 * Examples and documentation at: http://malsup.com/jquery/media/
	 * Copyright (c) 2007-2008 M. Alsup
	 * Dual licensed under the MIT and GPL licenses:
	 * http://www.opensource.org/licenses/mit-license.php
	 * http://www.gnu.org/licenses/gpl.html
	 * @author: M. Alsup
	 * @version: 0.81 (06/05/2008)
	 ------------------------------------------------------------------------- */
	 $.fn.media = function(options, f1, f2) {
	    return this.each(function() {
	        if (typeof options == 'function') {
	            f2 = f1;
	            f1 = options;
	            options = {};
	        }
	        var o = getSettings(this, options);
	        // pre-conversion callback, passes original element and fully populated options
	        if (typeof f1 == 'function') f1(this, o);
	        
	        var r = getTypesRegExp();
	        var m = r.exec(o.src) || [''];
	        o.type ? m[0] = o.type : m.shift();
	        for (var i=0; i < m.length; i++) {
	            fn = m[i].toLowerCase();
	            if (isDigit(fn[0])) fn = 'fn' + fn; // fns can't begin with numbers
	            if (!$.fn.media[fn]) 
	                continue;  // unrecognized media type
	            // normalize autoplay settings
	            var player = $.fn.media[fn+'_player'];
	            if (!o.params) o.params = {};
	            if (player) {
	                var num = player.autoplayAttr == 'autostart';
	                o.params[player.autoplayAttr || 'autoplay'] = num ? (o.autoplay ? 1 : 0) : o.autoplay ? true : false;
	            }
	            var $div = $.fn.media[fn](this, o);

	            $div.css('backgroundColor', o.bgColor).width(o.width);
	            // post-conversion callback, passes original element, new div element and fully populated options
	            if (typeof f2 == 'function') f2(this, $div[0], o, player.name);
	            break;
	        }
	    });
	};

	/**
	 * Non-chainable method for adding or changing file format / player mapping
	 * @name mapFormat
	 * @param String format File format extension (ie: mov, wav, mp3)
	 * @param String player Player name to use for the format (one of: flash, quicktime, realplayer, winmedia, silverlight or iframe
	 */
	$.fn.media.mapFormat = function(format, player) {
	    if (!format || !player || !$.fn.media.defaults.players[player]) return; // invalid
	    format = format.toLowerCase();
	    if (isDigit(format[0])) format = 'fn' + format;
	    $.fn.media[format] = $.fn.media[player];
	    $.fn.media[format+'_player'] = $.fn.media.defaults.players[player];
	};

	// global defautls; override as needed
	$.fn.media.defaults = {
	    width:         400,
	    height:        400,
	    autoplay:      0,         // normalized cross-player setting
	    bgColor:       '#ffffff', // background color
	    params:        { wmode: 'transparent'},  // added to object element as param elements; added to embed element as attrs
	    attrs:         {},        // added to object and embed elements as attrs
	    flashvars:     {},        // added to flash content as flashvars param/attr
	    flashVersion:  '7',       // required flash version
	    expressInstaller: null,   // src for express installer
	    
	    // default flash video and mp3 player (@see: http://jeroenwijering.com/?item=Flash_Media_Player)
	    flvPlayer:     'mediaplayer.swf',
	    mp3Player:     'mediaplayer.swf',
	    
	    // @see http://msdn2.microsoft.com/en-us/library/bb412401.aspx
	    silverlight: {
	        inplaceInstallPrompt: 'true', // display in-place install prompt?
	        isWindowless:         'true', // windowless mode (false for wrapping markup)
	        framerate:            '24',   // maximum framerate
	        version:              '0.9',  // Silverlight version
	        onError:              null,   // onError callback
	        onLoad:               null,   // onLoad callback
	        initParams:           null,   // object init params
	        userContext:          null    // callback arg passed to the load callback
	    }
	};

	// Media Players; think twice before overriding
	$.fn.media.defaults.players = {
	    flash: {
	        name:         'flash',
	        types:        'flv,mp3,swf',
	        oAttrs:   {
	            classid:  'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000',
	            type:     'application/x-oleobject',
	            codebase: 'http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + $.fn.media.defaults.flashVersion
	        },
	        eAttrs: {
	            type:         'application/x-shockwave-flash',
	            pluginspage:  'http://www.adobe.com/go/getflashplayer'
	        }        
	    },
	    quicktime: {
	        name:         'quicktime',
	        types:        'aif,aiff,aac,au,bmp,gsm,mov,mid,midi,mpg,mpeg,mp4,m4a,psd,qt,qtif,qif,qti,snd,tif,tiff,wav,3g2,3gp',
	        oAttrs:   {
	            classid:  'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
	            codebase: 'http://www.apple.com/qtactivex/qtplugin.cab'
	        },
	        eAttrs: {
	            pluginspage:  'http://www.apple.com/quicktime/download/'
	        }
	    },
	    realplayer: {
	        name:         'real',
	        types:        'ra,ram,rm,rpm,rv,smi,smil',
	        autoplayAttr: 'autostart',
	        oAttrs:   {
	            classid:  'clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA'
	        },
	        eAttrs: {
	            type:         'audio/x-pn-realaudio-plugin',
	            pluginspage:  'http://www.real.com/player/'
	        }
	    },
	    winmedia: {
	        name:         'winmedia',
	        types:        'asf,avi,wma,wmv',
	        autoplayAttr: 'autostart',
	        oUrl:         'url',
	        oAttrs:   {
	            classid:  'clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6',
	            type:     'application/x-oleobject'
	        },
	        eAttrs: {
	            type:         $.browser.mozilla && isFirefoxWMPPluginInstalled() ? 'application/x-ms-wmp' : 'application/x-mplayer2',
	            pluginspage:  'http://www.microsoft.com/Windows/MediaPlayer/'
	        }        
	    },
	    // special cases
	    iframe: {
	        name:  'iframe',
	        types: 'html,pdf'
	    },
	    silverlight: {
	        name:  'silverlight',
	        types: 'xaml'
	    }
	};

	//
	//  everything below here is private
	//


	// detection script for FF WMP plugin (http://www.therossman.org/experiments/wmp_play.html)
	// (hat tip to Mark Ross for this script)
	function isFirefoxWMPPluginInstalled() {
	    var plugs = navigator.plugins;
	    for (i = 0; i < plugs.length; i++) {
	        var plugin = plugs[i];
	        if (plugin['filename'] == 'np-mswmp.dll')
	            return true;
	    }
	    return false;
	}

	var counter = 1;

	for (var player in $.fn.media.defaults.players) {
	    var types = $.fn.media.defaults.players[player].types;
	    $.each(types.split(','), function(i,o) {
	        if (isDigit(o[0])) o = 'fn' + o;
	        $.fn.media[o] = $.fn.media[player] = getGenerator(player);
	        $.fn.media[o+'_player'] = $.fn.media.defaults.players[player];
	    });
	};

	function getTypesRegExp() {
	    var types = '';
	    for (var player in $.fn.media.defaults.players) {
	        if (types.length) types += ',';
	        types += $.fn.media.defaults.players[player].types;
	    };
	    return new RegExp('\\.(' + types.replace(/,/g,'|') + ')\\b');
	};

	function getGenerator(player) {
	    return function(el, options) {
	        return generate(el, options, player);
	    };
	};

	function isDigit(c) {
	    return '0123456789'.indexOf(c) > -1;
	};

	// flatten all possible options: global defaults, meta, option obj
	function getSettings(el, options) {
	    options = options || {};
	    var $el = $(el);
	    var cls = el.className || '';
	    // support metadata plugin (v1.0 and v2.0)
	    var meta = $.metadata ? $el.metadata() : $.meta ? $el.data() : {};
	    meta = meta || {};
	    var w = meta.width  || parseInt(((cls.match(/w:(\d+)/)||[])[1]||0));
	    var h = meta.height || parseInt(((cls.match(/h:(\d+)/)||[])[1]||0));
	    
	    if (w) meta.width  = w;
	    if (h) meta.height = h;
	    if (cls) meta.cls = cls;

	    var a = $.fn.media.defaults;
	    var b = options;
	    var c = meta;

	    var p = { params: { bgColor: options.bgColor || $.fn.media.defaults.bgColor } };
	    var opts = $.extend({}, a, b, c);
	    $.each(['attrs','params','flashvars','silverlight'], function(i,o) {
	        opts[o] = $.extend({}, p[o] || {}, a[o] || {}, b[o] || {}, c[o] || {});
	    });

	    if (typeof opts.caption == 'undefined') opts.caption = $el.text();

	    // make sure we have a source!
	    opts.src = opts.src || $el.attr('href') || $el.attr('src') || 'unknown';
	    return opts;
	};

	//
	//  Flash Player
	//

	// generate flash using SWFObject library if possible
	$.fn.media.swf = function(el, opts) {
	    if (!window.SWFObject && !window.swfobject) {
	        // roll our own
	        if (opts.flashvars) {
	            var a = [];
	            for (var f in opts.flashvars)
	                a.push(f + '=' + opts.flashvars[f]);
	            if (!opts.params) opts.params = {};
	            opts.params.flashvars = a.join('&');
	        }
	        return generate(el, opts, 'flash');
	    }

	    var id = el.id ? (' id="'+el.id+'"') : '';
	    var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
	    var $div = $('<div' + id + cls + '>');

	    // swfobject v2+
	    if (window.swfobject) {
	        $(el).after($div).appendTo($div);
	        if (!el.id) el.id = 'movie_player_' + counter++;

	        // replace el with swfobject content
	        swfobject.embedSWF(opts.src, el.id, opts.width, opts.height, opts.flashVersion, 
	            opts.expressInstaller, opts.flashvars, opts.params, opts.attrs);
	    }
	    // swfobject < v2
	    else {
	        $(el).after($div).remove();
	        var so = new SWFObject(opts.src, 'movie_player_' + counter++, opts.width, opts.height, opts.flashVersion, opts.bgColor);
	        if (opts.expressInstaller) so.useExpressInstall(opts.expressInstaller);    

	        for (var p in opts.params)
	            if (p != 'bgColor') so.addParam(p, opts.params[p]);
	        for (var f in opts.flashvars)
	            so.addVariable(f, opts.flashvars[f]);
	        so.write($div[0]);
	    }

	    if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
	    return $div;
	};

	// map flv and mp3 files to the swf player by default
	$.fn.media.flv = $.fn.media.mp3 = function(el, opts) {
	    var src = opts.src;
	    var player = /\.mp3\b/i.test(src) ? $.fn.media.defaults.mp3Player : $.fn.media.defaults.flvPlayer;
	    opts.src = player;
	    opts.src = opts.src + '?file=' + src;
	    opts.flashvars = $.extend({}, { file: src }, opts.flashvars );
	    return $.fn.media.swf(el, opts);
	};

	//
	//  Silverlight
	//
	$.fn.media.xaml = function(el, opts) {
	    if (!window.Sys || !window.Sys.Silverlight) {
	        if ($.fn.media.xaml.warning) return;
	        $.fn.media.xaml.warning = 1;
	        alert('You must include the Silverlight.js script.');
	        return;
	    }

	    var props = {
	        width: opts.width,
	        height: opts.height,
	        background: opts.bgColor,
	        inplaceInstallPrompt: opts.silverlight.inplaceInstallPrompt,
	        isWindowless: opts.silverlight.isWindowless,
	        framerate: opts.silverlight.framerate,
	        version: opts.silverlight.version
	    };
	    var events = {
	        onError: opts.silverlight.onError,
	        onLoad: opts.silverlight.onLoad
	    };

	    var id1 = el.id ? (' id="'+el.id+'"') : '';
	    var id2 = opts.id || 'AG' + counter++;
	    // convert element to div
	    var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
	    var $div = $('<div' + id1 + cls + '>');
	    $(el).after($div).remove();
	    
	    Sys.Silverlight.createObjectEx({
	        source: opts.src,
	        initParams: opts.silverlight.initParams,
	        userContext: opts.silverlight.userContext,
	        id: id2,
	        parentElement: $div[0],
	        properties: props,
	        events: events
	    });

	    if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
	    return $div;
	};

	//
	// generate object/embed markup
	//
	function generate(el, opts, player) {
	    var $el = $(el);
	    var o = $.fn.media.defaults.players[player];
	    
	    if (player == 'iframe') {
	        var o = $('<iframe' + ' width="' + opts.width + '" height="' + opts.height + '" >');
	        o.attr('src', opts.src);
	        o.css('backgroundColor', o.bgColor);
	    }
	    else if ($.browser.msie) {
	        var a = ['<object width="' + opts.width + '" height="' + opts.height + '" '];
	        for (var key in opts.attrs)
	            a.push(key + '="'+opts.attrs[key]+'" ');
	        for (var key in o.oAttrs || {})
	            a.push(key + '="'+o.oAttrs[key]+'" ');
	        a.push('></ob'+'ject'+'>');
	        var p = ['<param name="' + (o.oUrl || 'src') +'" value="' + opts.src + '">'];
	        for (var key in opts.params)
	            p.push('<param name="'+ key +'" value="' + opts.params[key] + '">');
	        var o = document.createElement(a.join(''));
	        for (var i=0; i < p.length; i++)
	            o.appendChild(document.createElement(p[i]));
	    }
	    else {
	        var a = ['<embed width="' + opts.width + '" height="' + opts.height + '" style="display:block"'];
	        if (opts.src) a.push(' src="' + opts.src + '" ');
	        for (var key in opts.attrs)
	            a.push(key + '="'+opts.attrs[key]+'" ');
	        for (var key in o.eAttrs || {})
	            a.push(key + '="'+o.eAttrs[key]+'" ');
	        for (var key in opts.params)
	            a.push(key + '="'+opts.params[key]+'" ');
	        a.push('></em'+'bed'+'>');
	    }
	    // convert element to div
	    var id = el.id ? (' id="'+el.id+'"') : '';
	    var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
	    var $div = $('<div' + id + cls + '>');
	    $el.after($div).remove();
	    ($.browser.msie || player == 'iframe') ? $div.append(o) : $div.html(a.join(''));
	    if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
	    return $div;
	};

	/* ------------------------------------------------------------------------
	 * Metadata - jQuery plugin for parsing metadata from elements
	 * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
	 * Dual licensed under the MIT and GPL licenses:
	 *   http://www.opensource.org/licenses/mit-license.php
	 *   http://www.gnu.org/licenses/gpl.html
	------------------------------------------------------------------------- */
	/**
	 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
	 * @before $.metadata.setType("class")
	 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
	 * @desc Reads metadata from the class attribute
	 * 
	 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
	 * @before $.metadata.setType("attr", "data")
	 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
	 * @desc Reads metadata from a "data" attribute
	 * 
	 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
	 * @before $.metadata.setType("elem", "script")
	 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
	 * @desc Reads metadata from a nested script element
	 * 
	 * @param String type The encoding type
	 * @param String name The name of the attribute to be used to get metadata (optional)
	 * @cat Plugins/Metadata
	 * @descr Sets the type of encoding to be used when loading metadata for the first time
	 * @type undefined
	 * @see metadata()
	 */
	$.extend({
		metadata : {
			defaults : {
				type: 'class',
				name: 'metadata',
				cre: /({.*})/,
				single: 'metadata'
			},
			setType: function( type, name ){
				this.defaults.type = type;
				this.defaults.name = name;
			},
			get: function( elem, opts ){
				var settings = $.extend({},this.defaults,opts);
				// check for empty string in single property
				if ( !settings.single.length ) settings.single = 'metadata';
				
				var data = $.data(elem, settings.single);
				// returned cached data if it already exists
				if ( data ) return data;
				
				data = "{}";
				
				if ( settings.type == "class" ) {
					var m = settings.cre.exec( elem.className );
					if ( m )
						data = m[1];
				} else if ( settings.type == "elem" ) {
					if( !elem.getElementsByTagName )
						return undefined;
					var e = elem.getElementsByTagName(settings.name);
					if ( e.length )
						data = $.trim(e[0].innerHTML);
				} else if ( elem.getAttribute != undefined ) {
					var attr = elem.getAttribute( settings.name );
					if ( attr )
						data = attr;
				}
				
				if ( data.indexOf( '{' ) <0 )
				data = "{" + data + "}";
				
				data = eval("(" + data + ")");
				
				$.data( elem, settings.single, data );
				return data;
			}
		}
	});

	/**
	 * Returns the metadata object for the first member of the jQuery object.
	 *
	 * @name metadata
	 * @descr Returns element's metadata object
	 * @param Object opts An object contianing settings to override the defaults
	 * @type jQuery
	 * @cat Plugins/Metadata
	 */
	$.fn.metadata = function( opts ){
		return $.metadata.get( this[0], opts );
	};

	/* ------------------------------------------------------------------------
		Helper function to create hidden IFRAME so that all select options do not shine trough 
	------------------------------------------------------------------------- */
	$.fn.bgIframe = function(s) {
		// This is only for IE6
		if ( ie6= $.browser.msie && ($.browser.version == "6.0") ) {
			s = $.extend({
				top     : 'auto', // auto == .currentStyle.borderTopWidth
				left    : 'auto', // auto == .currentStyle.borderLeftWidth
				width   : 'auto', // auto == offsetWidth
				height  : 'auto', // auto == offsetHeight
				opacity : true,
				src     : 'javascript:false;'
			}, s || {});
			var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
			    html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
			               'style="display:block;position:absolute;z-index:-1;'+
				               (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
						       'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
						       'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
						       'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
						       'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
						'"/>';
			return this.each(function() {
				if ( $('> iframe.bgiframe', this).length == 0 )
					this.insertBefore( document.createElement(html), this.firstChild );
			});
		}
		return this;
	};

	$.facebox = function(data, klass) {
    $.facebox.loading()

    if (data.ajax) fillFaceboxFromAjax(data.ajax, klass)
    else if (data.image) fillFaceboxFromImage(data.image, klass)
    else if (data.div) fillFaceboxFromHref(data.div, klass)
    else if ($.isFunction(data)) data.call($)
    else $.facebox.reveal(data, klass)
  }

	/* Facebox (for jQuery)
	 * version: 1.2 (05/05/2008)
	 * @requires jQuery v1.2 or later
	 * Examples at http://famspam.com/facebox/
	 * Licensed under the MIT: http://www.opensource.org/licenses/mit-license.php
	 * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]
	 *
	 * Usage:
	 *    jQuery.facebox('some html')
	 *    jQuery.facebox('some html', 'my-groovy-style')
	 *    jQuery.facebox(function($) { 
	 *      $.get('blah.html', function(data) { $.facebox(data) })
	 *    })  
	 *    jQuery.facebox({ ajax: 'remote.html' })
	 *    jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style')
	 *    jQuery.facebox({ image: 'stairs.jpg' })
	 *    jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style')
	 *    jQuery.facebox({ div: '#box' })
	 *    jQuery.facebox({ div: '#box' }, 'my-groovy-style')
	 */
	$.facebox = function(data, klass) {
    $.facebox.loading()

    if (data.ajax) fillFaceboxFromAjax(data.ajax, klass)
    else if (data.image) fillFaceboxFromImage(data.image, klass)
    else if (data.div) fillFaceboxFromHref(data.div, klass)
    else if ($.isFunction(data)) data.call($)
    else $.facebox.reveal(data, klass)
  }

  /*
   * Public, $.facebox methods
   */

  $.extend($.facebox, {
    settings: {
      opacity      : 0.15,
      overlay      : true,
      loadingImage : '/wps/themes/html/Facelift/gfx/content/loading.gif',
      closeImage   : '/wps/themes/html/Facelift/gfx/content/closelabel.png',
      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],
      faceboxHtml  : '\
    <div id="facebox" style="display:none;"> \
      <div class="popup"> \
        <table> \
          <tbody> \
            <tr> \
              <td class="tl"/><td class="b"/><td class="tr"/> \
            </tr> \
            <tr> \
              <td class="b"/> \
              <td class="body"> \
                <div class="footer"> \
                  <a href="#" class="close"> \
                    <img src="/wps/themes/html/Facelift/gfx/content/closelabel.gif" title="close" class="close_image" /> \
                  </a> \
                </div> \
				<div class="content"> \
                </div> \
              </td> \
              <td class="b"/> \
            </tr> \
            <tr> \
              <td class="bl"/><td class="b"/><td class="br"/> \
            </tr> \
          </tbody> \
        </table> \
      </div> \
    </div>'
    },

    loading: function() {
      init()
      if ($('#facebox .loading').length == 1) return true
      showOverlay()

      $('#facebox .content').empty()
      $('#facebox .body').children().hide().end().
        append('<div class="loading"><img src="'+$.facebox.settings.loadingImage+'"/></div>')

      $('#facebox').css({
		top:  getPageScroll()[1] + (getPageHeight() / 10),
      	//top:	getPageScroll()[1] +10,
        left:	$(window).width() / 2 - 205 
      }).show().bgIframe()

      $(document).bind('keydown.facebox', function(e) {
        if (e.keyCode == 27) $.facebox.close()
        return true
      })
      $(document).trigger('loading.facebox')
    },

    reveal: function(data, klass) {
      $(document).trigger('beforeReveal.facebox')
      if (klass) $('#facebox .content').addClass(klass)
      $('#facebox .content').append(data)
      $('#facebox .loading').remove()
      $('#facebox .body').children().fadeIn('normal')
      $('#facebox').css('left', $(window).width() / 2 - ($('#facebox table').width() / 2))
      $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')
    },

    close: function() {
      $(document).trigger('close.facebox')
      return false
    }
  })

  /*
   * Public, $.fn methods
   */

  $.fn.facebox = function(settings) {
    init(settings)

    function clickHandler() {
      $.facebox.loading(true)

      // support for rel="facebox.inline_popup" syntax, to add a class
      // also supports deprecated "facebox[.inline_popup]" syntax
      var klass = this.rel.match(/facebox\[?\.(\w+)\]?/)
      if (klass) klass = klass[1]

      fillFaceboxFromHref(this.href, klass)
      return false
    }

    return this.bind('click.facebox', clickHandler)
  }

  /*
   * Private methods
   */

  // called one time to setup facebox on this page
  function init(settings) {
    if ($.facebox.settings.inited) return true
    else $.facebox.settings.inited = true

    $(document).trigger('init.facebox')
    makeCompatible()

    var imageTypes = $.facebox.settings.imageTypes.join('|')
    $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i')

    if (settings) $.extend($.facebox.settings, settings)
    $('body').append($.facebox.settings.faceboxHtml)

    var preload = [ new Image(), new Image() ]
    preload[0].src = $.facebox.settings.closeImage
    preload[1].src = $.facebox.settings.loadingImage

    $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() {
      preload.push(new Image())
      preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1')
    })

    $('#facebox .close').click($.facebox.close)
    $('#facebox .close_image').attr('src', $.facebox.settings.closeImage)
  }
  
  // getPageScroll() by quirksmode.com
  function getPageScroll() {
    var xScroll, yScroll;
    if (self.pageYOffset) {
      yScroll = self.pageYOffset;
      xScroll = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
      yScroll = document.documentElement.scrollTop;
      xScroll = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
      yScroll = document.body.scrollTop;
      xScroll = document.body.scrollLeft;	
    }
    return new Array(xScroll,yScroll) 
  }

  // Adapted from getPageSize() by quirksmode.com
  function getPageHeight() {
    var windowHeight
    if (self.innerHeight) {	// all except Explorer
      windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
      windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
      windowHeight = document.body.clientHeight;
    }
    return windowHeight
  }

  // Backwards compatibility
  function makeCompatible() {
    var $s = $.facebox.settings

    $s.loadingImage = $s.loading_image || $s.loadingImage
    $s.closeImage = $s.close_image || $s.closeImage
    $s.imageTypes = $s.image_types || $s.imageTypes
    $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml
  }

  // Figures out what you want to display and displays it
  // formats are:
  //     div: #id
  //   image: blah.extension
  //    ajax: anything else
  function fillFaceboxFromHref(href, klass) {
    // div
    if (href.match(/#/)) {
      var url    = window.location.href.split('#')
      var target = href.replace(url,'')
      $.facebox.reveal($(target).show().replaceWith("<div id='facebox_moved'></div>"), klass)

    // image
    } else if (href.match($.facebox.settings.imageTypesRegexp)) {
      fillFaceboxFromImage(href, klass)
    // ajax
    } else {
      fillFaceboxFromAjax(href, klass)
    }
  }

  function fillFaceboxFromImage(href, klass) {
    var image = new Image()
    image.onload = function() {
      $.facebox.reveal('<div class="image"><img src="' + image.src + '" /></div>', klass)
    }
    image.src = href
  }

  function fillFaceboxFromAjax(href, klass) {
    $.get(href, function(data) { $.facebox.reveal(data, klass) })
  }

  function skipOverlay() {
    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null 
  }

  function showOverlay() {
    if (skipOverlay()) return

    if ($('#facebox_overlay').length == 0) 
      $("body").append('<div id="facebox_overlay" class="facebox_hide"></div>')

    $('#facebox_overlay').hide().addClass("facebox_overlayBG")
      .css({opacity: $.facebox.settings.opacity, height:$(document).height()})
      .click(function() { $(document).trigger('close.facebox') })
      .fadeIn(200)
    return false
  }

  function hideOverlay() {
    if (skipOverlay()) return

    $('#facebox_overlay').fadeOut(200, function(){
      $("#facebox_overlay").removeClass("facebox_overlayBG")
      $("#facebox_overlay").addClass("facebox_hide") 
      $("#facebox_overlay").remove()
    })
    
    return false
  }

  /*
   * Bindings
   */

  $(document).bind('close.facebox', function() {
    $(document).unbind('keydown.facebox')
    $('#facebox').fadeOut(function() {
      if ($('#facebox_moved').length == 0) $('#facebox .content').removeClass().addClass('content')
      else $('#facebox_moved').replaceWith($('#facebox .content').children().hide())
      hideOverlay()
      $('#facebox .loading').remove()
    })
  })

	/*
	 * jQuery blockUI plugin
	 * Version 2.08 (06/11/2008)
	 * @requires jQuery v1.2.3 or later
	 *
	 * Examples at: http://malsup.com/jquery/block/
	 * Copyright (c) 2007-2008 M. Alsup
	 * Dual licensed under the MIT and GPL licenses:
	 * http://www.opensource.org/licenses/mit-license.php
	 * http://www.gnu.org/licenses/gpl.html
	 * 
	 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
	 */
	// global $ methods for blocking/unblocking the entire page
	$.blockUI   = function(opts) { install(window, opts); };
	$.unblockUI = function(opts) { remove(window, opts); };
	
	// plugin method for blocking element content
	$.fn.block = function(opts) {
		return this.each(function() {
			if ($.css(this,'position') == 'static')
				this.style.position = 'relative';
			if ($.browser.msie) 
				this.style.zoom = 1; // force 'hasLayout'
			install(this, opts);
		});
	};
	
	// plugin method for unblocking element content
	$.fn.unblock = function(opts) {
		return this.each(function() {
			remove(this, opts);
		});
	};
	
	$.blockUI.version = 2.08; // 2nd generation blocking at no extra cost!
	
	// override these in your code to change the default behavior and style
	$.blockUI.defaults = {
		// message displayed when blocking (use null for no message)
		message:  '<h3>Please wait...</h3>',
		
		// styles for the message when blocking; if you wish to disable
		// these and use an external stylesheet then do this in your code:
		// $.blockUI.defaults.css = {};
		css: { 
			padding:        0,
			margin:         0,
			width:          '30%', 
			top:            '40%', 
			left:           '35%', 
			textAlign:      'center', 
			color:          '#000', 
			border:         '3px solid #aaa',
			backgroundColor:'#fff',
			cursor:         'wait'
		},
		
		// styles for the overlay
		overlayCSS:  { 
			backgroundColor:'#000', 
			opacity:        '0.6' 
		},
		
		// z-index for the blocking overlay
		baseZ: 1000,
		
		// set these to true to have the message automatically centered
		centerX: true, // <-- only effects element blocking (page block controlled via css above)
		centerY: true,
		
		// allow body element to be stetched in ie6; this makes blocking look better
		// on "short" pages.  disable if you wish to prevent changes to the body height
		allowBodyStretch: true,
		
		// be default blockUI will supress tab navigation from leaving blocking content;
		constrainTabKey: true,
		
		// fadeOut time in millis; set to 0 to disable fadeout on unblock
		fadeOut:  400,
		
		// if true, focus will be placed in the first available input field when
		// page blocking
		focusInput: true,
		
		// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
		applyPlatformOpacityRules: true,
		
		// callback method invoked when unblocking has completed; the callback is
		// passed the element that has been unblocked (which is the window object for page
		// blocks) and the options that were passed to the unblock call:
		//     onUnblock(element, options)
		onUnblock: null
	};
	
	// private data and functions follow...
	
	var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
	var pageBlock = null;
	var pageBlockEls = [];
	
	function install(el, opts) {
		var full = (el == window);
		var msg = opts && opts.message !== undefined ? opts.message : undefined;
		opts = $.extend({}, $.blockUI.defaults, opts || {});
		opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
		var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
		msg = msg === undefined ? opts.message : msg;
	
		// remove the current block (if there is one)
		if (full && pageBlock) 
			remove(window, {fadeOut:0}); 
		
		// if an existing element is being used as the blocking content then we capture
		// its current place in the DOM (and current display style) so we can restore
		// it when we unblock
		if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
			var node = msg.jquery ? msg[0] : msg;
			var data = {};
			$(el).data('blockUI.history', data);
			data.el = node;
			data.parent = node.parentNode;
			data.display = node.style.display;
			data.position = node.style.position;
			data.parent.removeChild(node);
		}
		
		var z = opts.baseZ;
		
		// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
		// layer1 is the iframe layer which is used to supress bleed through of underlying content
		// layer2 is the overlay layer which has opacity and a wait cursor
		// layer3 is the message content that is displayed while blocking
		
		var lyr1 = ($.browser.msie) ? $('<iframe class="blockUI" style="z-index:'+ z++ +';border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="javascript:false;"></iframe>')
									: $('<div class="blockUI" style="display:none"></div>');
		var lyr2 = $('<div class="blockUI" style="z-index:'+ z++ +';cursor:wait;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
		var lyr3 = full ? $('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';position:fixed"></div>')
						: $('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute"></div>');
	
		// if we have a message, style it
		if (msg) 
			lyr3.css(css);
	
		// style the overlay
		if (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform))) 
			lyr2.css(opts.overlayCSS);
		lyr2.css('position', full ? 'fixed' : 'absolute');
		
		// make iframe layer transparent in IE
		if ($.browser.msie) 
			lyr1.css('opacity','0.0');
	
		$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
		
		// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
		var expr = $.browser.msie && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
		if (ie6 || expr) {
			// give body 100% height
			if (full && opts.allowBodyStretch && $.boxModel)
				$('html,body').css('height','100%');
	
			// fix ie6 issue when blocked element has a border width
			if ((ie6 || !$.boxModel) && !full) {
				var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
				var fixT = t ? '(0 - '+t+')' : 0;
				var fixL = l ? '(0 - '+l+')' : 0;
			}
	
			// simulate fixed position
			$.each([lyr1,lyr2,lyr3], function(i,o) {
				var s = o[0].style;
				s.position = 'absolute';
				if (i < 2) {
					full ? s.setExpression('height','document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + "px"')
						 : s.setExpression('height','this.parentNode.offsetHeight + "px"');
					full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
						 : s.setExpression('width','this.parentNode.offsetWidth + "px"');
					if (fixL) s.setExpression('left', fixL);
					if (fixT) s.setExpression('top', fixT);
				}
				else if (opts.centerY) {
					if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
					s.marginTop = 0;
				}
			});
		}
		
		// show the message
		lyr3.append(msg).show();
		if (msg && (msg.jquery || msg.nodeType))
			$(msg).show();
	
		// bind key and mouse events
		bind(1, el, opts);
			
		if (full) {
			pageBlock = lyr3[0];
			pageBlockEls = $(':input:enabled:visible',pageBlock);
			if (opts.focusInput)
				setTimeout(focus, 20);
		}
		else
			center(lyr3[0], opts.centerX, opts.centerY);
	};
	
	// remove the block
	function remove(el, opts) {
		var full = el == window;
		var data = $(el).data('blockUI.history');
		opts = $.extend({}, $.blockUI.defaults, opts || {});
		bind(0, el, opts); // unbind events
		var els = full ? $('body').children().filter('.blockUI') : $('.blockUI', el);
		
		if (full) 
			pageBlock = pageBlockEls = null;
	
		if (opts.fadeOut) {
			els.fadeOut(opts.fadeOut);
			setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
		}
		else
			reset(els, data, opts, el);
	};
	
	// move blocking element back into the DOM where it started
	function reset(els,data,opts,el) {
		els.each(function(i,o) {
			// remove via DOM calls so we don't lose event handlers
			if (this.parentNode) 
				this.parentNode.removeChild(this);
		});
		if (data && data.el) {
			data.el.style.display = data.display;
			data.el.style.position = data.position;
			data.parent.appendChild(data.el);
			$(data.el).removeData('blockUI.history');
		}
		if (typeof opts.onUnblock == 'function')
			opts.onUnblock(el,opts);
	};
	
	// bind/unbind the handler
	function bind(b, el, opts) {
		var full = el == window, $el = $(el);
		
		// don't bother unbinding if there is nothing to unbind
		if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) 
			return;
		if (!full) 
			$el.data('blockUI.isBlocked', b);
			
		// bind anchors and inputs for mouse and key events
		var events = 'mousedown mouseup keydown keypress click';
		b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);
	
	// former impl...
	//    var $e = $('a,:input');
	//    b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
	};
	
	// event handler to suppress keyboard/mouse events when blocking
	function handler(e) {
		// allow tab navigation (conditionally)
		if (e.keyCode && e.keyCode == 9) {
			if (pageBlock && e.data.constrainTabKey) {
				var els = pageBlockEls;
				var fwd = !e.shiftKey && e.target == els[els.length-1];
				var back = e.shiftKey && e.target == els[0];
				if (fwd || back) {
					setTimeout(function(){focus(back)},10);
					return false;
				}
			}
		}
		// allow events within the message content
		if ($(e.target).parents('div.blockMsg').length > 0)
			return true;
			
		// allow events for content that is not being blocked
		return $(e.target).parents().children().filter('div.blockUI').length == 0;
	};
	
	function focus(back) {
		if (!pageBlockEls) 
			return;
		var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
		if (e) 
			e.focus();
	};
	
	function center(el, x, y) {
		var p = el.parentNode, s = el.style;
		var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
		var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
		if (x) s.left = l > 0 ? (l+'px') : '0';
		if (y) s.top  = t > 0 ? (t+'px') : '0';
	};
	
	function sz(el, p) { 
		return parseInt($.css(el,p))||0; 
	};

})(jQuery);	