var Orwik = {};

//listener to disable clicks until everything is loaded
(function() {
	var isOverloaded = function(target) {
		var get = function(attr) {
			return target[attr] || target.getAttribute(attr)
		}
		if (get('target')) return true;
		switch (target.tagName.toLowerCase()) {
			case "a":
				return (get('method') || get('type'));
			case "ul":
				return (target.className.indexOf("tabs") > -1) && get('name');
		}
	}
	
	var listener = function(event) {
		if (!event) event = window.event;
		var target = event.target || event.srcElement;
		if (document.body.className.indexOf('working') > -1) {
			var el = target;
			while (!isOverloaded(el) && (el = el.parentNode) && (el != document.body));
			if (el != document.body) {
				if (event.stopPropagation) event.stopPropagation();
				else event.cancelBubble = true;
				if (event.preventDefault) event.preventDefault();
				else event.returnValue = false;
				if (target.blur) target.blur();
			}
		} else { //already loaded, remove listener
			if (document.addEventListener){
			  document.removeEventListener('click', listener, false); 
			} else if (document.attachEvent){
			  document.detachEvent('onclick', listener);
			}
		}
	}
	if (document.addEventListener){
	  document.addEventListener('click', listener, false); 
	} else if (document.attachEvent){
	  document.attachEvent('onclick', listener);
	}	
})();


using('DomReady', 'Selectors', 'Class.Extras', 'Element.Style', function() {
  console.groupEnd();
  console.group('Application');
  
	Orwik = new Hash($extend(Orwik, {
	
		initialize: function() {
			this.fireEvent('startup');
		},
		
		notify: function(msg) {
			using('JSON', 'Fx.Slide', 'Fx.Morph', function() {
				
				if (!this.roost) this.roost = $$('.flash.messages')[0];
				if (!this.roost) return;
				
				var roost = this.roost;

				var ary = [];
				if (msg) {
					if ($type(msg) == 'string') msg = (msg.charAt(0) == '{') ? JSON.decode(msg) : {'notice': msg};

					this.roost.removeClass('success');
					this.roost.removeClass('notice');
					this.roost.removeClass('error');

					Hash.each(msg, function(value, key) {
					  var message = new Element('div', {'class': 'system message ' + key}).inject(this.roost);
						var paragraph = new Element('p', {html: value, 'class': 'offset'}).inject(message);
						message.get('slide').hide().start('in')
						ary.push(message);
					}, this);
				} else {
					ary = this.roost.getChildren();
				};

				(function() {
					ary.each(function(message) {
						message.get('slide').start('out').chain(function() {
							message.getParent().dispose();
							if (!roost.getChildren().length) roost.set('html', '')
						});
					})
				}).delay(15000);

				return this.roost;
				
			}.bind(this))
		},
		
		confirm: function() {
			var params = Array.link(arguments, {options: Object.type, string: String.type, anchor: Element.type, callback: Function.type});
			
			if (!params.anchor && params.options) params.anchor = params.options.anchor;
			
			if (params.anchor) {
				params.options = $extend(params.options || {}, params.anchor.retrieve('confirm:options'), params.string ? {question: params.string} : {});
				if (params.anchor.get('confirm')) params.options.question = params.anchor.get('confirm');
			}
			
			var kls = (params.options || {}).klass || (params.options.question.match(/^(\w*):(.*)$/) ? 'Dialog' : 'Confirm');
      
			using('Window.' + kls, function() {		
				var instance = params.anchor.retrieve('confirm:instance');
				if (params.anchor && instance) {
					//if there is a confirm already on that anchor, we just set content there
					instance.removeEvents('confirm');
					instance.addEvent('confirm', instance.onConfirm.bind(instance)) //sorry
					if (params.callback) instance.addEvent('confirm', params.callback);
					instance.set(params.options);
					instance.options.anchor = params.anchor;
					instance.reanchor();
					return instance;
				}
			  params.options.classes = ['orwik', 'footerless']
				
				MUI.Window[kls].create($merge({
					anchor: params.anchor,
					animated: true
				}, params.options)).chain(function(instance) {
					if (instance.options.anchor) instance.options.anchor.store('confirm:instance', instance);
					if (params.callback) instance.addEvent('confirm', params.callback);
				});		
			});
		},
		
		prompt: function() {
			var params = Array.link(arguments, {options: Object.type, string: String.type, example: String.type, anchor: Element.type, callback: Function.type});

			var more = [];
			if (!params.options) more.push(params.options = {});
			$extend(params.options, {
				klass: 'Prompt',
				buttons: {
					'No': {
						'html': 'Cancel'
					},
					
					'Yes': {
						'html': 'Proceed'
					}
				},
				
				input: {
					'placeholder': params.options.example || params.example
				}
			});
			var instance = Orwik.confirm.apply(this, $A(arguments).concat(more));
			if (!instance) return;
			if (instance.input) instance.input.set('placeholder', params.options.example);
		},
	
		redirect: function(value) {
		  if (this.$events.redirect) {
				this.fireEvent('redirect', value);
			} else {
				Orwik.work();
				location.href = value;
			}
		},
	
		prefetch: function(src) {
			//return (Browser.Engine.Gecko) ? (new Element('link', {'rel': 'prefetch', 'src': src}).inject(document.head)) : (new Element('img', {'src': src})).inject(document.body).setStyles({'position': 'absolute',  'top': -500});
		},
	
		scroll: function(el, callback) {
			if (!el) return;
			using('Fx.Scroll', function() {
				if (!this.scroller) this.scroller = new Fx.Scroll(window, {offset: {y: -200}});
				var type = $type(el);
				switch(type) {
					case 'element': 
						var ret = this.scroller.toElement(el);
						break;
					case 'number':
						var ret = this.scroller.start(0, el);
				}
				ret.chain(function() {
				  if (type == "element") (function() {
				    var instance = el.retrieve('instance')
				    if (instance && instance.focus) instance.focus();
				    else if (el.focus) el.focus();
				  }).delay(50);
				  if (callback) callback.apply(this, arguments);
				});
			}.bind(this));
		},
		
		print: function(e) {
		  var opts = e.getTarget().retrieve('send:options').data || {};
		  if (opts.comments) document.body.addClass('with-comments');
		  if (opts.meta) document.body.addClass('with-meta');
		  print();
		  (function() {
  		  if (opts.comments) document.body.removeClass('with-comments');
  		  if (opts.meta) document.body.removeClass('with-meta');
		  }).delay(300);
		  return false;
		},
		
		refresh: function() {
		  location.reload(true);
		},
		
		onBeforeUnload: function(fn) {
		  if (!this.unloaders) this.unloaders = [];
		  this.unloaders.push(fn);
		},
		
		unload: function() {
			Orwik.work();
		  var message;
		  if (this.unloaders) this.unloaders.each(function(fn) {
		    if (!message) message = fn();
		  }, this);
		  if (message) {
				Orwik.idle();
				return message;
			}
		},
		
		workers: 1,
		work: function() {
		  if (this.workers == 0) {
  			document.body.addClass('working');
  			if (Orwik.logo && window.getScrollTop() > 0) using('Fx.Tween', function() {
  	      Orwik.detachLogo();
  	      Orwik.logo.setStyle('top', Math.max(-40, 10 - window.getScrollTop()));
  		    Orwik.logo.get('tween', {duration: 200}).start('top', 10);
  		  });
		  }
		  this.workers++;
		},
		
		idle: function() {
		  if (this.workers > 0) this.workers--;
		  if (this.workers == 0) {
  			document.body.removeClass('working');
  			if (Orwik.logo && Orwik.logo.hasClass('detached')) {
  			  using('Fx.Tween', function() {
  		      var max = Math.max(-40, 10 - window.getScrollTop());
  			    Orwik.logo.get('tween', {duration: 200}).start('top', max).chain(function() {
  			      Orwik.attachLogo();
  			      Orwik.logo.setStyle('top', 10)
  			    })
  			  })
  			}
		  }
		},
		
		attachLogo: function() {
		  Orwik.logo.removeClass('detached').removeClass('initial');
		},
		
		detachLogo: function() {
		  Orwik.logo.addClass('detached').removeClass('initial');;
		},
		
		onScroll: function(e) {
	    var top = window.getScrollTop();
	    if (top == 0) {
	      Orwik.attachLogo();
	    } else {
	      if (Orwik.workers) Orwik.detachLogo();
	    }
		},
		
		updateSpace: function(space) {
			Environment.params.available_billable_space = space.toInt();
			this.fireEvent('space', Environment.params.available_billable_space);
		},

	  signout: function() {
		 	using('Request', function () {
				var signout_request = new Request({
			    url       : '/signout',
			    method    : 'delete',
			    isSuccess : function() { Orwik.refresh() }
				});

				signout_request.send();
		  }); // using Request
		},

		apps: function() {
			
	    var position = function(x, y) {
	      if (!y) y = x;
	      y += window.getScrollTop();
	      if (!arguments.callee.position) arguments.callee.position = {x: 50, y: 50};
	      arguments.callee.position.x += (x + 30);
	      arguments.callee.position.y += (y + 30);

	      return arguments.callee.position; 
	    }

	    $$('section .preview.image').each(function(preview) {
	      preview.addEvent('click', function() {
	        (Orwik.Tools.Preview.instance || new Orwik.Tools.Preview({application: position(50)})).open(preview.get('src') || preview.getElement('img').get('src'));
	      })
	    });

	    $$('section .preview.molecule').each(function(preview) {
	      preview.addEvent('click', function() {
	        (Orwik.Tools.Jmol.instance || new Orwik.Tools.Jmol({application: position(50)})).open(preview.get('src'));
	      });
	    })

           $$('section .preview.flash').each(function(preview) {
	      preview.addEvent('click', function() {
	        (Orwik.Tools.FlashPlayer.instance || new Orwik.Tools.FlashPlayer({application: position(50), width: preview.get('width').toInt(), height: preview.get('height').toInt()})).open(preview.get('src'));
	      });
	    });
            	
		},
		
		tips: function(tipped) {
		  
  	  if (tipped && tipped.length) using('Interface/Tips', function() {
  			if (!Tips.Disappearing) Tips.Disappearing = new Class({
    			Extends: Tips,

    			elementMove: function(event) {
    				this.position(event);
    				this.fireEvent('move', $(event.target))
    			},

    			setHiding: function(el) {
    				this.resetHiding(el);
    				var tip = this.tip;
    				el.store('tips:delay', function() {
    				  if (el.getParent()) {
    				    this.hide(el);
    				  } else {
    				    tip.dispose();
    				  }
    				}.delay(7000, this));
    			},

    			resetHiding: function(el) {
    				$clear(el.retrieve('tips:delay'));
    			}
    		});

        new Tips.Disappearing(tipped, {
          className: 'tip-wrapper', 
          onShow: function(tip, el){
            ['warning', 'error', 'message'].each(function(cls) {
              if (el.hasClass(cls)) tip.addClass(cls);
            })
      			tip.setStyle('visibility', 'visible');
    				this.setHiding(el);
      		},
      		onHide: function(tip, el){
      		  ['warning', 'error', 'message'].each(function(cls) {
              if (el.hasClass(cls)) tip.removeClass(cls);
            })
      			tip.setStyle('visibility', 'hidden');
      		},
    			onMove: function(el) {
    				this.show(el);
    				this.setHiding(el);
    			},
    			text: function(element) {
    				var shortcut = element.get('shortcut') || element.get('accesskey');
    				if (shortcut) {
    					return '(' + shortcut + ')'
    				} else {
    					return '';
    				}
    			}			

        });
    	});
		}
	}));
	$extend(Orwik, new Events);
	$extend(Orwik, new Options);
	window.onbeforeunload = Orwik.unload.bind(Orwik);
	DM.onGlobalLoad = Orwik.idle.bind(Orwik);

	Orwik.addEvent('nodeready', function(element) { 
	  var dates = element.getElements('abbr.relative-datetime');
		if (!dates.length) return;
	
		var relatize = function() {
			using('Date.Extras', function() {
				dates.each(function(el) { Element.relatizeDate(el); });
			});
		};
		relatize();

		(function() {
			relatize();
			relatize.periodical(60 * 1000);
		}).delay((60 - (new Date).getSeconds()) * 1000, this);
	});

	Orwik.addEvent('nodeready', function(element) {  	
		
	  element.getElements('textarea, input, select, div.html_area').each(function(el) {
			using('Widget/Input/Input', function() {
				Input.create(el);
			});
	  });

		element.getElements('form').each(function(el) {
			using('Widget/Form/Form', function() {
			  if (Browser.Engine.gecko) el.set("autocomplete", "off");
				Form.create(el);
			});
		});
	
		element.getElements('span.button[type=submit], div.button[type=submit], a.button]').each(function(el) {
			using('Widget/Button/Button', function() {
				Button.create(el);
			});
		});
		
		element.getElements('table').each(function(el) {
		  if (el.getElement('th[sort_by]')) using('Widget/Table/Table', function() {
		    Table.create(el);
		  })
		});
				
		element.getElements('ul.tabs[target], ul[name], ul.tabs:not([class*=piped])').each(function(el) {
  	  using('Widget/Tabs/Tabs', function() {
		    Tabs.create(el);
		  }) 
		});
		
	});

	Orwik.addEvent('nodeready', function(element) {
	  element.getElements('.unselectable').each(function(el) {
	    el.disableSelection();
	  });
	});
	
	

	Orwik.addEvent('nodeready', function(element) {
	  element.getElements('.accordion').each(function(el) {
	    using('Fx.Accordion', function() {
	      var headers = el.getChildren('header');
	      var pages = el.getChildren('.page');
	      $$(headers.getFirst('a')).addEvent($lambda(false));
	      var number = 0;
	      if (location.hash.length > 1) number = pages.map(function(el) {
          return el.get('id');
        }).indexOf(location.hash.substr(1, 255))
	      
	      
	      var delay;
	      new Fx.Accordion(el, headers, pages, {
	        onActive: function(toggler, element) {
	          $$(arguments).addClass('open');
	          $clear(delay)
	          delay = (function() {
	            element.setStyle('overflow', 'visible');
              element.setStyle('height', 'auto');
	          }).delay(550)
	        },
	        onBackground: function(toggler, element) {
            element.setStyle('overflow', 'hidden');
	          $$(arguments).removeClass('open');
	        },
	        initialDisplayFx: false,
	        show: number
	      })
	    })
	  });
	});


	Orwik.addEvent('nodeready', function(element) {
		element.getElements('a[confirm]').each(function(el) { 
			var events = el.retrieve('events') || {};
			var old = [];
			if (events.click && events.click.keys) {
				events.click.keys.each(function(fn) {
					old.push(fn);
					el.removeEvent('click', fn);
				})
			};
			
			
			(function(add, remove) {
			  var click = function(e) {
  				if (e) e.stop();
  				if (e.fired) return;
  				
  				Orwik.confirm(this, function(instance) {				    
  					if (old.length) {
  						old.each(function(fn) {
  							add.call(this, 'click', fn)
  						}, this)
    					e.fired = true;
    					this.fireEvent('click', e)
  						old.each(function(fn) {
  							this.removeEvent('click', fn)
  						}, this);
  					} else {
  						el.send()
  					}
  				}.bind(this));
  			};
  			if (el.get('disabled')) {
  			  if (el.retrieve('events:click')) old.push.apply(old, el.retrieve('events:click'));
  			  el.store('events:click', [click]); 
  			} else {
  			  el.addEvent('click', click);
  			}
			  el.addEvent = function(type, fn) {
			    if (type == 'click' && fn != click) old.push(fn);
			    else add.apply(this, arguments);
			  }
			  el.removeEvent = function(type, fn) {
			    if (type == 'click' && old.contains(fn)) old.erase(fn);
			    else remove.apply(this, arguments);
			  }
			})(el.addEvent, el.removeEvent);
		});
	});
	
	Orwik.addEvent('nodeready', function(element) {
		var open;
	  element.getElements('.textile-help a').addEvent('click', function() {
	    var that = this.getParent();
	    if (that.hasClass('clicked')) {
	      that.removeClass('clicked');
	    } else {
				if (open) open.removeClass('clicked');
	      that.addClass('clicked');
				open = that;
	    }
	    return false;
	  })
  });
	
	Orwik.addEvent('nodeready', function(element) {
	  
		element.getElements('a[method], a[interaction], a[state]').addEvent('click', function(e) {
		  var element = e.stop().getTarget('a');
			
		  var interaction = function() {
			  using('Widget', function() {
			    if (!element.get('method')) {
				    var interaction = element.retrieve('interaction') || Widget.Interaction.create(element);
				    if (interaction) interaction.run();
			    }
			    if (element.get('increments') || element.get('decrements')) {
				    var counter = new Widget.Counting;
				    counter.element = element;
				    counter.assignEvents();
				    counter.recount();
			    }
			  });
		  }	
		    
		  if (element.get('method')) {
			  Element.send(this, interaction, {
			    onRequest: Orwik.work.bind(Orwik),
			    onComplete: Orwik.idle.bind(Orwik)
			  });
  		} else {
			  interaction();
		  };
		});
	});
	
	Orwik.addEvent('nodeready', function(element) {
	  Orwik.tips(element.getElements('abbr[title], a[title]'));
	});

	Orwik.addEvent('nodeready', function(element) {
	  $$('.embedded.flash').each(function(el) {
	    using('Swiff', 'JSON', function() {
  	    new Swiff(el.get('src'), {
      		height: el.get('height'),
      		width: el.get('width'),
      		container: el,
      		params: {
      		  allowFullScreen: true
      		},
      		vars: el.get('params') ? JSON.decode(el.get('params')) : {}
  	    });
	    });
	  });

  });
	
  Orwik.addEvent('nodeready', function(element) {
    var tex = element.getElements('.tex, script[type=math/tex]')[0];
    if (tex) {
    	var parse = function() {
      	MathJax.parse(element);
      }
    	if (window.MathJax) {
      	parse();
      } else {
      	using("MathJax/MathJax", parse);
      }
    }
  })

	window.addEvent('domready', function() {
	  var states = ['js'];
		states.push(Browser.Plugins.Flash.version ? 'flash' : 'no-flash');
		document.body.className += ' ' + states.join(' ');
		
		
		(function(){

    	var m = new Element('BrowserExtrasFeatures');

    	var prop, i, tmp;

    	// Private funtion
    	// Loop through all possible properties and see if we get a valid response at all
    	checkProperties = function(prop){
    		var i = 0;
    		for (i in prop) {
    			if ($defined(m.style[prop[i]])) {
    				return prop[i];
    			}
    		}
    		return false;		
    	}

    	// Make sure the Browser.Extras object does exist
    	Browser.Extras = Browser.Extras || {};

    	Browser.Extras.Features = $merge({

    		borderimage: (function(){
    			// 'prop" is a list of DOM properties we want to check against. We specify
    			//  literally ALL possible (known and/or likely) properties on the element
    			//  including the non-vendor prefixed one, for forward compatibility.
    			prop = ['borderImage', 'webkitBorderImage', 'MozBorderImage', 'mozBorderImage', 'oBorderImage', 'msBorderImage'];
    			m.style.cssText = "border-image: url(m.png) 1 1 stretch; -webkit-border-image: url(m.png) 1 1 stretch; -moz-border-image: url(m.png) 1 1 stretch; -o-border-image: url(m.png) 1 1 stretch; -ms-border-image: url(m.png) 1 1 stretch;";
    			return checkProperties(prop);
    		})(),

    		borderradius: (function(){
    			/**
    			 *  See border-image for the explanations on the prop variable and the for loop
    			 */
    			prop = [
    				'borderTopRightRadius', 
    				'webkitBorderTopRightRadius', 
    				'MozBorderTopRightRadius', 
    				'mozBorderTopRightRadius', 
    				'oBorderTopRightRadius', 
    				'msBorderTopRightRadius',
    				'mozBorderRadiusTopright',
    				'MozBorderRadiusTopright'
    			];
    			m.style.cssText = "border-top-right-radius: 10px; "+
    				"-webkit-border-top-right-radius: 10px; "+
    				"-moz-border-top-right-radius: 10px; "+
    				"-o-border-top-right-radius: 10px; "+
    				"-ms-border-top-right-radius: 10px;"+
    				"-moz-border-radius-topright: 10px";
    			return checkProperties(prop);
    		})(),

    		boxshadow: (function(){
    			/**
    			 *  See border-image for the explanations on the prop variable and the for loop
    			 */
    			prop = ['boxShadow', 'webkitBoxShadow', 'MozBoxShadow', 'mozBoxShadow', 'oBoxShadow', 'msBoxShadow'];
    			m.style.cssText = "box-shadow: #000 1px 1px 3px; -webkit-box-shadow: #000 1px 1px 3px; -moz-box-shadow: #000 1px 1px 3px; -obox-shadow: #000 1px 1px 3px; -ms-box-shadow: #000 1px 1px 3px;";
    			return checkProperties(prop);
    		})(),

    		textshadow: (function(){
    			/**
    			 *  See border-image for the explanations on the prop variable and the for loop
    			 */		
    			prop = ['textShadow', 'webkitTextShadow', 'MozTextShadow', 'mozTextShadow', 'oTextShadow', 'msTextShadow'];
    			m.style.cssText = "text-shadow: 1px 1px 3px #000; -webkit-text-shadow: 1px 1px 3px #000; -moz-text-shadow: 1px 1px 3px #000; -o-text-shadow: 1px 1px 3px #000; -ms-text-shadow: 1px 1px 3px #000;";
    			return checkProperties(prop);
    		})(),

    		// The idea is taken from the Mediawiki OggHandler extension
    		// http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/OggHandler/OggPlayer.js
    		// Media wiki extension page: http://www.mediawiki.org/wiki/Extension:OggHandler

    		// actually, you should use the tag content as backup (<video>.. your backup html (flash player) ..</video>

    		// Firefox, Safari						Opera
    		video: typeof HTMLVideoElement == 'object' || typeof HTMLVideoElement == 'function',

    				// Firefox, Safari						Opera
    		audio: typeof HTMLAudioElement == 'object' || typeof HTMLAudioElement == 'function',
    		
    		placeholders: (function() {
          var i = document.createElement('input');
          return 'placeholder' in i;
    		})(),
    		
    		autofocus: (function() {
          var i = document.createElement('input');
          return 'autofocus' in i;
    		})()

    	},Browser.Extras.Features || {});

    	m.style.cssText = "";
    	tmp = i = prop = null;

    })();
		
		
		['borderradius', 'cssgradients', 'boxshadow'].each(function(item){
  		if(Browser.Extras.Features[item]){
  			$(document.body).addClass(item);
  		}else{
  			$(document.body).addClass('no-'+item);
  		}
  	});
  	
  	
		Orwik.logo = document.getElement('#layout > header h1');
	  if (Orwik.logo) using('Element.Dimensions', function() {
  		window.addEvent('scroll', Orwik.onScroll.bind(Orwik));
  		Orwik.onScroll();
  	});
		
		$$('.tip.message .close').addEvent('click', function(e) {
			var el = e.stop().getTarget('.tip');
			using('Fx.Slide', 'Fx.Tween', function() {
				el.get('slide').start('out').chain(function() {
					using('Cookie', function() {
						new Cookie(el.get('id')).write('0');
					})
					el.dispose();
				});
			});
		});
		
		$$('.printer.iconed').addEvent('click', Orwik.print.bind(Orwik));
		$$('#3d-party-sharing a').each(function(el) {
		  var url = el.get('href').substitute({url: encodeURIComponent(location.href), title: encodeURIComponent(document.title)});
		  el.set('href', url);
		  el.store('send:options', $merge(el.retrieve('send:options'), {url: url}));
		});
		

    var facebook_connect = $('facebook-connect');
    if (facebook_connect) {
			// TODO: we need some kind of spinner here because
			// it take some time to load Facebook library from their servers
	  	facebook_connect.addEvent('click', function() {
	  		using('Facebook/FeatureLoader', function() {
	  			FB_RequireFeatures(["Api"], function(){
				  	// require user to login 
				    FB.Connect.showPermissionDialog("email", function(exception) {
							Orwik.redirect(facebook_connect.get('href'));
				  	});
					});
				}); // using Facebook/FeatureLoader

				return false;
			});  // addEvenvt facebook_coonect.click
    };

    var facebook_signout = $('facebook-signout');
    if (facebook_signout) {
			facebook_signout.removeEvents();

			facebook_signout.addEvent('click', function(event) {
		    Orwik.work();
		    event.stop();

		    using('Facebook/FeatureLoader', function() {
					FB_RequireFeatures(["Api"], function(){
				    if (FB.Facebook.apiClient.get_session()) {
							FB.Connect.logout(function() {
						   	Orwik.signout();
							});
					  } else {
							facebook_signout.send();
					  }
		  		});
		    });

			  return false;
			}); // click event
    }



		Orwik.Menu = new Class({
		  Implements: Options,

		  options: {
		    delay: 300
		  },

		  initialize: function(element, options) {
		    this.element = $(element)
		    if (!this.element) return false;
		    this.setOptions(options);
		    this.menu = this.element.getLast()
		    this.menu.fade('hide').get('tween', {duration: 150})

		    this.element.addEvents({
		      'mouseenter': this.enter.bind(this),
		      'mouseleave': this.leave.bind(this)
		    });
		  },

		  enter: function(e) {
		    $clear(this.delay);
		    this.delay = this.open.delay(this.options.delay, this);
		  },

		  leave: function(e) {
		    $clear(this.delay);
		    if (this.shown) this.delay = this.close.delay(this.options.delay, this);
		  },

		  open: function() {
		    this.shown = true;
		    this.element.addClass('open');
		    this.menu.fade('in')
		    return false;	
		  },

		  close: function() {
		    this.shown = false;
		    this.menu.get('fade').start('out').chain(function() {
  		    this.element.removeClass('open')
		    }.bind(this))
		    return false;
		  }
		});

		
		var menu = $('dashboard-menu');
		if (menu) using('Fx.Tween', function() { 
		  new Orwik.Menu(menu);
		});
		
		
	  // Scroll to anchor
		document.body.addEvent('click(a[href*=#])', function(event) {
			var link = event.getTarget('a');
			var anchor = link.get('href').split('#')[1];
			if (!anchor.length) return event.stop();
			var el = $(anchor) || document.getElement('a[name=' + anchor + ']');
			if (el) {
				event.preventDefault();
				this.anchor = anchor;
				Orwik.scroll(el, function() {
					using('Fx.Tween', function() {
						el.set('tween', {duration: 1000})
						el.highlight("#dde9ec");
					})
					if (!Browser.Engine.webkit419) {
						window.location.hash = anchor;
					}
				});
				link.blur();
			}
		});
		
		setTimeout(function() {
			Orwik.fireEvent('nodeready', $(document.body));
			Orwik.prefetch('/images/icons/spinner.gif');
			Orwik.notify();
		}, 10);
	});

	//wrapper for crop-with-ellipsis hack
	$ellipsis = function(element, attributes) {
	  return new Element('span', $merge(attributes || {}, {'class': 'ellipsis'})).
	    grab(new Element('ins').grab(element)).
	    grab(new Element('del'));
	};

	Orwik.initialize();
	
	Orwik.filename = function(name) {
		if (!name || !name.length) return '';
		if (name.length < 19) return name;
		return name.substr(0, 8) + '…' + name.substr(name.length - 8, 8);
	};
	
	Orwik.filenameOf = function(number) {
	  var half = (number / 2);
	  return function(name) {
  		if (!name || !name.length) return '';
  		if (name.length < 19) return name;
  		return name.substr(0, half) + '…' + name.substr(name.length - half, half);
	  }
	}
	
	Orwik.extensions = [
		'zip', 'rar', '7z', 'gz', 'tar',
		'txt', 'pdf', 'html', 'djvu', 'rtf',
		'xsl', 'doc', 'ptt',
		'png', 'gif', 'jpg', 'jpeg', 'tiff',
		'xyz', 'cdt', 'pcl',
		'mp3', 'aa', 'flac', 'ogg'
	];
	Orwik.isFileKnown = function(filename) {
		if (!arguments.callee.regex) arguments.callee.regex = new RegExp('\\.(?:' + Orwik.extensions.join('|') + ')$');
		return filename && filename.length && arguments.callee.regex.exec(filename);
	};	
  
	Math.Rectangle = new Class({
	  initialize: function(obj) {
	    return $extend(this, obj);
	  },

	  intersection: function(another) {
	    var intersection = Math.Rectangle.intersect(this, another);
	    if (intersection) return new Math.Rectangle(intersection);
	  }
	});
	
	Math.Rectangle.intersect = function(one, another) {
    var x0 = Math.max(one.left, another.left);
    var x1 = Math.min(one.left + one.width, another.left + another.width);

    if (x0 <= x1) {
      var y0 = Math.max(one.top, another.top);
      var y1 = Math.min(one.top + one.height, another.top + another.height);

      if (y0 <= y1) return {left: x0, top: y0, width: x1 - x0, height: y1 - y0}
    }
  }
});

Resource = {};