(function($){
	var Tooltip=function(options,source){
		var self=this;
		this.defaults={
			id:'tooltip',
			'class':source.attr('id'),
			padding:10
		};
		this.availParams=['id','class'];
		this.getTemplates=function(){
			return {
				user:options.title,
				simple:source.data('title')?source.data('title'):source.attr('title'),
				flash:'\
					<object type="application/x-shockwave-flash" data="'+source.attr('href')+'" width="100%" height="100%">\
						<param name="movie" value="'+source.attr('href')+'"/>\
						<param name="wmode" value="transparent"/></object>\
				',
				image:'<img alt="" src="'+source.attr('href')+'"/>',
				iframe:'<iframe src="'+source.attr('href')+'" width="100%" height="100%"></iframe>'
			};
		};
		this.getHrefExtension=function(){
			r=source.attr('href').match(/\.([^\.]+)$/);
			return r==null?r:r[1];
		}
		this.getType=function(){
			var
				ext=typeof(source.attr('href'))!='undefined'?this.getHrefExtension():null,
				extensions={
					image:['gif','jpg','jpeg','png'],
					flash:['swf']
				}
			;
			if(typeof(options.title)!='undefined'){
				return 'user';
			}else if(ext){
				for(type in extensions){
					for(i in extensions[type]){
						if(ext==extensions[type][i]){
							return type;
						};
					}
				}
				return 'iframe';
			}
			return 'simple';
		}
		this.getHtml=function(){
			return this.getTemplates()[this.getType()];
		}
		this.bindEvents=function(){
			source.bind({
				'mouseover':function(){
					self.el.appendTo('body');
				},
				'mouseleave':function(){
					self.el.remove();
				},
				'mousemove':function(e){
					var css={
						left:e.pageX,
						top:e.pageY,
						marginLeft:0,
						marginTop:0
					};
					if(css.left+self.el.width()+options.padding<$(window).scrollLeft()+$(window).width()){
						css.left+=options.padding;
					}else{
						css.left-=options.padding;
						css.marginLeft=-self.el.width();
					}
					if(css.top+self.el.outerHeight()+options.padding<$(window).scrollTop()+$(window).height()){
						css.top+=options.padding;
					}else{
						css.top-=options.padding;
						css.marginTop=-self.el.outerHeight();
					}
					self.el.css(css);
				}
			});
		}
		this.action=function(){
			var
				params={},
				el
			;
			if(typeof(options)!='object'){
				options={title:options};
			}
			options=$.extend(self.defaults,options);
			for(p in self.availParams){
				if(typeof(options[self.availParams[p]])!='undefined'){
					params[self.availParams[p]]=options[self.availParams[p]];
				}
			}
			params.html=self.getHtml();
			source.removeAttr('title');
			self.el=$('<div/>',params);
			self.bindEvents();
		}();
	};
	$.fn.tooltip=function(options){
		return this.each(function(){
			new Tooltip(options,$(this));
		});
	};
})(jQuery);
