/**
	@preserve jquery_xtnd: Version 0.9.1 +Flash +Debounce
*/

/**
jquery_xtnd: Version 0.9.1 +Flash +Debounce

provides: 
	G8:									global namespace. will be created or extended if already set

	G8.ax_jqxtnd:				static class with general tools
	$Self(sel,scope):		new jquery-style selector
	String methods:			String objekt extensions
	jQuery methods:			jQuery extensions
	
	flowplayer flashembed included: flashembed 1.0.4
	
*/

window.G8 = window.G8 || {}; //Global Namespace: G8. extend if already available, else create

// +++ Tools +++ +++ +++ +++ +++ +++ +++
G8.ax_jqxtnd = (function ax_jqxtnd(){

/**
Class Static: 	ax_jqxtnd

package: 				eeElements.gallery

--- --- --- --- --- --- ---
provides:

	public methods:
		prxy(scope,func)
		makeDom()
		dbg()
		err()
		objectExtend(destination, source)
		escapeHtml(str)
		unescapeHtml(str)
		inputToHtml
		htmlToInput
		arrayCutFirst
		windowScrollTop
		windowScrollLeft
		readEmbedVideo
		getQueryVal
		cookie

*/

	function prxy(scope,func){
		//shortcut to $.proxy() with swapped arguments
		
		return $.proxy(func,scope);
	}
	
	function dbg(){ 		
		if(typeof console!="undefined") console.info(arguments);
		else {
			var strOut = "";
			$.each(arguments,function(key,val){
				if($.isArray(val) || typeof val=="object"){
					$.each(arguments,function(key2,val2){
						strOut += "  "+key2+":"+val2+"\n";
					});
				} else {
					strOut += val + "\n\n";
				}
			});
			//alert(strOut);
		}
	}
	
	function err(){ 		
		if(typeof console!="undefined") console.warn(arguments);
		else {
			var strOut = "ERROR:\n";
			$.each(arguments,function(key,val){
				strOut += val + "\n\n";
			});
			//alert(strOut);
		}
	}
	
	function makeDom(){ /*
	call:
	makeDom(
		"div"
		{id:xx,cl:classNames,hid:true,pos:"absolute"},
		content1,content2...); */
		
		var domType = arguments[0];
		var options = arguments[1];
		var contents = arguments[2]!=undefined? G8.ax_jqxtnd.arrayCutFirst(G8.ax_jqxtnd.arrayCutFirst(arguments)).join("") : ""; // !=undefined, damit 0 auch als content gilt (wichtig bei z.b. countern)

		var classStr = options.cl? ' class="' + options.cl + '"' : ''; //buginfo: naming nicht "class" wg. IE bug
		var idStr = options.id? ' id="'+options.id+'"' : '';
		var posStr = options.pos? 'position:'+options.pos+';' : '';
		var hiddenStr = options.hid? 'display:none;' : '';
		var styleStr = posStr!="" || hiddenStr!=""? ' style="'+posStr+hiddenStr+'"' : '';
		
		return '<'+domType+idStr+classStr+styleStr+'>'+contents+'</'+domType+'>';
	}
	
	//deise soll eignetlich weg. sattdessen nur noch makeDOM benutzen.
	function makeDiv(){ /*
	call:
	makeDiv(
		{id:xx,cl:classNames,hid:true,pos:"absolute"},
		content1,content2...); */
		
		var domType = "div";
		var options = arguments[0];
		var contents = arguments[1]!=undefined? G8.ax_jqxtnd.arrayCutFirst(arguments).join("") : ""; // !=undefined, damit 0 auch als content gilt (wichtig bei z.b. countern)

		var classStr = options.cl? ' class="' + options.cl + '"' : ''; //buginfo: naming nicht "class" wg. IE bug
		var idStr = options.id? ' id="'+options.id+'"' : '';
		var posStr = options.pos? 'position:'+options.pos+';' : '';
		var hiddenStr = options.hid? 'display:none;' : '';
		var styleStr = posStr!="" || hiddenStr!=""? ' style="'+posStr+hiddenStr+'"' : '';
		
		return '<'+domType+idStr+classStr+styleStr+'>'+contents+'</'+domType+'>';
	}

	function objectExtend(destination, source){ /*
		Native Object Extension */
		
	  for (var property in source) destination[property] = source[property];
	  return destination;
	}
		
	function escapeHtml(str){ /*
		bugfix: diese funktionen sollen eigentlich string prototyp extenden.
		geht aber nicht, weil sie irgendwo (auch in unterfunktion) $() benutzen. kontext problem? */

		return $("<div></div>").text(str).html();
	}
	
	function unescapeHtml(str){
		return $("<div></div>").html(str).text();
	}
	
	function inputToHtml(str){ /*
		wandlung von eingaben aus textfeld für html darstellung */
		
		return escapeHtml(str).nl2br().space2Nbsp();
	}
	
	function htmlToInput(str){ /*
	wandlung von html für textfeld eingabe 
	entfernt auch alle html tags AUSSER "<br />" und "$nbsp;", d.h. "Lorem <br /><a href>ipsum</a>" -> "Lorem \n ipsum" */

	  return unescapeHtml(str.br2nl().nbsp2Space());
	}
	
	function arrayCutFirst(obj){
	  var arr = $.makeArray(obj);
	  arr.shift();
	  return arr;
	}
	
	function windowScrollTop(val){ /*
		diese handelt scrollTop/ScrollLeft für die seite (wegen unterschiede $("body").scrollTop(), $("html").scrollTop(), $(document).scrollTop(), $(window).scrollTop	*/
		
		if(val)	return $("html,body").scrollTop(val);
		else {
			var doc = document.documentElement;
			var body = document.body;
	  	return doc && doc.scrollTop || body && body.scrollTop || 0;
		}
	}
	
	function windowScrollLeft(val){
		if(val)	return $("html,body").scrollLeft(val);
		else {
			var doc = document.documentElement;
			var body = document.body;
	  	return doc && doc.scrollLeft || body && body.scrollLeft || 0;
		}
	}
	
	function readEmbedVideo(par){ /*
	liest aus obj oder string dimensions und src (für <object>, <embed>).
	
	par kann sein:
	 jObj: 						$('<object><embed>...')
	 markup string:		"<object><embed>"
	 direct url:			"http://www.youtube.com?v=123" */
	
	/*
	--- Für diese funzt (markup oder direct link): ---
	www.youtube.com
		-DIRECT: http://www.youtube.com/watch?v=[VIDEOID]
		-EMBED MARKUP: <object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/xlRPDhuX1DY&hl=de&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/xlRPDhuX1DY&hl=de&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>
		->EMBED SRC: http://www.youtube.com/v/[VIDEOID]&hl=de&fs=1
		->THUMBNAIL: http://img.youtube.com/vi/[VIDEOID]/default.jpg oder http://img.youtube.com/vi/[VIDEOID]/   1.jpg,2.jpg,3.jpg
	info: hänge &fs=1 an, damit fullscreen button angezeigt wird!
	
	www.youtube-nocookie.com
		gleiches format wie youtube.com, aber www.youtube-nocookie.com domain
	
	www.tudou.com
		-"FLASH EXTERN LINK" (=so ähnlich wie EMBED): http://www.tudou.com/v/uGV8409kesY
	
	video.aol.com
		-EMBED MARKUP: <object width='400' height='300'><param name='movie' value='http://www.cbs.com/e/Zv0WuHjnuNNvIfP_upkx3EZUuI6K8PCl/aol/1/'></param><param name='allowFullScreen' value='true'></param><param name='allowScriptAccess' value='always'></param><embed width='400' height='300' src='http://www.cbs.com/e/Zv0WuHjnuNNvIfP_upkx3EZUuI6K8PCl/aol/1/'  allowfullscreen='true' allowScriptAccess='always' type='application/x-shockwave-flash'></embed></object>
	
	www.veoh.com
		-DIRECT: http://www.veoh.com/IRGENDWAS/IRGENDWAS.../watch/[VIDEOID]
		direct to embed geht noch nicht
		-EMBED MARKUP: <object width="410" height="341" id="veohFlashPlayer" name="veohFlashPlayer"><param name="movie" value="http://www.veoh.com/static/swf/webplayer/WebPlayer.swf?version=AFrontend.5.4.2.21.1002&permalinkId=[VIDEOID]&player=videodetailsembedded&videoAutoPlay=0&id=anonymous"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.veoh.com/static/swf/webplayer/WebPlayer.swf?version=AFrontend.5.4.2.21.1002&permalinkId=e41596&player=videodetailsembedded&videoAutoPlay=0&id=anonymous" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="410" height="341" id="veohFlashPlayerEmbed" name="veohFlashPlayerEmbed"></embed></object><br /><font size="1">Watch <a href="http://www.veoh.com/browse/videos/category/entertainment/watch/e41596">The Last Woman on Earth</a> in <a href="http://www.veoh.com/browse/videos/category/entertainment">Unterhaltung</a>&nbsp;&nbsp;|&nbsp;&nbsp;View More <a href="http://www.veoh.com">Free Videos Online at Veoh.com</a></font>
	
	vids.myspace.com
		-DIRECT: http://vids.myspace.com/index.cfm?fuseaction=vids.individual&videoid=[VIDEOID]
		direct to embed: noch nicht umgesetzt
		-EMBED MARKUP:<a href="http://vids.myspace.com/index.cfm?fuseaction=vids.individual&videoid=48478127">Mini Beyonce</a><br/><object width="425px" height="360px" ><param name="allowFullScreen" value="true"/><param name="wmode" value="transparent"/><param name="movie" value="http://mediaservices.myspace.com/services/media/embed.aspx/m=48478127,t=1,mt=video,searchID=,primarycolor=,secondarycolor="/><embed src="http://mediaservices.myspace.com/services/media/embed.aspx/m=48478127,t=1,mt=video,searchID=,primarycolor=,secondarycolor=" width="425" height="360" allowFullScreen="true" type="application/x-shockwave-flash" wmode="transparent"/></object>
		->EMBED SRC: http://mediaservices.myspace.com/services/media/embed.aspx/m=[VIDEOID],t=1,mt=video,searchID=,primarycolor=,secondarycolor=
	
	www.break.com
		-EMBED MARKUP: <object width="464" height="376" id="822222" type="application/x-shockwave-flash"><param name="movie" value="http://embed.break.com/ODIyMjIy"></param><param name="allowScriptAccess" value="always"></param><embed src="http://embed.break.com/ODIyMjIy" type="application/x-shockwave-flash" allowScriptAccess=always width="464" height="376"></embed></object><br><font size=1><a href="http://www.break.com/index/crazy-car-accident-at-intersection.html">Crazy Car Accident At Intersection</a> - Watch more <a href="http://www.break.com/">Funny Videos</a></font>
	
	www.vimeo.com
		-DIRECT: http://vimeo.com/3089176
		-EMBED MARKUP:	<object width="400" height="225"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=3089176&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=3089176&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="225"></embed></object><br /><a href="http://vimeo.com/3089176">Mykonos</a> from <a href="http://vimeo.com/grandchildren">Grandchildren</a> on <a href="http://vimeo.com">Vimeo</a>.
	
	video.google.com
		-DIRECT: http://video.google.de/videoplay?docid=-2904170660301853607&hl=de
		-EMBED MARKUP:	<embed id="VideoPlayback" src="http://video.google.de/googleplayer.swf?docid=-2904170660301853607&hl=de&fs=true" style="width:400px;height:326px" allowFullScreen="true" allowScriptAccess="always" type="application/x-shockwave-flash"> </embed>
	
	www.dailymotion.com
		-DIRECT: http://www.dailymotion.com/video/x871vj_obamas-speeches-teach-english_news
		geht direct to embed conversion?
		-EMBED MARKUP:	<div><object width="480" height="381"><param name="movie" value="http://www.dailymotion.com/swf/k4YfbANpEE3q8sVL9t&related=1"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"></param><embed src="http://www.dailymotion.com/swf/k4YfbANpEE3q8sVL9t&related=1" type="application/x-shockwave-flash" width="480" height="381" allowFullScreen="true" allowScriptAccess="always"></embed></object><br /><b><a href="http://www.dailymotion.com/video/x871vj_obamas-speeches-teach-english_news">Obama's speeches teach English</a></b><br /><i>Hochgeladen von <a href="http://www.dailymotion.com/CNN_International">CNN_International</a></i></div>
	
	www.metacafe.com
		-EMBED MARKUP:	<embed src="http://www.metacafe.com/fplayer/2381956/worst_female_cycling_start_ever.swf" width="400" height="345" wmode="transparent" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowFullScreen="true"> </embed><br><font size = 1><a href="http://www.metacafe.com/watch/2381956/worst_female_cycling_start_ever/">Worst Female Cycling Start Ever</a> - <a href="http://www.metacafe.com/">Funny video clips are a click away</a></font>
	
	video.gmx.net
		-PERMALINK: http://www.gmx.net/watch/5885225
		-EMBED MARKUP:	<object style='width:470px;height:406px;' width='470' height='406' type='application/x-shockwave-flash' data='http://video.gmx.net/movie/5885225'><param name='movie' value='http://video.gmx.net/movie/5885225'></param><param name='AllowFullscreen' value='true'></param><embed src='http://video.gmx.net/movie/5885225' width='470' height='406'></embed></object><br/><a href='http://video.gmx.net/watch/5885225/Nackt_an_der_Tankstelle' title='Nackt an der Tankstelle - GMX Video'>Nackt an der Tankstelle - GMX Video</a>
	
	video.web.de:
		-DIRECT: http://video.web.de/watch/5863839/hammer_pool_trick
		-EMBED MARKUP:	<object style='width:470px;height:406px;' width='470' height='406' type='application/x-shockwave-flash' data='http://video.web.de/movie/5863839'><param name='movie' value='http://video.web.de/movie/5863839'></param><param name='AllowFullscreen' value='true'></param><embed src='http://video.web.de/movie/5863839' width='470' height='406'></embed></object><br/><a href='http://video.web.de/watch/5863839/hammer_pool_trick' title='hammer pool trick - WEB.DE Video'>hammer pool trick - WEB.DE Video</a>
	
	liveleak.com
		-DIRECT: http://www.liveleak.com/view?i=1f6_1233641924
		-EMBED MARKUP: <object width="450" height="370"><param name="movie" value="http://www.liveleak.com/e/1f6_1233641924"></param><param name="wmode" value="transparent"></param><embed src="http://www.liveleak.com/e/1f6_1233641924" type="application/x-shockwave-flash" wmode="transparent" width="450" height="370"></embed></object>
	
	www.viddler.com
		-DIRECT: http://www.viddler.com/explore/failblog/videos/250/
		-EMBED MARKUP: <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="437" height="333" id="viddler_44fda3cc"><param name="movie" value="http://www.viddler.com/player/44fda3cc/" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><embed src="http://www.viddler.com/player/44fda3cc/" width="437" height="333" type="application/x-shockwave-flash" allowScriptAccess="always" allowFullScreen="true" name="viddler_44fda3cc"></embed></object>
		
	juggling.tv
		-EMBED MARKUP: <embed src="http://juggling.tv/nvplayer.swf?config=http://juggling.tv/nuevo/econfig.php?key=36a8c2d8bd3fa91ad3ac" width="488" height="414" wmode="transparent" allowscriptaccess="always" allowfullscreen="false" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" /></embed>
	*/
		//defaults:
		var dataState = false; // false / "ok" / "notSupported"(wenn provider nicht zulässig)
		var supportedProviders = [
			"www.youtube.com","www.youtube-nocookie.com",
			"video.gmx.net","www.gmx.net",
			"video.web.de",
			"www.liveleak.com",
			"www.metacafe.com",
			"video.google.com",
			"www.vimeo.com","vimeo.com",
			"vids.myspace.com","mediaservices.myspace.com",
			"www.break.com","embed.break.com",
			"www.veoh.com",
			"www.tudou.com",
			"video.aol.com","www.cbs.com",
			"www.dailymotion.com",
			"www.viddler.com",
			"juggling.tv"
		];
		var defaultVideoW = "348";
		var defaultVideoH = "282";
		var testObj,videoUrl,videoW,videoH,videoFlashVars;
		var thumbnailSrcs = [];
		var mode = "MarkupObj"; //default
		//ist es direkte URL?
		if(typeof par=="string") if(!par.hasStr("<")) mode = "Url";
		//--- object/markup: dimensions & src lesen
		if(mode == "MarkupObj") {
			var obj = $(par);
			//--- try read from <embed>
			testObj = $Self("embed",obj);
			if(testObj.length){
				videoUrl = testObj.attr("src");
				videoW = testObj.attr("width");
				videoH = testObj.attr("height");
				videoFlashVars = testObj.attr("flashVars");
			//-- try read form <object>
			} else {
				testObj = $Self("object",obj);
				if(testObj.length){
					//aus <object> lesen
					videoUrl = testObj.attr("data");
					videoW = testObj.attr("width");
					videoH = testObj.attr("height");
					//aus <param> lesen
					if(videoUrl=="") videoUrl = testObj.find("param[name='movie']").attr("value");
					videoFlashVars = testObj.find("param[name='FlashVars']").attr("value");
				}
			}
			//correct: z.b. google schreibt dimensions per style
			if(!videoW) videoW = testObj.css("width").stripCssUnit();
			if(!videoH) videoH = testObj.css("height").stripCssUnit();
			//wenn immer noch keine angabe: benutze default
			if(!videoW) videoW = defaultVideoW;
			if(!videoH) videoH = defaultVideoH;
			if(videoUrl){
				//change special youtube domain
				videoUrl = videoUrl.replace("youtube-nocookie.com","youtube.com");
				//--- read videoThumbnail src
				if(videoUrl.hasStr("youtube.com")) {
					var videoId = videoUrl.hasStr("&")? videoUrl.slice(0,videoUrl.indexOf("&")).replace("http://www.youtube.com/v/","") : videoUrl.slice(0).replace("http://www.youtube.com/v/","");
	 				thumbnailSrcs.push('http://img.youtube.com/vi/'+videoId+'/1.jpg');
	 				thumbnailSrcs.push('http://img.youtube.com/vi/'+videoId+'/2.jpg');
	 				thumbnailSrcs.push('http://img.youtube.com/vi/'+videoId+'/3.jpg');
	 				//modify video url: prevent related videos and mod color of playercontrols
	 				videoUrl = "http://www.youtube.com/v/"+videoId+"&fs=1&rel=0&color1=0x464646&color2=0xCDCDCD";
				}
			}
			
		//--- direct url: try to create embed-src from directUrl, use default dimensions/markup
		} else if(mode == "Url"){
			var str = par;
			//strip linebreaks
			var dirVideoUrl = str.stripNl();
			//add "http://"
			if(!dirVideoUrl.hasStr("http://")) dirVideoUrl = "http://"+dirVideoUrl;
			//--- translate direct url to embed url
			//youtube
			if(dirVideoUrl.hasStr("www.youtube.com")) videoUrl = dirVideoUrl.replace("www.youtube.com/watch?v=","www.youtube.com/v/");
			//vimeo
			else if(dirVideoUrl.hasStr("vimeo.com")) videoUrl = dirVideoUrl.replace("vimeo.com/","vimeo.com/moogaloop.swf?clip_id=");
			//gmx
			else if(dirVideoUrl.hasStr("video.gmx.net","www.gmx.net")) videoUrl = dirVideoUrl.replace("www.gmx.net","video.gmx.net").replace("video.gmx.net/watch","video.gmx.net/movie");
			//web.de
			else if(dirVideoUrl.hasStr("video.web.de")) videoUrl = dirVideoUrl.replace("video.web.de/watch","video.web.de/movie");
			//liveleak.com
			else if(dirVideoUrl.hasStr("www.liveleak.com")) videoUrl = dirVideoUrl.replace("www.liveleak.com/view?i=","www.liveleak.com/e/");
			//vids.myspace.com:
			else if(dirVideoUrl.hasStr("vids.myspace.com")) {
				var videoId = dirVideoUrl.match(/videoid=[^&]*/);
				if(videoId) {
					videoId = videoId[0].toString().replace("videoid=","");
					videoUrl = "http://mediaservices.myspace.com/services/media/embed.aspx/m="+videoId; }} 
			//www.veoh.com
			else if(dirVideoUrl.hasStr("www.veoh.com")) {
				var videoId = dirVideoUrl.match(/\/watch\/\S*/);
				if(videoId) {
					videoId = videoId[0].toString().replace("/watch/","");
					videoUrl = "http://www.veoh.com/static/swf/webplayer/WebPlayer.swf?permalinkId="+videoId; }}
	
			videoW = defaultVideoW;
			videoH = defaultVideoH;
		}
		//gültiges video?
		if(videoUrl==undefined || videoUrl.hasStr(" ") || !videoUrl.hasStr(".")) {
			return {dataState:false};
		} else {
			dataState = videoUrl.hasStr(supportedProviders)? "ok" : "notSupported";
			if(videoUrl.hasStr("www.youtube.com") && !videoUrl.hasStr("fs=")) videoUrl = videoUrl+"&fs=1"; //youtube: force "fs=1" for fullscreen button
			return {dataState:dataState, url:videoUrl, width:videoW, height:videoH, flashVars:videoFlashVars, thumbnailSrcs:thumbnailSrcs};
		}
	}
	
	function getQueryVal(queryKey){
		var queryStr = window.location.search.substring(1);
		var pairs = queryStr.split("&");
		var	retVal;
		$.each(pairs,function(key,val){
			var splittedPair = val.split("=");
			if(splittedPair[0]==queryKey){
				retVal = splittedPair.length>1? splittedPair[1] : "";
				return false;
			}
		});
		return retVal;
	}

	function cookie(name, value, options) {
	/**
	 * Cookie plugin
	 *
	 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
	 * Dual licensed under the MIT and GPL licenses:
	 * http://www.opensource.org/licenses/mit-license.php
	 * http://www.gnu.org/licenses/gpl.html
	
	
	 * Create a cookie with the given name and value and other optional parameters.
	 *
	 * example $.cookie('the_cookie', 'the_value');
	 * desc Set the value of a cookie.
	 * example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
	 * desc Create a cookie with all available options.
	 * example $.cookie('the_cookie', 'the_value');
	 * desc Create a session cookie.
	 * example $.cookie('the_cookie', null);
	 * desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
	 *      used when the cookie was set.
	 *
	 * param String name The name of the cookie.
	 * param String value The value of the cookie.
	 * param Object options An object literal containing key/value pairs to provide optional cookie attributes.
	 * option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
	 *                            If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
	 *                            If set to null or omitted, the cookie will be a session cookie and will not be retained
	 *                            when the the browser exits.
	 * option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
	 * option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
	 * option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
	 *                       require a secure protocol (like HTTPS).
	 * type undefined
	 *
	 * name $.cookie
	 * cat Plugins/Cookie
	 * author Klaus Hartl/klaus.hartl@stilbuero.de
	
	
	 * Get the value of a cookie with the given name.
	 *
	 * example $.cookie('the_cookie');
	 * desc Get the value of a cookie.
	 *
	 * param String name The name of the cookie.
	 * return The value of the cookie.
	 * type String
	 *
	 * name $.cookie
	 * cat Plugins/Cookie
	 * author Klaus Hartl/klaus.hartl@stilbuero.de
	 */
		
	    if (typeof value != 'undefined') { // name and value given, set cookie
	        options = options || {};
	        if (value === null) {
	            value = '';
	            options.expires = -1;
	        }
	        var expires = '';
	        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
	            var date;
	            if (typeof options.expires == 'number') {
	                date = new Date();
	                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
	            } else {
	                date = options.expires;
	            }
	            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
	        }
	        // CAUTION: Needed to parenthesize options.path and options.domain
	        // in the following expressions, otherwise they evaluate to undefined
	        // in the packed version for some reason...
	        var path = options.path ? '; path=' + (options.path) : '';
	        var domain = options.domain ? '; domain=' + (options.domain) : '';
	        var secure = options.secure ? '; secure' : '';
	        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
	    } else { // only name given, get cookie
	        var cookieValue = null;
	        if (document.cookie && document.cookie != '') {
	            var cookies = document.cookie.split(';');
	            for (var i = 0; i < cookies.length; i++) {
	                var cookie = $.trim(cookies[i]);
	                // Does this cookie string begin with the name we want?
	                if (cookie.substring(0, name.length + 1) == (name + '=')) {
	                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
	                    break;
	                }
	            }
	        }
	        return cookieValue;
	    }
	}

	//--- return public methods & properties --- --- --- --- --- --- ---
	return {
		prxy:prxy,
		makeDom:makeDom,
		makeDiv:makeDiv,
		dbg:dbg,
		err:err,
		objectExtend:objectExtend,
		escapeHtml:escapeHtml,
		unescapeHtml:unescapeHtml,
		inputToHtml:inputToHtml,
		htmlToInput:htmlToInput,
		arrayCutFirst:arrayCutFirst,
		windowScrollTop:windowScrollTop,
		windowScrollLeft:windowScrollLeft,
		readEmbedVideo:readEmbedVideo,
		getQueryVal:getQueryVal,
		cookie:cookie
	};

})();


//+++ new jQ-Style Selector +++ +++ +++ +++ +++ +++ +++
function $Self(selector,scope){ /*
	wie $, findet aber selector angewendet auf -scope childs und -scope selbst */
	
	return scope.find(selector).add(scope.filter(selector));
}


//+++ String Extension +++ +++ +++ +++ +++ +++ +++
G8.ax_jqxtnd.objectExtend(String.prototype, {

/**
String object extended

--- --- --- --- --- --- ---
provides:

	string methods:
		stripScripts
		stripTags
		truncate
		nl2br
		br2nl
		space2Nbsp
		nbsp2Space
		stripNl
		stripCssUnit
		hasStr
*/

  stripScripts: function(){
    return this.replace(new RegExp('<\s*script[^>]*>([\\S\\s]*?)<\/\s*script[^>]*>', 'img'), '');
  },

  stripTags: function(){
    return this.replace(/<\/?[^>]+>/gi, '');
  },

  truncate: function(length, truncation){
    length = length || 30;
    truncation = truncation === undefined ? '...' : truncation;
    return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this);
  },

  nl2br: function(){
  	//wandel input-zeilenumbruch in html zeilenumbruch
  	//wandel <br><br> in <br>&nbsp;<br> damit leere zeile im html angezeigt wird
    return this.replace(/(\r\n)|(\n\r)|\r|\n/g,"<br />").replace(/<br \/><br \/>/g,"<br />&nbsp;<br />");
  },

  stripNl: function(){
  	//entfernt linebreaks
    return this.replace(/(\r\n)|(\n\r)|\r|\n/g,"");
  },
  
  stripCssUnit: function(){
  	//entfernt css maÃŸeinheiten
    return parseInt(this);
  },

  br2nl: function(){
    return this.replace(/<br \/>/g,"\n").replace(/<br\/>/g,"\n").replace(/<br>/g,"\n");
  },
  	
  space2Nbsp: function(){
  	//wandel doppel-space in zwei &nbsp;
    return this.replace(/  /g,"&nbsp;&nbsp;");
  },

  nbsp2Space: function(){
    return this.replace(/&nbsp;/g," ").replace(/&#160;/g," ");
  },
  
  hasStr: function(){/*
  parameter: entweder liste von strings ("a","abcd"...) oder array (["a","abc"])
  checkt, ob heuhaufen.indexOf(mindEinerDerNeedles)!=-1. also, ob wenigstens einer der needles im heuhaufen vorkommt
  ist NICHT case sensitive */
  	var strs = $.isArray(arguments[0])? arguments[0] : arguments;
		for(var i=0; i<strs.length; i++) if(this.toLowerCase().indexOf(strs[i].toLowerCase())!=-1) return true;
		return false;
	}
	
});


//+++ jQuery Obj Extension +++ +++ +++ +++ +++ +++ +++
jQuery.fn.extend({

/**
jquery object extended

--- --- --- --- --- --- ---
provides:

	jQeury object fn methods:
		
		+++ SHOW/HIDE/EFFECTS

		fadeInXB(speed, callback)
		fadeOutXB(speed, callback)
		tglFadeInXB(speed, callback)
		tglFadeOutXB(speed, callback)
		tgl(bool)
		tglFadeIn(speed, callback)
		tglFadeOut(speed, callback)
		tglSlideDown(speed, origHeight, callback)
		tglSlideUp(speed, origHeight, callback)
		opacity(val)
		stopp()
		removeAni(speed,callback)
		
		+++ MISC
		
		inpReadVal()								-> returns val
		tglClass(cssClass,bool)
		isChildOf(parentObjs)
		isOrIsChildOf(parentObj)
		parentsSelf(selector)
		outerHtml()
		cloneAsForm(obj,opt)
		getIdFromClass(prefix)
		bindProxy(eventType,listenerFunc,scope)
		storeDiv()
		switchClassF(oldClass,newClass)
		
		+++ IMAGE/HREF/SRC
		
		switchSrc(val,newVal)
		srcF(val)
		switchHref(val,newVal)
		
		+++ POSITION/DIMENSION
		
		clonePos(obj,opts)
		left(xPos)
		top(yPos)
		moveLeft(x)
		moveTop(y)
		setPosTo(obj, param1, param2)
		totalHeight(newHeight)
		totalWidth(newWidth)
		intPadding()
		intMargin()
		intBorder()
		intCss(str)
		cloneWidth(obj,xOff)
		cloneHeight(obj,yOff)
		cloneDim(obj,opts)
		isInViewport()
		
*/

	//--- SHOW/HIDE/EFFECTS ---------------------------------
	
	fadeInXB: function(speed, callback){
		if($.browser.msie) return this.show(0, callback); //IE transparency bug: just show/hide, no animation
		else return this.fadeIn(speed, callback);
	},
	
	fadeOutXB: function(speed, callback){
		if($.browser.msie) return this.hide(0, callback); //IE transparency bug: just show/hide, no animation
		else return this.fadeOut(speed, callback);
	},
	
	tglFadeInXB: function(speed, callback){
		if($.browser.msie) return this.show(0, callback); //IE transparency bug: just show/hide, no animation
		else return this.tglFadeIn(speed, callback);
	},
	
	tglFadeOutXB: function(speed, callback){
		if($.browser.msie) return this.hide(0, callback); //IE transparency bug: just show/hide, no animation
		else return this.tglFadeOut(speed, callback);
	},

	tgl: function(bool){
	//wie toggle(switch) von jQuery eigentlich sein sollte: bool==true -> show(); bool==false -> hide()
	//(original fehlerhaft umgesetzt: -man kann nicht chainen und -manchmal funzt der toggle nicht)
	//buginfo: manchmal muss man erst show machen, dann toggle, sonst funzt es nicht. warum?
	//buginfo: nach toggle kann man nicht chain mit .toggle().end().find(nächster)... warum?

		return bool? this.show() : this.hide();
	},
	
  tglFadeIn: function(speed, callback){
  //wie fadeIn, aber geeignet für fade Toggling (z.b. item faded-out und während fading soll er wieder einfaden)

  	//methode 1: faded von 0-100
  	return this.stopp().hide().opacity(1).fadeIn(speed,callback); //opacity = ziel-opacity!

  	//methode 2: faded von IST-100
  	//return this.stopp().show().fadeTo(speed,1,callback);
  },
  
  tglFadeOut: function(speed, callback){
  	//methode 1: faded von 100-0
  	if(this.is(":visible"))	return this.stopp().show().opacity(1).fadeOut(speed,callback); //opacity = ziel-opacity!
  	//wenn nicht sichtbar: kein fade erzwingen!
  	else return this.hide();

  	//methode 2: faded von IST-0
  	//return this.stopp().show().fadeTo(speed,0,callback);
  },

  tglSlideDown: function(speed, origHeight, callback){
  //wie slideDown, aber geeignet für fade Toggling (z.b. item slide down und während sliding soll er wieder einfaden)
  //TODO: diese func ist noch billig umgesetzt. die origHeight sollte aus objekt gelesen werden (beim ersten mal wo slide passiert)
  //TODO: ausserdem sollten alle animations-arten als eine func umgesetzt werden (tglFadeIn, tglSlidedown usw. als tglFXIn("slide",speed,callback) und tglFXOut(...))

  	//methode 1: slided von 0-100
  	return this.stopp().hide().css("height",origHeight).slideDown(speed,callback);

  	//methode 2: faded von IST-100
  	//return this.stopp().show().fadeTo(speed,1,callback);
  },
  
  tglSlideUp: function(speed, origHeight, callback){
  //TODO: diese func ist noch billig umgesetzt. die origHeight sollte aus objekt gelesen werden (beim ersten mal wo slide passiert)

  	//methode 1: slided von 100-0
  	return this.stopp().show().css("height",origHeight).slideUp(speed,callback); 

  	//methode 2: faded von IST-0
  	//return this.stopp().show().fadeTo(speed,0,callback);
  },

  opacity: function(val){
  	if(val || val===0){return this.css({"opacity":val});}
    else return this.css("opacity");
  },
	
  stopp: function(){
	//wie stop, aber danach wird NICHTS ausgeführt (schreibt man kommentar in die nächste zeile, gibt es fehler im IE!!!!)????

    //return(this.queue([]).stop());
    return this.stop(true);
  },

  removeAni: function(speed,callback){
  //hide div und entfernt es dann komplett

  	var obj = this;
  	this.slideUp(speed,function(){
  		obj.remove();
  		if(callback) callback();
  	});
  	return obj;
  },


	//--- MISC ---------------------------------
	
	inpReadVal: function(){
		return $.trim(this.val());
	},
	
	tglClass: function(cssClass,bool){
	//wie toggleClass von jQuery eigentlich sein sollte: bool==true -> addClass(); bool==false -> removeClass()
	//aber jquery funzt nicht

		return bool? this.addClass(cssClass) : this.removeClass(cssClass);
	},

  //deprecated. Benutze isOrIsChildOf()
  isChildOf: function(parentObjs){
  // prüft, ob obj in parentObjs sitzt (oder selbst parentObjs ist).
  // dabei kann parentObjs mehrere objekte sein oder standard selector

  	//--- wenn selector übergeben, geht auch die standard-methode von jQuery
  	//TODO: geht noch nicht richtig. warum???
  	//if(typeof parentObjs=="string") return this.parents(parentObjs).length>0;
  	//--- prüfe manuell
  	//else {
			var retVal = false;
			var objDOM = this[0];
			$(parentObjs).each(function(){
				//schneller wenn hier direkt verglichen wird anstelle von $(this).children().andSelf() !!
				if(this==objDOM) {
					retVal = true;
					return false;
				} else {
					//TODO: teste, ob weg andersrum (also vom obj.parents() ausgehend) schneller ist
					$(this).find("*").each(function(){
						if(this==objDOM){
							retVal = true;
							return false;
						}
					});
					if(retVal) return false;
				}});
			return retVal;
		//}
  },
  
  isOrIsChildOf: function(scope){ 

  	var boolIsOrIsChild = false;
  	var thisDomObj = this[0];
  	
  	scope.each(function(){
  		var currScopeDomObj = this; //achtung: here this != jqueryMathcedObj
  		if($.contains(currScopeDomObj,thisDomObj) || currScopeDomObj==thisDomObj) {
  			boolIsOrIsChild = true;
  			return false;
  		}
  	});
  	
  	return boolIsOrIsChild;
  	
  	/*
  	//alte version:
		//prüft nur für erstes objekt aus scope!  	
  	if($.contains(scope[0],this[0]) || scope[0]==this[0]) return true;
  	else return false;
  	*/
  },

  parentsSelf: function(selector){ 
  // wie parents, schliesst sich selbst aber ein

  	return this.parents(selector).add(this.filter(selector));
  },

  outerHtml: function(){
    return $( $('<div></div>').html(this.clone())).html();
  } ,

  cloneAsForm: function(obj,opt){
  	opt = opt || {};
  	var wOff = opt.wOff || 0;
  	var hOff = opt.hOff || 0;
  	var color = opt.color || obj.css("color");
  	wOff+=6; //FF3 bug: obwohl form text exakt gleiche metrics hat und textfeld gleiche breite, flieÃŸt text bei umruch anders als im div. deshalb 3 pixel sicherheit
  	
    this.clonePos(obj).css({
    	border: 0,
      fontSize: obj.css("fontSize"),
      color: color,
      backgroundColor: "transparent", //backgroundColor: obj.css("background-color"),
      fontWeight: obj.css("font-weight"),
      fontFamily: obj.css("font-family"),
      textAlign: obj.css("text-align"),
      lineHeight: obj.css("line-height"),
      fontStyle: obj.css("font-style"),
      //textDecoration: obj.css("text-decoration"),
      width: obj.outerWidth()+wOff,
      height: obj.outerHeight()+hOff+(this.get(0).tagName=="TEXTAREA"?15:0)
      //padding: obj.css("padding")
    });

  	return this;
  },

	getIdFromClass: function(prefix){
	//lies teilstring aus class, die mit prefix beginnt(prefix enthält)
	//beispiel: findet MEINEID per getIdFromClass($(),"needle") aus <div class="text gross needleMEINEID">

  	var ret = "";
   	if(this.attr("class")){ //error handling
    	$.each(this.attr("class").split(/\s+/), function(){
       	if(this.hasStr(prefix)) ret = this.replace(prefix, "");
     	});
   	}
   	return ret;
	},

	bindProxy: function(){
	//arguments can be:
	//	eventType, listenerFunc, scope
	//	eventType, {additional:data}, listenerFunc, scope
		
		var eventType = arguments[0];
		var additionalData = !$.isFunction(arguments[1])? arguments[1] : false;
		var listenerFunc = additionalData? arguments[2] : arguments[1];
		var scope = additionalData? arguments[3] : arguments[2];
		
		if(additionalData) this.bind(eventType, additionalData, $.proxy(listenerFunc,scope));
		else this.bind(eventType, $.proxy(listenerFunc,scope));
  	
  	return this;
	},

	storeDiv: function(){
	//hängt obj in body (append) und macht display:none (soz. ausgelagert)

	  return this.appendTo("body").css({display:"none"});
	},

	switchClassF: function(oldClass,newClass){
  //ersetzt class durch andere class (neue class bekommt nur der, der alte class hatte!)
	//"switchClass" gibt es in UI, deswegen anderes naming

		this.filter("."+oldClass).removeClass(oldClass).addClass(newClass);
		return this;
  },

	//--- IMAGE/HREF/SRC ---------------------------------
	
  switchSrc: function(val,newVal){
  //ersetzt einen teil aus src="..." mit neuem string (für img-rollover)
  //val kann string oder regExp sein.

  	//TODO: wieso function(){return...} ?
    return this.attr("src", function(){return this.src.replace(val, newVal);} );
	},

  srcF: function(val){
  //setzt/liest src (einfacher shortcut)

  	if(val!=undefined) return this.attr("src",val);
  	else return this.attr("src");
	},

  switchHref: function(val,newVal){
  //ersetzt einen teil aus href="..." mit neuem string
  //val kann string oder regExp sein.
  //2do: wenn val=string -> behandel als string, sonst als regExp

  	if(typeof val == "string") val = new RegExp(val);
  	//TODO: wieso function(){return...} ?
    return this.attr("href", function(){return this.href.replace(val, newVal);} );
	},

	//--- POSITION/DIMENSION ---------------------------------
	
  clonePos: function(obj,opts){
  //windowFixed (default: false): objekt wird im fenster an der position angezeigt (für css:fixed)
  	
  	opts = opts || {};
  	var xOff = opts.xOff || 0;
  	var yOff = opts.yOff || 0;
  	
  	//special:
  	var windowFixed = opts.windowFixed===undefined? false : opts.windowFixed;
  	if(windowFixed) {
    	this.css({
      	left:obj.offset().left-$(window).scrollLeft()+xOff,
      	top:obj.offset().top-$(window).scrollTop()+yOff
    	});
  	
  	//normal
  	} else {  		
  		this.setPosTo(obj,["LEFTI",xOff],["TOPI",yOff]);
  	}
  	
  	return this;
  	/*
  	opts = opts || {};
  	var windowFixed = opts.windowFixed===undefined? false : opts.windowFixed;
  	var xOff = opts.xOff || 0;
  	var yOff = opts.yOff || 0;

  	if(windowFixed) {
    	this.css({
      	left:obj.offset().left-$(window).scrollLeft()+xOff,
      	top:obj.offset().top-$(window).scrollTop()+yOff
    	});
  	} else {
    	this.css({
      	left:obj.offset().left+xOff,
      	top:obj.offset().top+yOff
    	});
    }
    return this;
    */
  },

  left: function(xPos){
    if(xPos==undefined) {
    	if(this[0]==$("window")[0]) return 0; //window will else return null
    	else return this.offset().left;
    } else {
      this.css({left:xPos+"px"});
      return this;
    }
  },

  top: function(yPos){
    if(yPos==undefined) {
    	if(this[0]==$("window")[0]) return 0; //window will else return null
    	else return this.offset().top;
    } else {
      this.css({top:yPos+"px"});
      return this;
    }
  },

  moveLeft: function(x){
    return this.css({left:this.left()+x});
  },

  moveTop: function(y){
    return this.css({top:this.top()+y});
  },

  setPosTo: function(obj, param1, param2){

  //call like:
  //  setPosTo($(obj), "CENTERX");
  //  setPosTo($(obj), "CENTERX", "CENTERY");
  //  setPosTo($(obj), "CENTERX", ["BOTTOMI",-200]);
  //  setPosTo($(obj), ["CENTERX",150], "BOTTOMI");
  
  // wenn man callt:
  //  setPosTo($(window), "CENTERX", "CENTERY"); wird es zentriert auf viewport, sichtbar in der mitte egal wo gecrollt ist
  //  setPosTo($(document), "CENTERX", "CENTERY"); wird es zentriert auf document, in der mitte, also evtl. ausserhalb des viewports

  	var mode,param;
  	var par = this.parent();
  	var T = {}; //this: das objekt das ausgerichtet wird
  	var P = {}; //par: parent von T
  	var O = {}; //obj: objekt an dem ausgerichtet wird
  	O.isWindow = obj.get(0)==window;
  	O.isDocument = obj.get(0)==document;
    T.height = this.outerHeight();
    T.width = this.outerWidth();
		T.origOpacity = this.css("opacity");
		T.origDisplay = this.css("display");
		if(T.origDisplay=="none") $.browser.msie? this.css({display:"block"}) : this.css({opacity:0,display:"block"}); //show (invisble) //bugfix: IE macht probleme mit png transparency, wenn opacity hier gesetzt wird. besser weglassen
    var xOffset=0;
    var yOffset=0;
    if(this.css("left")=="auto") this.css("left","0px"); //bugfix for all browsers (except FF), if "this" has no explicit left/top setting
    if(this.css("top")=="auto") this.css("top","0px"); //bugfix for all browsers (except FF), if "this" has no explicit left/top setting
    var cssLeft = isNaN(parseFloat(this.css("left")))? 0 : parseFloat(this.css("left"));
    var cssTop = isNaN(parseFloat(this.css("top")))? 0 : parseFloat(this.css("top"));
    var thisParentOffsetX = this.left() - cssLeft;
    var thisParentOffsetY = this.top() - cssTop;
    if(T.origDisplay=="none") $.browser.msie? this.css({display:T.origDisplay}) : this.css({opacity:T.origOpacity,display:T.origDisplay});
    if(O.isWindow || O.isDocument){
	    O.left = 0; //TODO: kann bei document auch anders sein.
  	  O.top = 0;
    	O.height = obj.height();
    	O.width = obj.width();
	    O.scrollLeft = obj.scrollLeft();
  	  O.scrollTop = obj.scrollTop();
  	} else {
	    O.left = obj.left();
  	  O.top = obj.top();
    	O.height = obj.outerHeight();
    	O.width = obj.outerWidth();
	    O.scrollLeft = 0;
  	  O.scrollTop = 0;
  	}
  	var totalParams = param2? 2 : 1;
    for(var i=1; i<=totalParams; i++){ //loop through both params if provided, else only one

    	param = i==1? param1 : param2;
      
      if(typeof param=="object"){ //param is array: maybe offset is provided
        mode = param[0];
        if(param.length==2){ // offset is provided
        	if(mode=="LEFT"||mode=="LEFTI"||mode=="RIGHT"||mode=="RIGHTI"||mode=="CENTERX"){ //provided offset relates to X
        		xOffset = param[1] - thisParentOffsetX + O.scrollLeft; 
        	} else if(mode=="TOP"||mode=="TOPI"||mode=="BOTTOM"||mode=="BOTTOMI"||mode=="CENTERY"){ //provided offset relates to Y
        		yOffset = param[1] - thisParentOffsetY + O.scrollTop;
        	}
        }
      }
      
      else if(typeof param=="string"){ //param is string: no offset
      	mode = param;
     		xOffset = - thisParentOffsetX + O.scrollLeft;
     		yOffset = - thisParentOffsetY + O.scrollTop;
      }
      
      if(this.css("position")=="fixed") xOffset = yOffset = 0; //wenn this position=fixed, gibt es keinen parent offset!

      //--- positionieren
      if(mode=="CENTERX") 			this.left(O.left + Math.round((O.width - T.width)/2) + xOffset);
      else if(mode=="CENTERY") 	this.top(O.top + Math.round((O.height - T.height)/2) + yOffset);
      else if(mode=="LEFT") 		this.left(O.left - T.width + xOffset); //OUTER
      else if(mode=="LEFTI") 		this.left(O.left + xOffset); //INNER
      else if(mode=="TOP") 			this.top(O.top - T.height + yOffset);
      else if(mode=="TOPI") 		this.top(O.top + yOffset);
      else if(mode=="RIGHT") 		this.left(O.left + O.width + xOffset);
      else if(mode=="RIGHTI") 	this.left(O.left + O.width - T.width + xOffset);
      else if(mode=="BOTTOM") 	this.top(O.top + O.height + yOffset);
      else if(mode=="BOTTOMI") 	this.top(O.top + O.height - T.height + yOffset);
    }
    
    return this;
  },

  totalHeight: function(newHeight){
  //geht auch für display:none objekte
  // set: macht, dass height + padding + border = wert
  // get: return height incl. padding + border

    if (newHeight==undefined) return this.outerHeight();// return this.height() + pad + bor;
    else {
	  	var pad = this.intPadding().y;
  		var bor = this.intBorder().y;
    	return this.height(newHeight - pad - bor);
    }
  },

  totalWidth: function(newWidth){
    if(newWidth==undefined) return this.outerWidth();//return this.width() + pad + bor;
    else {
	  	var pad = this.intPadding().x;
  		var bor = this.intBorder().x;
    	return this.width(newWidth - pad - bor);
    }
  },
  
  intPadding: function(){
  	var pL = this.intCss("padding-left");
  	var pR = this.intCss("padding-right");
  	var pT = this.intCss("padding-top");
  	var pB = this.intCss("padding-bottom");
  	return {x:pL+pR, y:pT+pB};
	},

  intMargin: function(){
  	var mL = this.intCss("margin-left");
  	var mR = this.intCss("margin-right");
  	var mT = this.intCss("margin-top");
  	var mB = this.intCss("margin-bottom");
  	return {x:mL+mR, y:mT+mB};
	},

  intBorder: function(){
  	//css-schreibweise wichtig (einzig richtige!)
  	var bL = this.intCss("borderLeftWidth"); 
  	var bR = this.intCss("borderRightWidth"); 
  	var bT = this.intCss("borderTopWidth"); 
  	var bB = this.intCss("borderBottomWidth");
  	return {x:bL+bR, y:bT+bB};
	},
	
	intCss: function(str){
		return parseInt(this.css(str));
	},

  cloneWidth: function(obj,xOff){
  	xOff = xOff || 0;
    return this.totalWidth(obj.outerWidth() + xOff);
  },

  cloneHeight: function(obj,yOff){
  	yOff = yOff || 0;
    return this.totalHeight(obj.outerHeight() + yOff);
  },

  cloneDim: function(obj,opts){
  	opts = opts || {};
  	var offWidth = opts.offWidth || 0;
  	var offHeight = opts.offHeight || 0;
  	var margin = opts.margin || false;
    this.css({
      width:obj.outerWidth(margin)+offWidth+"px",
      height:obj.outerHeight(margin)+offHeight+"px"
    });
    return this;
  },

	isInViewport: function(){
 		var win = $(window);
 		var leftScroll = win.scrollLeft();
 		var topScroll = win.scrollTop();
 		var viewportHeight = win.height();
 		var viewportWidth = win.width();
 		
 		var objLeft = this.left();
 		var objRight = objLeft + this.outerWidth();
 		var objTop = this.top();
 		var objBot = objTop + this.outerHeight();
		
		//flags: -1: kleiner als viewport, 0:im viewport, 1: grÃ¶ÃŸer	als viewport
		var leftXFlag = objLeft<leftScroll ? -1 : objLeft>=leftScroll+viewportWidth ? 1 : 0;
		var rightXFlag = objRight<leftScroll ? -1 : objRight>=leftScroll+viewportWidth ? 1 : 0;
		var topYFlag = objTop<topScroll ? -1 : objTop>=topScroll+viewportHeight ? 1 : 0;
		var botYFlag = objBot<topScroll ? -1 : objBot>=topScroll+viewportHeight ? 1 : 0;
		
		//es werden 4 flags returnt (für jede seite des zu prüfenden objekts. 
		//(ausserdem wird noch die viewport breite/hÃ¶he returnt, da man diese oft braucht in verbindung mit isInViewport)
 		return {xLeft:leftXFlag,xRight:rightXFlag,yTop:topYFlag,yBot:botYFlag,viewportHeight:viewportHeight,viewportWidth:viewportWidth};
	}

});

/*
 * jquery.tools 1.1.2 - The missing UI library for the Web
 * 
 * [tools.flashembed-1.0.4]
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 * 
 * -----
 * 
 * File generated: Wed Apr 07 11:00:13 GMT 2010
 */
(function(){var e=typeof jQuery=="function";var i={width:"100%",height:"100%",allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:null,onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(e){jQuery.tools=jQuery.tools||{};jQuery.tools.flashembed={version:"1.0.4",conf:i}}function j(){if(c.done){return false}var l=document;if(l&&l.getElementsByTagName&&l.getElementById&&l.body){clearInterval(c.timer);c.timer=null;for(var k=0;k<c.ready.length;k++){c.ready[k].call()}c.ready=null;c.done=true}}var c=e?jQuery:function(k){if(c.done){return k()}if(c.timer){c.ready.push(k)}else{c.ready=[k];c.timer=setInterval(j,13)}};function f(l,k){if(k){for(key in k){if(k.hasOwnProperty(key)){l[key]=k[key]}}}return l}function g(k){switch(h(k)){case"string":k=k.replace(new RegExp('(["\\\\])',"g"),"\\$1");k=k.replace(/^\s?(\d+)%/,"$1pct");return'"'+k+'"';case"array":return"["+b(k,function(n){return g(n)}).join(",")+"]";case"function":return'"function()"';case"object":var l=[];for(var m in k){if(k.hasOwnProperty(m)){l.push('"'+m+'":'+g(k[m]))}}return"{"+l.join(",")+"}"}return String(k).replace(/\s/g," ").replace(/\'/g,'"')}function h(l){if(l===null||l===undefined){return false}var k=typeof l;return(k=="object"&&l.push)?"array":k}if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}})}function b(k,n){var m=[];for(var l in k){if(k.hasOwnProperty(l)){m[l]=n(k[l])}}return m}function a(r,t){var q=f({},r);var s=document.all;var n='<object width="'+q.width+'" height="'+q.height+'"';if(s&&!q.id){q.id="_"+(""+Math.random()).substring(9)}if(q.id){n+=' id="'+q.id+'"'}if(q.cachebusting){q.src+=((q.src.indexOf("?")!=-1?"&":"?")+Math.random())}if(q.w3c||!s){n+=' data="'+q.src+'" type="application/x-shockwave-flash"'}else{n+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'}n+=">";if(q.w3c||s){n+='<param name="movie" value="'+q.src+'" />'}q.width=q.height=q.id=q.w3c=q.src=null;for(var l in q){if(q[l]!==null){n+='<param name="'+l+'" value="'+q[l]+'" />'}}var o="";if(t){for(var m in t){if(t[m]!==null){o+=m+"="+(typeof t[m]=="object"?g(t[m]):t[m])+"&"}}o=o.substring(0,o.length-1);n+='<param name="flashvars" value=\''+o+"' />"}n+="</object>";return n}function d(m,p,l){var k=flashembed.getVersion();f(this,{getContainer:function(){return m},getConf:function(){return p},getVersion:function(){return k},getFlashvars:function(){return l},getApi:function(){return m.firstChild},getHTML:function(){return a(p,l)}});var q=p.version;var r=p.expressInstall;var o=!q||flashembed.isSupported(q);if(o){p.onFail=p.version=p.expressInstall=null;m.innerHTML=a(p,l)}else{if(q&&r&&flashembed.isSupported([6,65])){f(p,{src:r});l={MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title};m.innerHTML=a(p,l)}else{if(m.innerHTML.replace(/\s/g,"")!==""){}else{m.innerHTML="<h2>Flash version "+q+" or greater is required</h2><h3>"+(k[0]>0?"Your version is "+k:"You have no flash plugin installed")+"</h3>"+(m.tagName=="A"?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='http://www.adobe.com/go/getflashplayer'>here</a></p>");if(m.tagName=="A"){m.onclick=function(){location.href="http://www.adobe.com/go/getflashplayer"}}}}}if(!o&&p.onFail){var n=p.onFail.call(this);if(typeof n=="string"){m.innerHTML=n}}if(document.all){window[p.id]=document.getElementById(p.id)}}window.flashembed=function(l,m,k){if(typeof l=="string"){var n=document.getElementById(l);if(n){l=n}else{c(function(){flashembed(l,m,k)});return}}if(!l){return}if(typeof m=="string"){m={src:m}}var o=f({},i);f(o,m);return new d(l,o,k)};f(window.flashembed,{getVersion:function(){var m=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var l=navigator.plugins["Shockwave Flash"].description;if(typeof l!="undefined"){l=l.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var n=parseInt(l.replace(/^(.*)\..*$/,"$1"),10);var r=/r/.test(l)?parseInt(l.replace(/^.*r(.*)$/,"$1"),10):0;m=[n,r]}}else{if(window.ActiveXObject){try{var p=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7")}catch(q){try{p=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");m=[6,0];p.AllowScriptAccess="always"}catch(k){if(m[0]==6){return m}}try{p=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(o){}}if(typeof p=="object"){l=p.GetVariable("$version");if(typeof l!="undefined"){l=l.replace(/^\S+\s+(.*)$/,"$1").split(",");m=[parseInt(l[0],10),parseInt(l[2],10)]}}}}return m},isSupported:function(k){var m=flashembed.getVersion();var l=(m[0]>k[0])||(m[0]==k[0]&&m[1]>=k[1]);return l},domReady:c,asString:g,getHTML:a});if(e){jQuery.fn.flashembed=function(l,k){var m=null;this.each(function(){m=flashembed(this,l,k)});return l.api===false?this:m}}})();


/*
 * jQuery throttle / debounce - v1.1 - 3/7/2010
 * http://benalman.com/projects/jquery-throttle-debounce-plugin/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */
(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);
	
/* 
+++ New Ideas: +++ +++ +++ +++ +++ +++ +++

gute funcs von prototype.js:
-array.uniq(); //macht das mit array, was unique mit objekten macht
-anything.inspect(); //liefert debug string zurück


INFO: mod für in original-jquery:

// Get width or height on the element
//(this.length ? jQuery.css( this[0], type ) : null) :

//FLO MOD: add padding to width/height
(this.length ? jQuery.css(this[0],type)+ (type=="height"?parseInt(this.css("padding-top"))+parseInt(this.css("padding-bottom")):parseInt(this.css("padding-left"))+parseInt(this.css("padding-right"))) : null) :

*/