/*------------------------------------------------------------------------------
Main JS library

@dependencies:  prototype.js
@testedBrowser: Firefox 2.0+ / Opera 9 / Safari 3 / IExplorer 6, 7
@author:        Felix Vogel
@copyright      2007 Mokono GmbH
------------------------------------------------------------------------------*/ 
blog_de =
{
	/*
	 * crossbrowser solution for executing functions when DOM is Loaded
	 * thx to: Dean Edwards, Matthias Miller & John Resig
	 */
	onDomLoaded : 
	{
		// array of functions to be called
		functions : [],
		
		// adds a function to be called
		add : function (fn)
		{
			// on first call apply onDomLoaded functionality
			if (!this.functions.length) 
			{
				init = function ()
				{
					if (arguments.callee.done) return;
					arguments.callee.done = true;
					if (_timer) clearInterval(_timer);
					this.functions.each(function(fn) {fn();});
				};
				if (document.addEventListener) {document.addEventListener("DOMContentLoaded", init.bind(this), false);}
				if (/WebKit/i.test(navigator.userAgent)) {var _timer = setInterval(function() {if (/loaded|complete/.test(document.readyState)) {init.bind(blog_de.onDomLoaded)();}}, 10);}	
				window.onload = init.bind(this);
			}
			
			// add function
			this.functions.push(fn);
		}
	},

	/*
	 * inits general js functionality on all pages
	 */
	init : function ()
	{
		body = $$('body').first();
		// ie6 tweaks
		if (this.client.ie5_6)
		{
			// enable background-image cache for IE6 (thx. to Dan POPA)
			try {document.execCommand("BackgroundImageCache", false, true);} catch(e){};
			
			// apply png transparency
			$$('#guide .mascot').each(function(elem) {blog_de.ie.pngTransparency(elem, 'crop');});
		}
		
		// submit site language selection on change; remove submit button
		if ($('languageForm'))
		{
			$('languageForm_select').observe('change', function () {$('languageForm').submit();});
		}
		
		// create graphic borders for form elements
		// todo: block only safari < 3.0 
		if (!blog_de.client.safari && !blog_de.client.ie5_6)
		{
			// each flaged input element gets border & wrapper with additional classname "[type]Wrapper"
			$$('input.fText, input.fPassword').each(function(input) {input.wrap('span', {className : 'textWrapper'}).createBorder();});
			$$('input.fSubmit, input.fReset').each(function(input) {input.wrap('span', {className : input.readAttribute('type') + 'Wrapper'}).createBorder();});
			$$('input.fButton').each(function(input) {input.wrap('span', {className : 'submitWrapper'}).createBorder();});
			
			// add css hook for submitWrapper of search button
			$$('.fSearch').each(function(elem)
			{
				elem.up().addClassName('searchWrapper');
				if (blog_de.client.ie7) { blog_de.redraw(elem.up()); }
			});
			
			// each flaged textarea element gets border & wrapper with additional classname "textareaWrapper"
			$$('.fTextarea').each(function(elem) { Element.wrap(elem, 'span', {className : 'textareaWrapper'}).createBorder(); });
		}
		
		// set focus hook for formelements
		if (!blog_de.client.ie5_6) { this.initFocus(); }
		
		// rounded corner for each pageSelect
		//$$('.pageSelect').each(function(pageSelect) { if (!pageSelect.hasClassName('emptyPagiTop') && !pageSelect.hasClassName('emptyPagiBottom')) { pageSelect.createBorder(true); if (blog_de.client.opera) blog_de.redraw(pageSelect); } });
		
		// create popup layers
		if (!window.showNoHelp) // IE6 hotfix
		{
			blog_de.layer = new blog_de.Layer('layer');
			
			blog_de.layer.add(
				$$('.helpInfo'),
				function(trigger) {return trigger.innerHTML;},
				'help',
				'helpIcon',
				true
			);
			
			blog_de.layer.add(
				$$('.helpForm'),
				function(trigger) {return '<strong class="title">' + trigger.previous('dt').down('label').lastChild.nodeValue + '</strong><div class="userContent">' + trigger.innerHTML + '</div>';},
				'help helpFormLayer',
				'helpIcon',
				true
			);
		}
		
		/* Check if the user is logged in */
		//alert($$('meta[Content-Type]')); 
		
		if ( $$('body').first().hasClassName('loggedin')) { /* logged in? */
			var Tick	=	0;	// Count ajax request
			var MaxTick	=	30;	// Max ajax request allowed
			var timer = 30000;
			
			if ( $('blazeBar') ) {
				timer = 2000;
				MaxTick	=	300;
			}
			
			
			/* Its not in blog mail index page, wants to be notified */			
            if ( !$('noMSGLayer') && $$('body').first().hasClassName('msgNoti') )
			{								
				blog_de.notify = new blog_de.Notify('messageLayer');
				/* We added time param to avoid cache on explorer */
				var d = new Date();				
				var url = '/my/messages/notify.php?time='+d.getTime();
				                
				/* Onload */							
                new Ajax.Request(url, {			  
				  method: 'get',				  
				  onSuccess: function(transport) {			    			 				    
                    var json = transport.responseText.evalJSON(true);			    			 				    				    
                    if ( json != 0 ) {                        
                        blog_de.notify.show(json['css_class'], json['string']);
                    }
				  }
				})
								
				/* Every 30 seconds */				
				setInterval(function () {			
				if ( Tick >= MaxTick ) {
					return false;
				} 
				var d = new Date();	
				var url = '/my/messages/notify.php?time='+d.getTime();
				Tick++;								
				new Ajax.Request(url, {			  
				  method: 'get',				  				  
				  onSuccess: function(transport) {			    			 				    
				    var json = transport.responseText.evalJSON(true);			    			 				    				   				  				    
                    /* Check if it is the same message */
				    if ( ( json != 0 )   && (json['string'] != blog_de.notify.lastContent) ) {				    	
                        blog_de.notify.show(json['css_class'], json['string']);
				    	$('topMsgCount').innerHTML	= parseInt($('topMsgCount').innerHTML) 	+	json['count'];	// Header count				    
				    	$('topMsgCount').up().up().addClassName('unread'); 										// Add the unread class 
				  		lastjson = json['string'];
				  	}
                    /* Hide the noti */
                    if (json == 0) {
                        blog_de.notify.safehide();
                    }
				  },
				  onException: function() {
				  	blog_de.notify.safehide();
				  }
				})}, timer);
			} else {
				/* Request come from inbox */
				var url = '/my/messages/notify.php?msgPage=1';
				setInterval(function () {			
				if ( Tick >= MaxTick ) {
					return false;
				} 
				Tick++;				
				new Ajax.Request(url, {			  
				  method: 'get',				  
				  onSuccess: function(transport) {			    
				    var json = transport.responseText.evalJSON(true);				    
				    
				    /* There are messages */
				    if ( $('MsgsTable') ) {
					    new Insertion.Top('messagesList', json['string']);		 												   			    			   				    				   
					   	initTableEvents ();				   	
						if( $('mailboxCount') ) {
							$('mailboxCount').innerHTML = parseInt($('mailboxCount').innerHTML) +		json['count'];	// Count on Mailbox		// Count on Mailbox, > 0			   		
						   	} else {			   
						   		$('mailbox').innerHTML 	= $('mailbox').innerHTML +	' (<span id="mailboxCount">' + json['count'] + '</span>)';	// Count on Mailbox, from 0
						   	}			   					   			    			    			  			    
						$('topMsgCount').innerHTML		= parseInt($('topMsgCount').innerHTML) 		+	json['count'];	// Header count		
						$('topMsgCount').up().up().addClassName('unread');	 											// Add the unread class
						if ( $('totalMsgsCount') ) {
							$('totalMsgsCount').innerHTML 	= parseInt($('totalMsgsCount').innerHTML) 	+	json['count'];	// Count of total messages
						   	$('currentPageCount').innerHTML	= parseInt($('currentPageCount').innerHTML) +	json['count'];	// Count on current page
						}
					} else { /* No messages, reload*/
						location.reload();
					}					 		    	   						   
				  }
				})}, timer);	
			}
		}
		
		function googleSearch (elem_select, elem_input)
		{
			function change ()
			{
				elem_input[($F(elem_select)=='blogs' && !$F(elem_input))? 'addClassName' : 'removeClassName']('googleSearch');
			}
			
			if (elem_select && elem_input)
			{
				elem_select.onchange = elem_input.onblur = change;
				change();
			}
		}
		
		googleSearch($('searchForm_category'), $('searchForm_term'));
		googleSearch($('footerSearchForm_category'), $('footerSearchForm_term'));
	},

	Rate : function (arr_rateLinks)
	{
		var noRate = arr_rateLinks.first().up('.rateItem').hasClassName('norate'),
			loggedOut = arr_rateLinks.first().up('.rateItem').hasClassName('loggedout');
			
		arr_rateLinks.each(function(rateLink,i) {
			if (!loggedOut) {rateLink.onclick = function () {return false;};}
			if (!noRate)
			{
				Event.observe(rateLink, 'mouseover', over.bind(rateLink.up()));
				Event.observe(rateLink, 'mouseout', out.bind(rateLink.up()));
				if (!loggedOut) {Event.observe(rateLink, 'mousedown', click.bind(rateLink.up(), i+1));}
			}
		});
		
		function over ()
		{
			if (!this.up('.rateItem').hasClassName('rated'))
			{
				this.up('.rateItem').addClassName('hoverRate');
				this.previousSiblings().invoke('addClassName', 'hover');
				this.addClassName('vote');
				this.nextSiblings().invoke('removeClassName', 'hover');
			}
		}
		
		function out ()
		{
			this.up('.rateItem').removeClassName('hoverRate');
			this.previousSiblings().invoke('removeClassName', 'hover');
			this.removeClassName('vote');
		}

		function click (rateDigit)
		{
			if (!this.up('.rateItem').hasClassName('rated'))
			{
				this.up('.rateItem').addClassName('rated');
				this.up('.rateItem').removeClassName('hoverRate');
				this.previousSiblings().invoke('removeClassName', 'hover');
				this.removeClassName('vote');
				// wenn voting erfolreich:
				new Ajax.Request('/community/profile_media_options.php',
				{
					method:'get',
					parameters:'a=rate&redirect=no&item_ID=' + item_ID + '&rating=' + rateDigit,
					onSuccess: function(t)
					{
						var data = t.responseText.evalJSON();
						$$('.rateItem .count')[0].update(data.count);
						$$('.rateItem li').each(function(elm,j) {
							if (j<data.avg) {
								elm.addClassName('active');
							} else {
								elm.removeClassName('active');
							}
						});
					}
				});
			}
		}
	},

	/*
	 * 
	 * 
	 * associated styles: screenMain.css / ...
	 */
	Toggle : function (elem, str_show, str_hide, str_unit, int_rowHeight, int_rowCount, int_offset, bool_visible)
	{	
		var heightExpanded = elem.getHeight(),
			heightMinimized = int_rowHeight * int_rowCount + int_offset;
		
		// proceed if at least a whole row to toggle
		if (heightExpanded - int_rowHeight >= heightMinimized)
		{
    		// toggles between minimized & expanded
			this.toggle = function ()
    		{
    			var minimized = !(this.label.innerHTML==str_show);
				this.label.toggleClassName('expanded');
				if (window.Effect)
				{
					new Effect.Morph(
						elem,
						{
							style: 'height:' + (minimized? heightMinimized + str_unit : heightExpanded + str_unit),
							duration: .5,
							afterFinish: function () { if (blog_de.client.safari) { blog_de.redraw(elem); } } // hotfix for webkit bug
						}
					);
				}
				else { elem.style.height = minimized? heightMinimized + str_unit : heightExpanded + str_unit;}
    			this.label.update(minimized? str_show : str_hide);
				// if parent element begins above viewport, scroll it into view
				if (minimized && Position.page(elem.up())[1]<0) {window.setTimeout(function() {this.up().scrollIntoView(true);}.bind(elem), 1);}
    		};
			
            // create toggle link
		    new Insertion.After(elem, '<div class="toggle"><strong><a href="#" onclick="return false;">' + (bool_visible? str_hide : str_show) + '</a></strong></div>');

			var elemToggle = elem.next();
			this.label = elemToggle.down('a');
			
			// set overflow:hidden; minimize if bool_visible; set label classname
			elem.setStyle({height: (bool_visible? heightExpanded : heightMinimized) + str_unit, overflow: 'hidden'});
			if (bool_visible) {this.label.addClassName('expanded');}
			
			// move bottom margin & padding from elem to toggle link
			elemToggle.style.marginBottom = elem.getStyle('margin-bottom');
			elem.style.marginBottom = '0';
			elemToggle.style.paddingBottom = elem.getStyle('padding-bottom');
			elem.style.paddingBottom = '0';
			
			// register event
		    Event.observe(elemToggle, 'mousedown', this.toggle.bindAsEventListener(this));
		} 
	},
	
	createOverlay : function (str_html, str_close, str_styleUrl)
	{
		closeIt = function ()
		{
			$$('html').first().removeClassName('overlay'); 
			$$('#overlayContent, #overlayBG').invoke('remove');
		}
		
		closeIt(); // guarantee unique overlay
		$$('html').first().addClassName('overlay'); // css flag
		new Insertion.Bottom(body, '<div id="overlayBG"></div><div id="overlayContent"><div class="content"><div id="overlayClose">' + str_close + '</div>' + str_html + '</div></div>');
		Event.observe($('overlayClose'), 'click', closeIt);
		$$('#overlayContent .content').first().createBorder();
		$('overlayContent').style.top = ((window.pageYOffset || document.documentElement.scrollTop)+75)+'px'; // position 75px below viewport-top
		$('overlayBG').style.height = body.getHeight()+'px';
		if (blog_de.client.ie5_6 || blog_de.client.ie7) {$('overlayBG').style.filter = 'alpha(opacity=60)';}
	},

	Layer : function (str_id)
	{
		var layer, // layer element
			innerLayer,
			content,
			corners, // layer border corners
			borders, // layer borders
			timeout = null; // timeout id for delayed layer closing
					
		// adds elements, wich could open a layer
		this.add = function (arr_triggers, fn_getContent, str_layerClass, str_triggerClass, ieTransparency)
		{
			arr_triggers.each(function(trigger)
			{
				trigger.addClassName(str_triggerClass || 'layerTrigger');
				trigger.onmousedown = show.bindAsEventListener(this, trigger, fn_getContent, str_layerClass);
				trigger.onmouseout = initHiding.bind(this);
				if (ieTransparency && blog_de.client.ie5_6) { blog_de.ie.pngTransparency(trigger, 'scale'); }
			}.bind(this));
		}
		
		// returns layer position
		this.getPosition = function (e, trigger, direction)
		{
			layer.show(); // needed here for innerLayer.getDimensions
			var mouse = trigger.hasClassName('mouse'),	
				triggerDim = mouse? {width:0, height:0} : trigger.getDimensions(), // trigger size
				triggerPos = mouse? [Event.pointerX(e), Event.pointerY(e)] : Position.cumulativeOffset(trigger), // trigger top-left position
				layerDim = innerLayer.getDimensions(); // layer size
			
			switch (direction)
			{
				case 'topLeft' 		: return [triggerPos[0] - layerDim.width, 	triggerPos[1] - layerDim.height];
				case 'topRight' 	: return [triggerPos[0] + triggerDim.width, triggerPos[1] - layerDim.height];
				case 'bottomLeft' 	: return [triggerPos[0] - layerDim.width, 	triggerPos[1] + triggerDim.height];
				case 'bottomRight' 	: return [triggerPos[0] + triggerDim.width, triggerPos[1] + triggerDim.height];
				case 'left' 		: return [triggerPos[0] - layerDim.width, 	triggerPos[1] + (triggerDim.height - layerDim.height) / 2];
				case 'right' 		: return [triggerPos[0] + triggerDim.width, triggerPos[1] + (triggerDim.height - layerDim.height) / 2];
				case 'top' 			: return [triggerPos[0] + (triggerDim.width - layerDim.width) / 2, triggerPos[1] - layerDim.height];
				case 'bottom' 		: return [triggerPos[0] + (triggerDim.width - layerDim.width) / 2, triggerPos[1] + triggerDim.height];
				default 			: return [0, 0];
			}
		}

		// shows layer
		function show (e, trigger, fn_getContent, str_layerClass)
		{
			var layerPos; // layer top-left position
			
			if (!layer) { buildLayer(); }
			
			this.direction = ['top', 'topRight', 'right', 'bottomRight', 'bottom', 'bottomLeft', 'left', 'topLeft'].find(function(d) {return trigger.hasClassName(d);}) || 'topRight';
			
			// set opening direction flag & layer name
			layer.className = str_layerClass;
			innerLayer.className = 'inner ' + this.direction;

			// set content
			content.innerHTML = fn_getContent(trigger);

			// set position
			layerPos = this.getPosition(e, trigger, this.direction);
			if (!blog_de.client.ie5_6 || !layer.hasClassName('popup'))
			{
				layer.setStyle({left: layerPos[0]+'px', top: layerPos[1]+'px'});
				innerLayer.setStyle({left: null, top: null});
			}
			else
			{
				layer.setStyle({left: null, top: null});
				innerLayer.setStyle({left: layerPos[0]+'px', top: layerPos[1]+'px'});
			}
			// show layer
			showHelp.bind(this)();

			// ie6: refresh png transparency of corners & recalc border height
			if (blog_de.client.ie5_6)
			{
				innerLayer.down('iframe').style.height = innerLayer.getHeight() + 'px';
				
				// fix prototype bug
				content.innerHTML = content.innerHTML.replace(/ _counted="undefined"/g,'');
			}
		}
		
		// shows layer; stops delayed layer hiding;
		function showHelp ()
		{
			if (timeout) {window.clearTimeout(timeout)};
			timeout = null;
			layer.show();
		}
		
		// hides layer
		function hideHelp () {layer.hide();}
		
		// inits delayed layer hiding
		function initHiding ()
		{
			if (timeout) {window.clearTimeout(timeout)};
			timeout = window.setTimeout(hideHelp.bind(this), 750);
		}
		
		// create layer
		function buildLayer ()
		{
			new Insertion.Bottom(body, '<div id="' + str_id + '" style="display:none;"><div class="inner"><div class="content"></div>'+(blog_de.client.ie5_6? '<iframe style="filter:mask();"></iframe>' : '')+'</div></div>');
			layer = $(str_id);
			innerLayer = layer.down('.inner');
			content = innerLayer.down('.content');
			
			// create border
			if (!blog_de.client.ie5_6)
			{
				innerLayer.createBorder();
				corners = $$('#layer .topL, #layer .topR, #layer .bottomL, #layer .bottomR');
				borders = corners.concat($$('#layer .topM, #layer .middleL, #layer .middleR, #layer .bottomM'));
			}
			// add event handler for layer toggling
			innerLayer.observe( 'mouseout', initHiding.bind(this));
			innerLayer.observe( 'mouseover', showHelp.bind(this));
			if (!blog_de.client.ie5_6) corners.each(function(elem) {elem.onclick = hideHelp.bind(this);}.bind(this));
		}
	},

	// 
	Notify : function (str_id)
	{
		var layer;
		this.content;
		this.lastContent = '';
		
		this.show = function (str_class, str_content)
		{
			if (str_content != 'undefined')
			{
				this.content.innerHTML = this.lastContent = str_content;
				layer.className = str_class;
				// create border
				if (!blog_de.client.ie5_6) { layer.getElementsBySelector('input.fSubmit').each(function(input) {input.wrap('span', {className : input.readAttribute('type') + 'Wrapper'}).createBorder();}); }
				// fix z-index
				else {layer.down('iframe').style.height = layer.getHeight() + 'px';}
				var pos = ($(document.body).hasClassName('notifyTL') || $(document.body).hasClassName('notifyTR'))? 'top' : 'bottom';
				layer.style[pos] = (blog_de.client.ie5_6? (document.documentElement.scrollTop - 10) : 0) + 'px';
				layer.show();
			}
		}
		
		this.clean = function ()
		{
			var d = new Date();			
			var url = '/my/messages/cleannotify.php?time='+d.getTime();            
            new Ajax.Request(url, {
            method: 'get',            
            onSuccess: function(transport) {$('notifyForm').submit();}
            });	
		}
		this.hide = function ()
		{
			layer.hide();
			var d = new Date();			
			var url = '/my/messages/cleannotify.php?time='+d.getTime();
			new Ajax.Request(url, {
            method: 'get',
            parameters: 'clean=true',
            onSuccess: function() {}
            });
			// avoid mem leak
			if (blog_de.client.ie5_6 || blog_de.client.ie7) $A(layer.getElementsByTagName('a')).each(function(elem) { elem.onmousedown = null; });
		}
		
		/* In safehide its not needed to request for a clean notifys */
		this.safehide = function ()
		{
			layer.hide();
		
			// avoid mem leak
			if (blog_de.client.ie5_6 || blog_de.client.ie7) $A(layer.getElementsByTagName('a')).each(function(elem) { elem.onmousedown = null; });
		}
		
		// CONSTRUCTOR
		
		// create layer
		new Insertion.Bottom(document.body, '<div id="' + str_id + '" style="display:none;"><div class="content"></div>'+(blog_de.client.ie5_6? '<iframe style="filter:mask();"></iframe>' : '')+'</div>');
		layer = $(str_id);
		this.content = layer.down('.content');
		if (!blog_de.client.ie5_6) { layer.createBorder(true); }
	},

	// enforce render update
	redraw : function (elem)
	{
		var size = elem.getStyle('font-size');
		elem.setStyle({fontSize: '0'});
		window.setTimeout(function () { this.setStyle({fontSize: size}); }.bind(elem, size), 1);
	},
	
	// each formelement gets during onfocus classname focus
	initFocus: function ()
	{
		$$('input, textarea, select, button').each(function(s) {
			s.observe( 'focus', function() {$(this, this.parentNode).invoke('addClassName', 'focus');}.bind(s));
			s.observe( 'blur', function() {$(this, this.parentNode).invoke('removeClassName', 'focus');}.bind(s));
		});
	},
	
	// 
	Strings : {},
	addStrings: function (arr_strings)
	{
		arr_strings.each(function(hash)
		{
			var key = hash[0],
				value = hash[1];
			if (blog_de.Strings[key]) { alert('Warning! addStrings overwrite: ' + key); }
			else { blog_de.Strings[key] = value; }
		});
	},
	
	StaticTabs : function (elem_subNavi)
	{			
		elem_subNavi.addClassName('tabs');
		elem_subNavi.up().removeClassName('accessibility');
		elem_subNavi.immediateDescendants().each(function(li)
		{
			li.down().onclick=function(){return false;};
			li.observe( 'mousedown', activate.bind(li));
			if (li.hasClassName('active')) {activate.bind(li)();}
		});
		if (blog_de.client.ie5_6) {blog_de.ie.hover(elem_subNavi.immediateDescendants());}

		function activate ()
		{
			function id (a) {return a.href.substring(a.href.indexOf("#") + 1);}
			
			this.siblings().each(function(li)
			{
				li.removeClassName('active');
				$(id(li.down())).hide();
			});
			
			this.addClassName('active');
			$(id(this.down())).show();
			
		}	
	},

	/*
	 * new Selection([elem,...], [function (elem) {return elem.parentNode;},...]);
	 */
	Selection : function (arr_triggers, arr_targetFns, obj_options)
	{
		this.selectedName = obj_options['selectedName'] || 'active'; // className of selected targets 
		this.unselectedName = obj_options['unselectedName'] || 'inactive'; // className of unselected targets
		this.lastTrigger = obj_options['lastTrigger'] || false; // last trigger that changed selection
		this.multiselectable = obj_options['multiselectable'] || false; // true iff multiple selection possible
		this.deselectable = obj_options['deselectable'] || false; // true iff deselection possible

		// selects or deselects element by setting classname
		this.selectElem = function (element, bool_select)
		{
			element.addClassName(bool_select? this.selectedName : this.unselectedName);
			element.removeClassName(bool_select? this.unselectedName : this.selectedName);
		};

		// selects targets of elem_trigger & deselects targets of lastTrigger; (conditioned deselection if deselectable or multiselectable)
		this.select = function (elem_trigger)
		{
			if (elem_trigger)
			{
				var activate = elem_trigger != this.lastTrigger;
				
				arr_targetFns.each(function(targetFn)
				{
					// deselect targets of lastTrigger
					if (activate && this.lastTrigger && !this.multiselectable) { this.selectElem(targetFn(this.lastTrigger)); }
					// (de)select targets of elem_trigger
					if (activate || this.deselectable)
					{
						var sel = !this.deselectable || !targetFn(elem_trigger).hasClassName(this.selectedName);
						this.selectElem(targetFn(elem_trigger, sel), sel);
					}
				}.bind(this));
	
				this.lastTrigger = (activate)? elem_trigger : (this.deselectable)? false : this.lastTrigger;
			}
		};
			
		// true iff if first target of elem_trigger has class selectedName
		this.isActive = function (elem_trigger) { return arr_targetFns[0] && $(arr_targetFns[0](elem_trigger)).hasClassName(this.selectedName); };
		
		// switches between singleselection & multiselection
		this.toggleMultiple = function ()
		{
			if (this.multiselectable) { this.init(this.lastTrigger); }
			this.multiselectable = !this.multiselectable;
		};
		
		// deselects targets of all triggers, exept of elem_trigger, those targets will be selected; if elem_trigger null, all selected targets stay selected;
		this.init = function (elem_trigger)
		{
			var select = function (elem) { arr_targetFns.each(function(targetFn) { this.selectElem(targetFn(elem, true), true); }.bind(this)); },
				deselect = function (elem) { arr_targetFns.each(function(targetFn) { this.selectElem(targetFn(elem)); }.bind(this)); };
			
			arr_triggers.each(function(elem) 
			{
				// deactivate trigger & target
				if (elem_trigger != true &&
						(elem_trigger == false ||
						(elem_trigger == null && !this.isActive(elem)) ||
						(elem != elem_trigger && elem_trigger))
					)
					{ deselect.bind(this)(elem); }
				// preselected trigger
				else
				{
					select.bind(this)(elem);
					this.lastTrigger = elem;
				}
				
			}.bind(this));
		};
		
		// attach eventhandler
		arr_triggers.each(function(elem)
		{		
			elem.onmousedown=function(elem_this)
			{
				this.select(elem_this);
				return false;
			}.bind(this, elem);
			if (elem.readAttribute('href')) { elem.onclick=function() { return false; }; }
		}.bind(this));
		
		this.init(this.lastTrigger || null);
	},

	ie :
	{
		/*
		 * every element in "arr_elements" gets className "hover" while mouseover
		 */
		hover : function (arr_elements)
		{
			arr_elements.each(function(elem)
			{
				elem.observe('mouseover', function() { $(this).addClassName('hover'); }.bind(elem));
				elem.observe('mouseout', function() { $(this).removeClassName('hover'); }.bind(elem));
			});
		},
		 
		/*
		 * applies png transparency; "str_method" should be 'scale' or 'crop'
		 */
		pngTransparency : function (elem, str_method)
		{
			elem.style.backgroundImage = '';
			elem.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + blog_de.getBgURL(elem) + '",sizingMethod="' + str_method + '")';
			elem.style.background = 'none';
		},

		/*
		 * abbr support
		 */
		abbr : function ()
		{
			document.documentElement.setAttribute("xmlns:ie", "http://www.w3.org/1999/xhtml");
			body.innerHTML = body.innerHTML.replace(/<abbr/gi, "<ie:abbr").replace(/<\/abbr/gi, "</ie:abbr");
		},
		 
		/*
		 * adjust insufficient css capabilities (coeval top & bottom)
		 */
		fixborder : function (elem)
		{
			elem.down('.middleL').style.height = elem.down('.middleR').style.height = elem.getHeight() + 'px';
		}
	},
	
	getBgURL : function (elem) {return elem.getStyle('background-image').replace(/url|["()]/g, '');},
	
	/*
	 * dynamic js file load; a file is only imported once; There is an delay, until js is loaded!
	 */
	importJS: function (str_url)
	{
		// if file hasn't be included yet
		if (!$$('script[src="/script/'+str_url+'"]').size())
		{
			// create new script element in document head
			var scriptElt = document.createElement('script');
			scriptElt.type = 'text/javascript';
			scriptElt.src = '/script/' + str_url;
			document.getElementsByTagName('head')[0].appendChild(scriptElt);
		}
	},

	// browser detection
	client :
	{
		'ie5_6' : !!(window.ActiveXObject && !window.XMLHttpRequest),
		'ie7' : !!(window.ActiveXObject && window.XMLHttpRequest),
		'gecko' : !!document.getBoxObjectFor,
		'opera' : !!window.opera,
		'safari' : !!(/WebKit/i.test(navigator.userAgent))
	}
}

Element.addMethods(
{
	wrap: function(element, tagName, obj_attribs)
	{
		element = $(element);
		var wrapper = document.createElement(tagName);
		element.parentNode.replaceChild(wrapper, element);
		wrapper.appendChild(element);
		$H(obj_attribs).each(function(pair) { wrapper[pair.key] = pair.value; });
		return Element.extend(wrapper);
	},
	
	innerWrap: function(element, tagName, obj_attribs)
	{
		element = $(element);
		element.innerHTML = '<' + tagName + '>' + element.innerHTML + '</' + tagName + '>';
		$H(obj_attribs).each(function(pair) { element.down()[pair.key] = pair.value; });
		return element;
	},

	/*
	 * creates 8 spans at bottom of "elem", wich will be positioned absolute outside of "elem" as
	 * graphical border; returns "elem";
	 * associated styles: screenMain.css / createBorder
	 */
	createBorder : function (elem, noTransparency)
	{
		new Insertion.Bottom(elem, '<span class="topL"></span><span class="topR"></span><span class="topM"></span><span class="middleL"></span><span class="middleR"></span><span class="bottomL"></span><span class="bottomR"></span><span class="bottomM"></span>');	
		
		// compatibility tweak for ie6; important: has to be REALLY VISIBLE during initialisiation (use timeout)
		if (blog_de.client.ie5_6 && !noTransparency)
		{
			// apply png transparency
			for (var l=elem.lastChild, i=0; i++<8; l=l.previousSibling) { blog_de.ie.pngTransparency($(l), 'scale'); };
			// adjust insufficient css capabilities (coeval top & bottom)
			blog_de.ie.fixborder(elem);
		}

		return elem;
	}
});
