IMDb lookup

By lazyttrick Last update Oct 5, 2010 — Installed 4,393 times.

There are 33 previous versions of this script.

Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)

// ==UserScript==
// @name           IMDb lookup
// @namespace      meh
// @description     mouseover movie or person link to lookup info
// @include        http://www.imdb.*
// ==/UserScript==
/*
TODO:
 - improve hiddentab's style(border?)
 - treat empty cases: no plot, no media...?
   - treat lack of info in "www.imdb.*"
 */
var delay_tooltip = 500;//ms
var divLookup, currentURL, timer, timerEvtObj;
var evt;


//CSS
if(!GM_getValue('color_text')) 
{
	// default by http://userscripts.org/users/114490
	GM_setValue('color_text', '111111');
	GM_setValue('color_link', '772211');
	GM_setValue('color_border', '111111');
	GM_setValue('color_first_BG', '7799dd');
	GM_setValue('color_second_BG', '8db0d3');
	GM_setValue('font_size_tab', 'small');
}
var color_text = GM_getValue('color_text');
var color_link = GM_getValue('color_link');
var color_border = GM_getValue('color_border');
var color_border_top = GM_getValue('color_border_top');
var color_first_BG = GM_getValue('color_first_BG');
var color_second_BG = GM_getValue('color_second_BG');
var font_size_tab = GM_getValue('font_size_tab');
if(!getId('imdblookupcssholder')){
	getTag('head')[0].appendChild(createElement('style', {id:'imdblookupcssholder', type:'text/css'}));
}
function updateCSS()
{
	getId('imdblookupcssholder').innerHTML += '.color_text {color:#'+color_text+' !important;} '+
		'.color_link:link {color:#'+color_link+' !important;} '+
		'.color_link:visited {color:#'+color_link+' !important;} '+
		'.color_link:hover {color:#'+color_link+' !important;} '+
		'.color_link:active {color:#'+color_link+' !important;} '+
		'.color_border {border:solid 1px #'+color_border+' !important;} '+
		'.color_border_top {border-top:solid 10px #'+color_second_BG+' !important;} '+//padding border
		'.color_first_BG {background-color:#'+color_first_BG+' !important;} '+
		'.color_second_BG {background-color:#'+color_second_BG+' !important;}'+
		'.font_size_tab {font-size:'+font_size_tab+' !important;}' +

		'a.imdblookup:link {color: '+color_link+' !important; text-decoration: underline !important;}'+ 
		'a.imdblookup:visited {color: '+color_link+' !important; text-decoration: underline !important;}'+
		'a.imdblookup:hover {color: '+color_link+' !important; text-decoration: underline !important;}'+
		'a.imdblookup:active {color: '+color_link+' !important; text-decoration: underline !important;}';
}
updateCSS();



//click outside to close div
document.addEventListener('click', clickOutside, false);


//attach events
xp('//a[contains(@href,"/title/tt") or contains(@href,"/name/nm")]').forEach(function(a){
	if( /\/name\/nm\d+\/$/.test(a.href) || /\/title\/tt\d+\/$/.test(a.href) ){
		a.addEventListener('mouseover', start, false);
		a.addEventListener('mouseout', end, false);
	}
});


function end(evt){
	if(timer)
		window.clearTimeout(timer);
}

function start(evt){
	timerEvtObj = evt;
	
	if(timer)
		window.clearTimeout(timer);
		
	timer = window.setTimeout(
		function ()
		{
			var link = (timerEvtObj.target.tagName=='A' ? timerEvtObj.target : timerEvtObj.target.parentNode );
			
			if(!divLookup){
				divLookup = createElement('div', {id:'divLookupImdb', class:'color_text color_first_BG color_border', style:'position:absolute; top:'+(timerEvtObj.clientY+window.pageYOffset+10)+'px; left:'+(timerEvtObj.clientX+window.pageXOffset+30)+'px; padding:3px; z-index:1000; font-size:small; font-family: Arial; -moz-border-radius:3px;'});
				document.body.appendChild(divLookup);
			}else{
				divLookup.innerHTML = '';
				divLookup.style.top = (timerEvtObj.clientY+window.pageYOffset+10)+'px';
				divLookup.style.left = (timerEvtObj.clientX+window.pageXOffset+30)+'px';
			}
			divLookup.appendChild(imgLookup.cloneNode(false));
			
			if( /name\/nm/.test(link.href) ) { //person
				divLookup.addEventListener('mouseover', lookupPerson, false);
				currentURL = link.href;
			}else if( /title\/tt/.test(link.href) ) { //movie
				divLookup.addEventListener('mouseover', lookupTitle, false);	
				currentURL = link.href;
			}
		}	
		,delay_tooltip
	);
}




function lookupPerson(evt)
{
	divLookup.removeEventListener('mouseover', lookupPerson, false);
	divLookup.innerHTML = 'loading...';
	GM_xmlhttpRequest({
		method: 'GET',
		url: currentURL,
		onload: function(resp) {	
		
			//select body and remove some tags
			var html = resp.responseText.match(/\<body[^\>]*\>([\s\S]+)\<\/body\>/)[1];
			html = html.replace(/\<script[^\<]+\<\/script\>/ig, '');
			html = html.replace(/\<iframe[^\<]+\<\/iframe\>/ig, '');
			
			//append requested page as hidden iframe
			var iframe = document.body.appendChild(createElement('iframe', {style:'display:none; visibility:hidden;'}));	
			iframe.contentWindow.document.body.appendChild(createElement('div', {id:'divExtract'}, null, html));
			var divExtract = iframe.contentWindow.document.getElementById('divExtract');
			
			
			//name
			var name;
			name = '<a href="'+currentURL+'" target="_blank" class="imdblookup"><b>' + resp.responseText.match(/\<title\>([^\<]+)/)[1] + '</b></a>'; 
			
			
			//birth 
			var bio, day, year, place;
			try{ day = resp.responseText.match(/\<a href\=\"\/OnThisDay[^\>]+\>([^\<]+)/)[1];}catch(e){}
			try{ year = resp.responseText.match(/\<a href\=\"\/search\/name\?birth\_year[^\>]+\>([^\<]+)/)[1];}catch(e){}
			try{ place = resp.responseText.match(/\<a href\=\"\/search\/name\?birth\_place[^\>]+\>([^\<]+)/)[1];}catch(e){}
			bio = (day?day:'') + (year?(day?', '+year:year):'') + (place?' ('+place+')':'') + ((day||year||place)?'<br>':'');
			
			
			//face picture
			var href, src, link;
			try{ 
				var txt = resp.responseText.match(/\<a[^\>]+name\=\"headshot\"[^\>]*\>\s*\<img[^\>]+src\=\"[^\"]+/g)[0];
				src = txt.replace(/^.+src\=\"/,"");
			}catch(e){
				src = 'http://i.media-imdb.com/images/nophoto.jpg';
			}
			try{
				href = 'http://www.imdb.com'+txt.match(/\/rg\/action\-box\-name\/headshot\/media\/rm\d+\/nm\d+/)[0];//rg/action-box-name/headshot/media/rm2048364032/nm0519043
			}catch(e){
				href = 'http://i.media-imdb.com/images/nophoto.jpg';
			}
			
			
			//assemble resume
			divLookup.innerHTML = 	'<table>'+
										'<tr>'+
											'<td id="td111" valign="top"></td>'+
											'<td id="td222" valign="top"></td>'+
										'</tr><tr>'+
											'<td></td>'+
											'<td id="td333" valign="top"></td>'+
										'</tr>'+
									'</table>';
			getId('td111').appendChild(createElement('a',{href:href, target:'_blank'})).appendChild(createElement('img', {src:src, style:'margin:3px 10px 10px 3px; border:0; '}, 'mouseover enlargePic false'));
			getId('td222').appendChild( createElement('span',{style:'font-size:small;'},null,name +'<br>'+bio));
			getId('td222').appendChild( createElement('br'));
			
			
			//Filmography
			getId('td222').appendChild(createElement('div', {id:'divtabs', style:'font-size:small;'}));
			getId('td222').appendChild(createElement('div', {id:'divcontents', class:'color_second_BG font_size_tab color_border_top', style:'overflow:auto; max-width:400px; height:150px; padding:0px 10px 0px 10px; margin-bottom:5px;'}));
			try{
				var count = 0;
				var divss = divExtract.getElementsByTagName('div');
				xp('.//div[@class="filmo"]', divExtract, iframe.contentWindow.document).forEach(
					function(s){
						//category: actor,producer...
						var category = getTag('h5', s)[0].textContent.replace(/(:|^\s*|\s*$)/g,'');
						
						//tab title 
						var tab = createElement('div', {id:'tab_'+category.replace(/\s/,'_'), class:'color_first_BG', style:'display:inline; -moz-border-radius-topleft:3px; -moz-border-radius-topright:3px; padding:0px 7px; cursor:pointer;'}, 'click handleTabClick false', (category.match(/^[\s\S]{15}/) ? category.match(/^[\s\S]{15}/)[0]+'...' : category.match(/^[\s\S]+/)[0]));
						getId('divtabs').appendChild(tab);
						if(count==0){//select first tab
							tab.setAttribute('class', 'color_second_BG');
							tab.style.cursor = 'default';
						}else if(count>2){
							//hidden tabs in a drop down menu
							if(!getId('hiddentabs'))
								document.body.appendChild(createElement('div', {id:'hiddentabs', class:'color_second_BG', style:'display:none; font-size:small; z-index:1001; position:absolute; margin-top:15px;'}));
							getId('hiddentabs').appendChild(tab);
							tab.setAttribute('hiddentab','ya');
							tab.style.display = 'block';
						}
						
						//tab content
						var content = getTag('ol', s)[0];
						content.setAttribute('id','tabcontent_'+category.replace(/\s/,'_'));
						if(count!=0){//hide unselected contents
							content.style.display = 'none';
						}
						getId('divcontents').appendChild(content);
						
						count++;
					}
				);
			}catch(e){
				GM_log(e);
			}
			

			/*media*/
			//tab
			tab = createElement('div', {id:'tab_media', class:'color_first_BG', style:'display:inline; -moz-border-radius-topleft:3px; -moz-border-radius-topright:3px; padding:0px 7px; cursor:pointer;'}, 'click handleTabClick false', 'Media');
			getId('divtabs').appendChild(tab);
			tab.style.cursor = 'pointer';				
			//content
			try{
				getId('divcontents').appendChild(createElement('div', {id:'tabcontent_media', style:'display:none'}, null, 'Mouse over to enlarge.<br>'));

				resp.responseText.match(/\<a\s+href\=\"\/rg\/photos\-name\/[^\"]+\/media\/rm\d+\/nm\d+\"\s*\>\s*\<img[^\>]+\>\s*\<\/a\>/g).forEach(
					function(a){
						var src = a.match(/http\:\/\/ia\.media\-imdb\.com\/images\/[^\"]+\_SS90\_\.jpg/)[0].replace(/\_SS90\_/,'_SS45_');
						var href = 'http://www.imdb.com' + a.match(/\/media\/rm\d+\/nm\d+/)[0];
						var link = getId('tabcontent_media').appendChild(createElement('a', {href:href, target:'_blank'}));
						link.appendChild(createElement('img', {src:src, style:'margin-right:2px; margin-bottom:2px; border:0;'}, 'mouseover enlargePic false'));
					}
				);
			}catch(e){
			}
			
			
			//menu hidden tabs (+)
			if(getId('hiddentabs')){
				getId('divtabs').appendChild(createElement('a', {href:'javascript:void(0)', style:'text-decoration:none; font-weight:bold;'}, 'click toogleMenuTabs false', ' + '));
			}
			
			
			//close link
			//divLookup.appendChild(createElement('a', {href:"javascript:void(0)", style:"position:absolute; right: 3px; top: 3px; font-size:small",  class:"imdblookup"}, "click close false", "close"));
			

			//options link
			getId('td333').appendChild(createElement('a', {id:'optionsLink', href:'javascript:void(0);', style:'position:absolute; bottom:1px; right:3px; font-size:small; text-decoration:none;'}, 'click options false', '>>'));				
			
			
			//drag
			divLookup.addEventListener('mousedown', dragHandler, false);
			
			//reposition if out of window
			var scrollY = divLookup.offsetTop - document.documentElement.scrollTop + divLookup.clientHeight - window.innerHeight;
			if( scrollY > 0){
				divLookup.style.top = (divLookup.offsetTop - scrollY)+'px';
			}
			if( divLookup.offsetLeft > window.innerWidth - 450)
				divLookup.style.left = (window.innerWidth - 450)+'px';
			
			//cleanup
			iframe.parentNode.removeChild(iframe);
		}
	});
}


function options(evt)
{
	var divOptions = getId('divOpt');
	
	if(!divOptions)//show options
	{
		divOptions = createElement('div', {id:'divOpt', class:'color_second_BG', style:'position:relative; padding:5px;'});
		getId('td333').appendChild(divOptions);
		getId('optionsLink').style.visibility = 'hidden';
		

		//font size
		divOptions.appendChild(createElement('span',null,null,'Tabs font-size '));
		divOptions.appendChild(createElement('select', {id:'sel_font_size'}, 'change previewOptions false', '<option>x-small</option><option>small</option><option>medium</option><option>large</option>'));	
		divOptions.appendChild(createElement('br'));
		getId('sel_font_size').value = font_size_tab;
		
		
		//colors
		divOptions.appendChild(createElement('span',null,null,'Text '));
		divOptions.appendChild(createElement('input', {id:'ta_color_text', value:color_text, size:'11', class:'color {pickerPosition:"right"}'}, 'change previewOptions false'));
		divOptions.appendChild(createElement('br'));
		divOptions.appendChild(createElement('span',null,null,'Link '));
		divOptions.appendChild(createElement('input', {id:'ta_color_link', size:'11', value:color_link, class:'color {pickerPosition:"right"}'}, 'change previewOptions false'));
		divOptions.appendChild(createElement('br'));
		divOptions.appendChild(createElement('span',null,null,'Border '));
		divOptions.appendChild(createElement('input', {id:'ta_color_border', size:'11', value:color_border, class:'color {pickerPosition:"right"}'}, 'change previewOptions false'));
		divOptions.appendChild(createElement('br'));
		divOptions.appendChild(createElement('span',null,null,'1st background '));
		divOptions.appendChild(createElement('input', {id:'ta_color_first_BG', size:'11', value:color_first_BG, class:'color {pickerPosition:"right"}'}, 'change previewOptions false'));
		divOptions.appendChild(createElement('br'));
		divOptions.appendChild(createElement('span',null,null,'2nd background '));
		divOptions.appendChild(createElement('input', {id:'ta_color_second_BG', size:'11', value:color_second_BG, class:'color {pickerPosition:"right"}'}, 'change previewOptions false'));
		divOptions.appendChild(createElement('br'));
		
		//init color picker
		jscolor.init();
		
		//save
		divOptions.appendChild(createElement('br'));
		divOptions.appendChild(createElement('a', {href:'javascript:void(0);'}, 'click saveOptions false', 'save'));
		
		
		//cancel
		divOptions.appendChild(createElement('span', null, null,'&nbsp;'));
		divOptions.appendChild(createElement('a', {href:'javascript:void(0);'}, 'click options false', 'cancel'));
		
	}
	else//hide options
	{	
		divOptions.parentNode.removeChild(divOptions);
		getId('optionsLink').style.visibility = 'visible';
		
		//restore colors in case previewOptions() changed them
		color_text = GM_getValue('color_text');
		color_link = GM_getValue('color_link');
		color_border = GM_getValue('color_border');
		color_border_top = GM_getValue('color_border_top');
		color_first_BG = GM_getValue('color_first_BG');
		color_second_BG = GM_getValue('color_second_BG');	
		updateCSS();	
	}
}


function previewOptions(e)
{
	var id = e.target.getAttribute('id');
	if(id=='sel_font_size'){
		getId('divcontents').style.fontSize = e.target.value;
	}else if(id=='ta_color_text'){
		color_text = e.target.value;
	}else if(id=='ta_color_link'){
		color_link = e.target.value;
	}else if(id=='ta_color_border'){
		color_border = e.target.value;
	}else if(id=='ta_color_first_BG'){
		color_first_BG = e.target.value;
	}else if(id=='ta_color_second_BG'){
		color_second_BG = e.target.value;
	}
	
	updateCSS();			
}


function saveOptions(evt)
{	

	//save colors
	GM_setValue('color_text', getId('ta_color_text').value);
	GM_setValue('color_link', getId('ta_color_link').value);
	GM_setValue('color_border', getId('ta_color_border').value);
	GM_setValue('color_first_BG', getId('ta_color_first_BG').value);
	GM_setValue('color_second_BG', getId('ta_color_second_BG').value);
	color_text = GM_getValue('color_text');
	color_link = GM_getValue('color_link');
	color_border = GM_getValue('color_border');
	color_first_BG = GM_getValue('color_first_BG');
	color_second_BG = GM_getValue('color_second_BG');
	
	//font size
	font_size_tab = getId('sel_font_size').value;
	GM_setValue('font_size_tab', font_size_tab);
	
	
	//close options
	getId('td333').removeChild(getId('divOpt'));
	getId('optionsLink').style.visibility = 'visible';
}



function toogleMenuTabs(e)
{
	if(getId('hiddentabs').style.display == 'none'){
		if(e){
			getId('hiddentabs').style.top = e.pageY+'px';
			getId('hiddentabs').style.left = e.pageX+'px';
		}
		getId('hiddentabs').style.display = 'inherit';
	}else{
		getId('hiddentabs').style.display = 'none';
	}	
}

function toogleImages(e)
{
	if(getId('divImgGallery').style.display == 'none'){
		getId('divImgGallery').style.display = 'inherit';
	}else{
		getId('divImgGallery').style.display = 'none';
	}
}


function handleTabClick(e)
{
	var category = e.target.getAttribute('id').replace(/^[^\_]+\_/,'');
	var tab = e.target;
	var content = getId('tabcontent_'+category);
	
	//if tab in dropdown menu, switch places
	if(tab.getAttribute('hiddentab')){
		var lastVisTab = xp('.//div[starts-with(@id,"tab_")]', getId('divtabs'))[2];
		
		//pull out hidden tab outside
		getId('divtabs').insertBefore(tab, lastVisTab.nextSibling);
		tab.style.display = 'inline';
		
		//move hiddentabs to pulled out tab
		//tab.appendChild(getId('hiddentabs'));
		
		//move last tab to hiddentabs
		getId('hiddentabs').insertBefore(lastVisTab, getId('hiddentabs').firstChild);
		lastVisTab.setAttribute('class', 'color_first_BG');
		lastVisTab.style.display = 'block';
		lastVisTab.style.cursor = 'pointer';
	
		//hide menu
		toogleMenuTabs(null);
		
		//attribute hiddentab
		lastVisTab.setAttribute('hiddentab','ya');
		tab.removeAttribute('hiddentab');
		
	}
	
	
	//reset tabs colors
	xp('.//div[starts-with(@id,"tab_")]', getId('divtabs')).forEach(function(t){
		t.setAttribute('class', 'color_first_BG');
		t.style.cursor = 'pointer';
	});
	
	
	//select tab and content
	xp('.//*[starts-with(@id,"tabcontent_")]', content.parentNode).forEach(function(cntnt){
		cntnt.style.display = 'none';
		if(cntnt.getAttribute('id') == content.getAttribute('id')){
			cntnt.style.display = 'inherit';
			getId('tab_'+category).setAttribute('class', 'color_second_BG');
			getId('tab_'+category).style.cursor = 'default';
		}
	});
	
	
	if(getId('hiddentabs') && getId('hiddentabs').style.display != 'none')
		getId('hiddentabs').style.display = 'none'
}


function lookupTitle(evt)
{
	divLookup.removeEventListener('mouseover', lookupTitle, false);	
	divLookup.innerHTML = 'loading...';
	GM_xmlhttpRequest({
		method: 'GET',
		url: currentURL,
		onload: function(resp) {
			divLookup.innerHTML = 'processing...';
			
			//select body and remove some tags
			var html = resp.responseText.match(/\<body[^\>]*\>([\s\S]+)\<\/body\>/)[1];
			html = html.replace(/\<script[^\<]+\<\/script\>/ig, '');
			html = html.replace(/\<iframe[^\<]+\<\/iframe\>/ig, '');
			
			//append requested page as hidden iframe
			var iframe = document.body.appendChild(createElement('iframe', {style:'display:none; visibility:hidden;'}));	
			iframe.contentWindow.document.body.appendChild(createElement('div', {id:'divExtract'}, null, html));
			var divExtract = iframe.contentWindow.document.getElementById('divExtract');
			
			
			//name(year)
			var name;
			name = '<b><a href="'+currentURL+'" target="_blank"  class="imdblookup">' + resp.responseText.match(/\<title\>([^\<]+)/)[1].replace(/\s+$/,'') + '</a> </b> '; 
			
			
			//genres
			var genres = '';
			try{
				resp.responseText.match(/\<a href\=\"\/Sections\/Genres\/[^\/]+/g).forEach(function(a){
					genres += a.match(/\/Sections\/Genres\/([^\/]+)/)[1] + '/';
				});
				genres = genres.replace(/\/[^\/]+\/$/,'');//lame fix
			}catch(e){
				genres = '';
			}	

			
			//rating
			var rate = ' <br> ', rating, votes;
			try{
				rating = resp.responseText.match(/\d[\.]\d\/10/)[0];
				votes = resp.responseText.match(/\<a[^\>]+href\=\"ratings\"[^\>]*\>([\d\,]+ votes)/)[1];
				rate += rating + ' ('+votes+') ';
			}catch(e){
			}
			
			
			//assemble resume
			divLookup.innerHTML = '<table border="0">' 
				+'<tr>'
				+'	<td id="td111" valign="top" style="min-width:100px;"></td>'
				+'	<td id="td222" valign="top">' + name +'<br> <div style="font-size:small;">' + genres + '  ' + rate + '<br><br></div></td>'
				+'</tr><tr>'+
				'	<td></td>'+
				'	<td id="td333" valign="top"></td>'+
				'</tr>'+
				'</table>';			
				

			//poster
			var href, src, link;
			try{ 
				var txt = resp.responseText.match(/\<a[^\>]+name\=\"poster\"[^\>]*\>\s*\<img[^\>]+src\=\"[^\"]+/g)[0];
				src = txt.replace(/^.+src\=\"/,"");
				href = 'http://www.imdb.com'+txt.match(/\/rg\/action\-box\-title\/primary-photo\/media\/rm\d+\/tt\d+/)[0];
			}catch(e){
				src = 'http://i.media-imdb.com/images/nophoto.jpg';
			}
			if(src=='http://i.media-imdb.com/images/nophoto.jpg')
				link = getId('td111');
			else
				link = getId('td111').appendChild(createElement('a', {href:href, target:'_blank'}));
			link.appendChild(createElement('img', {src:src, style:'margin-bottom:2px; border:0;'}, 'mouseover enlargePic false'));

				
				
			//div tabs and contents
			getId('td222').appendChild(createElement('div', {id:'divtabs', style:'font-size:small;'}));
			getId('td222').appendChild(createElement('div', {id:'divcontents', class:'color_second_BG font_size_tab color_border_top', style:'overflow:auto; height:150px; padding:0px 10px 0px 10px; margin-bottom:5px; max-width:400px;'}));			
				
				
			/* cast */
			//tab
			var tab = createElement('div', {id:'tab_cast', class:'color_second_BG', style:'display:inline; -moz-border-radius-topleft:3px; -moz-border-radius-topright:3px; padding:0px 7px; cursor:pointer;'}, 'click handleTabClick false', 'Cast');
			getId('divtabs').appendChild(tab);
			//content
			getId('divcontents').appendChild(createElement('div', {id:'tabcontent_cast',style:'display:inherit;'}));
			try{
				var t = resp.responseText.match(/\<td class\=\"hs\"\>\s*\<a[^\>]+\>\s*\<img[^\>]+\>\s*\<\/a\>\s*\<br\/?\>\s*\<\/td\>\s*\<td class\=\"nm\"\>\s*\<a[^\>]+\>[^\<]+\<\/a\>\s*\<\/td\>\s*\<td class\=\"ddd\"\>[^\<]+\<\/td\>\s*\<td class\=\"char\"\>(\s*\<a[^\>]+\>[^\<]+\<\/a\>[^\<]*|[^\<]+)\<\/td\>/g);
				t.forEach(
					function(s){
						var img = s.match(/http\:\/\/ia\.media\-imdb\.com\/images\/\S+_V1._SY30_SX23_.jpg/)[0];
						var href = s.match(/\/name\/nm\d+\//)[0];
						var name = s.match(/\<a[^\>]+href\=\"\/name\/nm\d+\/\"[^\>]*\>([^\<]+)\<\/a\>/)[1];
						var character = s.match(/\<td class\=\"char\"\>(.+)\<\/td\>$/)[1].replace(/\<a/,'<a class="imdblookup" ');
						getId('tabcontent_cast').appendChild(createElement('a', {id:img, href:'http://www.imdb.com'+href, target:'_blank', class:"imdblookup"}, 'mouseover enlargeCastPic false', name));
						getId('tabcontent_cast').appendChild(createElement('span', null,null, '&nbsp;&nbsp;...&nbsp;&nbsp;'+character+''));
						getId('tabcontent_cast').appendChild(createElement('br'));
					}
				);
			}catch(e){
			}
			
			
			/*direction*/
			var director, writer;
			try	{ 
				director = xp('.//div[@id="director-info"]', divExtract, iframe.contentWindow.document)[0].innerHTML.replace(/\<\/?div[^\>]*\>/g,'').replace(/\<\/?h\d[^\>]*\>/g,'');
			}catch(e){ director = ''; }
			try	{ 
				writer = xp('.//div[@id="director-info"]', divExtract, iframe.contentWindow.document)[0].nextSibling.nextSibling.innerHTML.replace(/\<\/?div[^\>]*\>/g,'').replace(/\<\/?h\d[^\>]*\>/g,'');
			}catch(e){ writer = ''; }
			
			//tab
			tab = createElement('div', {id:'tab_direction', class:'color_first_BG', style:'display:inline; -moz-border-radius-topleft:3px; -moz-border-radius-topright:3px; padding:0px 7px; cursor:pointer;'}, 'click handleTabClick false', 'Direction');
			getId('divtabs').appendChild(tab);
			tab.style.cursor = 'pointer';
			//content
			getId('divcontents').appendChild(createElement('div', {id:'tabcontent_direction', style:'display:none;'}, null, director + writer));
				
				
			/*plot*/
			//tab
			tab = createElement('div', {id:'tab_plot', class:'color_first_BG', style:'display:inline; -moz-border-radius-topleft:3px; -moz-border-radius-topright:3px; padding:0px 7px; cursor:pointer;'}, 'click handleTabClick false', 'Plot');
			getId('divtabs').appendChild(tab);
			tab.style.cursor = 'pointer';			
			//content
			var plot;
			try{
				plot = xp('.//div[@class="info-content"]/a[@href="synopsis"]', divExtract, iframe.contentWindow.document)[0].parentNode.innerHTML;
			}catch(e){
				plot = '';
			}
			getId('divcontents').appendChild(createElement('div', {id:'tabcontent_plot', style:'display:none;'}, null, plot));
			

			
			/*media*/
			//tab
			tab = createElement('div', {id:'tab_media', class:'color_first_BG', style:'display:inline; -moz-border-radius-topleft:3px; -moz-border-radius-topright:3px; padding:0px 7px; cursor:pointer;'}, 'click handleTabClick false', 'Media');
			getId('divtabs').appendChild(tab);
			tab.style.cursor = 'pointer';	
			//images
			try{
				getId('divcontents').appendChild(createElement('div', {id:'tabcontent_media', style:'display:none'}, null, 'Mouse over to enlarge.<br>'));
				resp.responseText.match(/\<a\s+href\=\"\/rg\/photos\-title\/[^\"]+\/media\/rm\d+\/tt\d+\"\s*\>\s*\<img[^\>]+\>\s*\<\/a\>/g).forEach(function(a){
					var src = a.match(/http\:\/\/ia\.media\-imdb\.com\/images\/[^\"]+\_SS90\_\.jpg/)[0].replace(/\_SS90\_/,'_SS45_');
					var href = 'http://www.imdb.com' + a.match(/\/media\/rm\d+\/\D{2}\d+/)[0];
					var link = getId('tabcontent_media').appendChild(createElement('a', {href:href, target:'_blank'}));
					link.appendChild(createElement('img', {src:src, style:'margin-right:2px; margin-bottom:2px; border:0;'}, 'mouseover enlargePic false'));
				});
			}catch(e){
			}
			//trailers 
			var select = createElement('select', {id:'trailerSelect'}, "change playTrailer false");
			select.addEventListener('click', loadTrailersPage, false);
			select.appendChild(createElement('option', {value:""}, null, ""));
			getId('tabcontent_media').appendChild(createElement('span', null, null, '<br><br>Trailers: '));
			getId('tabcontent_media').appendChild(select);
			
			
			//close link
			//divLookup.appendChild(createElement('a', {href:"javascript:void(0)", style:"position:absolute; right: 3px; top: 3px; font-size:small",  class:"imdblookup"}, "click close false", "close"));			
			

			//options link
			getId('td333').appendChild(createElement('a', {id:'optionsLink', href:'javascript:void(0);', style:'position:absolute; bottom:1px; right:3px; font-size:small; text-decoration:none;'}, 'click options false', '>>'));							
			
			
			//dragging
			divLookup.addEventListener('mousedown', dragHandler, false);
			
			
			//reposition if out of window
			var scrollY = divLookup.offsetTop - document.documentElement.scrollTop + divLookup.clientHeight - window.innerHeight;
			if( scrollY > 0){
				divLookup.style.top = (divLookup.offsetTop - scrollY)+'px';
			}
			if( divLookup.offsetLeft > window.innerWidth - 450)
				divLookup.style.left = (window.innerWidth - 450)+'px';
			
			
			//cleanup
			iframe.parentNode.removeChild(iframe);
		}
	});
}


function enlargePic(e)
{
	if(e.target.getAttribute('src').search('nophoto') > -1)
		return;
	
	document.body.appendChild(createElement('img', {id:"tempImgBiggg", src:e.target.getAttribute('src').replace(/\_V1\.\_\S+\.jpg$/,'_V1._SY400_SX600_.jpg'), style:'z-index:1001; position:fixed;'}));
	
	evt = e;
	positionBigPic();
	
	e.target.addEventListener('mouseout', hidePic, true);
	
	//preload neighbours
	var prevImg = xp('preceding-sibling::a[position()=1]/img',e.target.parentNode)[0];
	var nextImg = xp('following-sibling::a[position()=1]/img',e.target.parentNode)[0];
	if(!getId('divPreloadImages')){
		document.body.appendChild(createElement('div',{id:'divPreloadImages', style:'display:none;'}))
	}
	if(prevImg && !getId('preload_'+prevImg.getAttribute('src'))){
		getId('divPreloadImages').appendChild(createElement('img', {id:'preload_'+prevImg.getAttribute('src'), src:prevImg.getAttribute('src').replace(/\_V1\.\_\S+\.jpg$/,'_V1._SY400_SX600_.jpg'), style:'display:none;'}));
	}
	if(nextImg && !getId('preload_'+nextImg.getAttribute('src'))){
		getId('divPreloadImages').appendChild(createElement('img', {id:'preload_'+nextImg.getAttribute('src'), src:nextImg.getAttribute('src').replace(/\_V1\.\_\S+\.jpg$/,'_V1._SY400_SX600_.jpg'), style:'display:none;'}));
	}	
}


function positionBigPic()
{	
	var img = getId('tempImgBiggg');
	if(!img) 
		return;
	if(img.height==0 || img.width==0){
		setTimeout(positionBigPic,500);//img not loaded, wait 1/2 sec
		return;
	}

	var clientWidth = window.document.documentElement.clientWidth;
	var clientHeight = window.document.documentElement.clientHeight;
	var x = (evt.clientX >= clientWidth/2) ? evt.clientX-img.width-50 : evt.clientX+50;
	var y = (evt.clientY >= clientHeight/2) ? evt.clientY-img.height+(img.height/3) : evt.clientY-50;
	
	img.style.left = x+'px';
	if( y + img.height > clientHeight )
		img.style.bottom = '0px';
	else
		img.style.top = y+'px';
}


function hidePic(e)
{
	var p = getId('tempImgBiggg');
	p.parentNode.removeChild(p);
}



function enlargeCastPic(e)
{
	document.body.appendChild(createElement('img', {id:"tempCastImgBiggg", src:e.target.getAttribute('id').replace(/_SY\d+_SX\d+_/, "_SX100_SY150_"), style:'z-index:1001; position:fixed; top:'+(e.clientY-30)+'px; left:'+(e.clientX+70)+'px;'}));
	e.target.addEventListener('mouseout', hideCastPic, false);
	e.target.style.fontWeight = "bold";
}
function hideCastPic(e)
{
	var p = getId('tempCastImgBiggg');
	p.parentNode.removeChild(p);
	e.target.style.fontWeight = "normal";
}



function loadTrailersPage(evt)
{
	var select = getId('trailerSelect');
	
	//loading...
	select.removeEventListener('click', loadTrailersPage, false);
	select.appendChild( createElement('option', {id:"idloadingoption"}, null, "Loading..."));	
	
	GM_xmlhttpRequest({
		method: 'GET',
		url: currentURL+'videosites',
		onload: function(resp) {
			
			//remove loading...
			select.removeChild(getId("idloadingoption"));
			
			//insert options...
			var arr = resp.responseText.match(/\(Flash\)\s+\([^\)]+\)/g);
			for(var i=0; i<arr.length; i++){
				try{
					select.appendChild(
						createElement('option',
							{ value: arr[i].match(/\"http[^\"]+\"/)[0].replace(/\"/g,"") },
							null,
							""+arr[i].match(/\>[^\<]+/)[0].replace(/\>/,"")
						)
					);
				}catch(e){
					GM_log(e);
				}
			}
		}
	});
}


function playTrailer(evt)
{
	var sel = evt.target;
	
	if(sel.selectedIndex==0)
		return;
		
	GM_openInTab(sel.value);
}


function clickOutside(e)
{
	if(e.target.tagName=='A' || e.target.parentNode.tagName=='A'){
		window.clearTimeout(timer);
		return;
	}
	if(!divLookup){
		return;
	}
	if(getId('divcolorpicker') && isAncestor(e.target, getId('divcolorpicker'))){
		return;
	}
	if(!isAncestor(e.target, divLookup)){
		close();
		//restore colors case options was open
		color_text = GM_getValue('color_text');
		color_link = GM_getValue('color_link');
		color_border = GM_getValue('color_border');
		color_border_top = GM_getValue('color_border_top');
		color_first_BG = GM_getValue('color_first_BG');
		color_second_BG = GM_getValue('color_second_BG');	
		updateCSS();
	}
}

function isAncestor(x, anc)
{		
	while(x.nodeName!='HTML' && x.parentNode!=anc){
		x = x.parentNode;
	}
	
	if(x.parentNode==anc)
		return true;
	else
		return false;
}


function close(evt){
	if(getId('hiddentabs'))
		getId('hiddentabs').parentNode.removeChild(getId('hiddentabs'));
	
	if(getId('divPreloadImages'))
		getId('divPreloadImages').parentNode.removeChild(getId('divPreloadImages'));
	
	divLookup.parentNode.removeChild(divLookup);
	divLookup = null;
	
}




function createElement(type, attrArray, evtListener, html)
{
	var node = document.createElement(type);

	for (var attr in attrArray) if (attrArray.hasOwnProperty(attr)){
		node.setAttribute(attr, attrArray[attr]);
	}

	if(evtListener){
		var a = evtListener.split(' ');
		node.addEventListener(a[0], eval(a[1]), eval(a[2]));
	} 
 
	if(html) 
		node.innerHTML = html;
	
	return node;
}

function getId(id, parent){
	if(!parent)
		return document.getElementById(id);
	return parent.getElementById(id);	
}

function getTag(name, parent){
	if(!parent)
		return document.getElementsByTagName(name);
	return parent.getElementsByTagName(name);
}

function xp(p, context, doc) {
  if (!context) 
	context = document;
  if (!doc) 
	doc = document;	
  var i, arr = [], xpr = doc.evaluate(p, context, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  for (i = 0; item = xpr.snapshotItem(i); i++) 
	arr.push(item);
  return arr;
}

function debug(str)
{
	
	var d = document.getElementById('debugg');
	if(!d){
		var div = document.createElement('div');
		div.setAttribute('id','divdebug');
		div.setAttribute('style', 'background-color:#000000; position:fixed; bottom:3px; left:3px; width:50%; z-index:9999;');
		
		var closeButton = document.createElement('input');
		closeButton.setAttribute('id','closedebug');
		closeButton.setAttribute('type', 'button');
		closeButton.setAttribute('value', 'close');
		closeButton.setAttribute('onClick', 'this.parentNode.parentNode.removeChild(this.parentNode);');
		
		d = document.createElement('textarea');
		d.setAttribute('id','debugg');
		d.setAttribute('style',"height:200px; width:99%; margin:2px;");
		
		div.appendChild(d);
		div.appendChild(document.createElement('br'));
		div.appendChild(closeButton);
		document.body.appendChild(div);
	}
	d.innerHTML += '\n'+str;
	d.scrollTop = d.scrollHeight;
}



var imgLookup = createElement('img',{border:0});
imgLookup.src = 'data:image/gif,GIF89a%12%00%12%00%B3%00%00%FF%FF%FF%F7%F7%EF%CC%CC%CC%BD%BE%BD%99%99%99ZYZRUR%00%00%00%FE%01%02%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%04%14%00%FF%00%2C%00%00%00%00%12%00%12%00%00%04X0%C8I%2B%1D8%EB%3D%E4%00%60(%8A%85%17%0AG*%8C%40%19%7C%00J%08%C4%B1%92%26z%C76%FE%02%07%C2%89v%F0%7Dz%C3b%C8u%14%82V5%23o%A7%13%19L%BCY-%25%7D%A6l%DF%D0%F5%C7%02%85%5B%D82%90%CBT%87%D8i7%88Y%A8%DB%EFx%8B%DE%12%01%00%3B';






















/*
 * Drag and drop support adapted fom http://www.hunlock.com/blogs/Javascript_Drag_and_Drop
 */

var savedTarget=null;                           // The target layer (effectively vidPane)
var orgCursor=null;                             // The original mouse style so we can restore it
var dragOK=false;                               // True if we're allowed to move the element under mouse
var dragXoffset=0;                              // How much we've moved the element on the horozontal
var dragYoffset=0;                              // How much we've moved the element on the verticle

var didDrag=false;								//set to true when we do a drag
	
	
function moveHandler(e){
	if (e == null) return;// { e = window.event } 
	if ( e.button<=1 && dragOK ){
		savedTarget.style.left = e.clientX - dragXoffset + 'px';
		savedTarget.style.top = e.clientY - dragYoffset + 'px';
		return false;
	}
}

function dragCleanup(e) {
	document.removeEventListener('mousemove',moveHandler,false);
	document.removeEventListener('mouseup',dragCleanup,false);
	savedTarget.style.cursor=orgCursor;

	dragOK=false; //its been dragged now
	didDrag=true;
	
}

function dragHandler(e){

	var htype='-moz-grabbing';
	if (e == null) return;//{ e = window.event;}  // htype='move';} 
	var target = e.target;// != null ? e.target : e.srcElement;
	orgCursor=target.style.cursor;

	//cancel drag
	if(clickedInsideID(target, 'divcontents')){
		return;	
	}
	
	//drag
	if (target = clickedInsideID(target, 'divLookupImdb')) {
		savedTarget=target;       
		target.style.cursor=htype;
		dragOK=true;
		dragXoffset = e.clientX-target.offsetLeft;
		dragYoffset = e.clientY-target.offsetTop;
		
		//set the left before removing the right
		target.style.left = e.clientX - dragXoffset + 'px';
		target.style.right = null;
		
		
		document.addEventListener('mousemove',moveHandler,false);
		document.addEventListener('mouseup',dragCleanup,false);
		return false;
	}
}

function clickedInsideID(target, id) {

	if (target.getAttribute('id')==id)
		return getId(id);
	
	if (target.parentNode) {
		while (target = target.parentNode) {
			try{
				if (target.getAttribute('id')==id)
					return getId(id);
			}catch(e){
			}
		}
	}
	
	return null;
}
//end drag code





















/**
 * jscolor, JavaScript Color Picker
 *
 * @version 1.3.0
 * @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html
 * @author  Jan Odv�rko, http://odvarko.cz
 * @created 2008-06-15
 * @updated 2009-10-16
 * @link    http://jscolor.com
 */


var jscolor = {


	dir : '', // location of jscolor directory (leave empty to autodetect)
	bindClass : 'color', // class name
	binding : true, // automatic binding via <input class="...">
	preloading : true, // use image preloading?


	install : function() {
		jscolor.addEvent(window, 'load', jscolor.init);
	},


	init : function() {
		if(jscolor.binding) {
			jscolor.bind();
		}
		if(jscolor.preloading) {
			jscolor.preload();
		}
	},


	getDir : function() {
		if(!jscolor.dir) {
			var detected = jscolor.detectDir();
			jscolor.dir = detected!==false ? detected : 'jscolor/';
		}
		return jscolor.dir;
	},


	detectDir : function() {
		var base = location.href;

		var e = document.getElementsByTagName('base');
		for(var i=0; i<e.length; i+=1) {
			if(e[i].href) { base = e[i].href; }
		}

		var e = document.getElementsByTagName('script');
		for(var i=0; i<e.length; i+=1) {
			if(e[i].src && /(^|\/)jscolor\.js([?#].*)?$/i.test(e[i].src)) {
				var src = new jscolor.URI(e[i].src);
				var srcAbs = src.toAbsolute(base);
				srcAbs.path = srcAbs.path.replace(/[^\/]+$/, ''); // remove filename
				srcAbs.query = null;
				srcAbs.fragment = null;
				return srcAbs.toString();
			}
		}
		return false;
	},


	bind : function() {
		var matchClass = new RegExp('(^|\\s)('+jscolor.bindClass+')\\s*(\\{[^}]*\\})?', 'i');
		var e = document.getElementsByTagName('input');
		for(var i=0; i<e.length; i+=1) {
			var m;
			if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))) {
				var prop = {};
				if(m[3]) {
					try {
						eval('prop='+m[3]);
					} catch(eInvalidProp) {}
				}
				e[i].color = new jscolor.color(e[i], prop);
			}
		}
	},


	preload : function() {
		for(var fn in jscolor.imgRequire) {
			if(jscolor.imgRequire.hasOwnProperty(fn)) {
				jscolor.loadImage(fn);
			}
		}
	},


	images : {
		pad : [ 181, 101 ],
		sld : [ 16, 101 ],
		cross : [ 15, 15 ],
		arrow : [ 7, 11 ]
	},


	imgRequire : {},
	imgLoaded : {},


	requireImage : function(filename) {
		jscolor.imgRequire[filename] = true;
	},


	loadImage : function(filename) {
		if(!jscolor.imgLoaded[filename]) {
			jscolor.imgLoaded[filename] = new Image();
			jscolor.imgLoaded[filename].src = jscolor.getDir()+filename;
		}
	},


	fetchElement : function(mixed) {
		return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
	},


	addEvent : function(el, evnt, func) {
		if(el.addEventListener) {
			el.addEventListener(evnt, func, false);
		} else if(el.attachEvent) {
			el.attachEvent('on'+evnt, func);
		}
	},


	fireEvent : function(el, evnt) {
		if(!el) {
			return;
		}
		if(document.createEventObject) {
			var ev = document.createEventObject();
			el.fireEvent('on'+evnt, ev);
		} else if(document.createEvent) {
			var ev = document.createEvent('HTMLEvents');
			ev.initEvent(evnt, true, true);
			el.dispatchEvent(ev);
		} else if(el['on'+evnt]) { // alternatively use the traditional event model (IE5)
			el['on'+evnt]();
		}
	},


	getElementPos : function(e) {
		var e1=e, e2=e;
		var x=0, y=0;
		if(e1.offsetParent) {
			do {
				x += e1.offsetLeft;
				y += e1.offsetTop;
			} while(e1 = e1.offsetParent);
		}
		while((e2 = e2.parentNode) && e2.nodeName !== 'BODY') {
			x -= e2.scrollLeft;
			y -= e2.scrollTop;
		}
		return [x, y];
	},


	getElementSize : function(e) {
		return [e.offsetWidth, e.offsetHeight];
	},


	getMousePos : function(e) {
		if(!e) { e = window.event; }
		if(typeof e.pageX === 'number') {
			return [e.pageX, e.pageY];
		} else if(typeof e.clientX === 'number') {
			return [
				e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
				e.clientY + document.body.scrollTop + document.documentElement.scrollTop
			];
		}
	},


	getViewPos : function() {
		if(typeof window.pageYOffset === 'number') {
			return [window.pageXOffset, window.pageYOffset];
		} else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
			return [document.body.scrollLeft, document.body.scrollTop];
		} else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
			return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
		} else {
			return [0, 0];
		}
	},


	getViewSize : function() {
		if(typeof window.innerWidth === 'number') {
			return [window.innerWidth, window.innerHeight];
		} else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
			return [document.body.clientWidth, document.body.clientHeight];
		} else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
			return [document.documentElement.clientWidth, document.documentElement.clientHeight];
		} else {
			return [0, 0];
		}
	},


	URI : function(uri) { // See RFC3986

		this.scheme = null;
		this.authority = null;
		this.path = '';
		this.query = null;
		this.fragment = null;

		this.parse = function(uri) {
			var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/);
			this.scheme = m[3] ? m[2] : null;
			this.authority = m[5] ? m[6] : null;
			this.path = m[7];
			this.query = m[9] ? m[10] : null;
			this.fragment = m[12] ? m[13] : null;
			return this;
		};

		this.toString = function() {
			var result = '';
			if(this.scheme !== null) { result = result + this.scheme + ':'; }
			if(this.authority !== null) { result = result + '//' + this.authority; }
			if(this.path !== null) { result = result + this.path; }
			if(this.query !== null) { result = result + '?' + this.query; }
			if(this.fragment !== null) { result = result + '#' + this.fragment; }
			return result;
		};

		this.toAbsolute = function(base) {
			var base = new jscolor.URI(base);
			var r = this;
			var t = new jscolor.URI;

			if(base.scheme === null) { return false; }

			if(r.scheme !== null && r.scheme.toLowerCase() === base.scheme.toLowerCase()) {
				r.scheme = null;
			}

			if(r.scheme !== null) {
				t.scheme = r.scheme;
				t.authority = r.authority;
				t.path = removeDotSegments(r.path);
				t.query = r.query;
			} else {
				if(r.authority !== null) {
					t.authority = r.authority;
					t.path = removeDotSegments(r.path);
					t.query = r.query;
				} else {
					if(r.path === '') { // TODO: == or === ?
						t.path = base.path;
						if(r.query !== null) {
							t.query = r.query;
						} else {
							t.query = base.query;
						}
					} else {
						if(r.path.substr(0,1) === '/') {
							t.path = removeDotSegments(r.path);
						} else {
							if(base.authority !== null && base.path === '') { // TODO: == or === ?
								t.path = '/'+r.path;
							} else {
								t.path = base.path.replace(/[^\/]+$/,'')+r.path;
							}
							t.path = removeDotSegments(t.path);
						}
						t.query = r.query;
					}
					t.authority = base.authority;
				}
				t.scheme = base.scheme;
			}
			t.fragment = r.fragment;

			return t;
		};

		function removeDotSegments(path) {
			var out = '';
			while(path) {
				if(path.substr(0,3)==='../' || path.substr(0,2)==='./') {
					path = path.replace(/^\.+/,'').substr(1);
				} else if(path.substr(0,3)==='/./' || path==='/.') {
					path = '/'+path.substr(3);
				} else if(path.substr(0,4)==='/../' || path==='/..') {
					path = '/'+path.substr(4);
					out = out.replace(/\/?[^\/]*$/, '');
				} else if(path==='.' || path==='..') {
					path = '';
				} else {
					var rm = path.match(/^\/?[^\/]*/)[0];
					path = path.substr(rm.length);
					out = out + rm;
				}
			}
			return out;
		}

		if(uri) {
			this.parse(uri);
		}

	},


	/*
	 * Usage example:
	 * var myColor = new jscolor.color(myInputElement)
	 */

	color : function(target, prop) {


		this.required = true; // refuse empty values?
		this.adjust = true; // adjust value to uniform notation?
		this.hash = false; // prefix color with # symbol?
		this.caps = true; // uppercase?
		this.valueElement = target; // value holder
		this.styleElement = target; // where to reflect current color
		this.hsv = [0, 0, 1]; // read-only  0-6, 0-1, 0-1
		this.rgb = [1, 1, 1]; // read-only  0-1, 0-1, 0-1

		this.pickerOnfocus = true; // display picker on focus?
		this.pickerMode = 'HSV'; // HSV | HVS
		this.pickerPosition = 'bottom'; // left | right | top | bottom
		this.pickerFace = 10; // px
		this.pickerFaceColor = 'ThreeDFace'; // CSS color
		this.pickerBorder = 1; // px
		this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight'; // CSS color
		this.pickerInset = 1; // px
		this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow'; // CSS color
		this.pickerZIndex = 10000;


		for(var p in prop) {
			if(prop.hasOwnProperty(p)) {
				this[p] = prop[p];
			}
		}


		this.hidePicker = function() {
			if(isPickerOwner()) {
				removePicker();
			}
		};


		this.showPicker = function() {
			if(!isPickerOwner()) {
				var tp = jscolor.getElementPos(target); // target pos
				var ts = jscolor.getElementSize(target); // target size
				var vp = jscolor.getViewPos(); // view pos
				var vs = jscolor.getViewSize(); // view size
				var ps = [ // picker size
					2*this.pickerBorder + 4*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0],
					2*this.pickerBorder + 2*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[1]
				];
				var a, b, c;
				switch(this.pickerPosition.toLowerCase()) {
					case 'left': a=1; b=0; c=-1; break;
					case 'right':a=1; b=0; c=1; break;
					case 'top':  a=0; b=1; c=-1; break;
					default:     a=0; b=1; c=1; break;
				}
				var l = (ts[b]+ps[b])/2;
				var pp = [ // picker pos
					-vp[a]+tp[a]+ps[a] > vs[a] ?
						(-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
						tp[a],
					-vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
						(-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
						(tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
				];
				drawPicker(pp[a], pp[b]);
			}
		};


		this.importColor = function() {
			if(!valueElement) {
				this.exportColor();
			} else {
				if(!this.adjust) {
					if(!this.fromString(valueElement.value, leaveValue)) {
						styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
						styleElement.style.color = styleElement.jscStyle.color;
						this.exportColor(leaveValue | leaveStyle);
					}
				} else if(!this.required && /^\s*$/.test(valueElement.value)) {
					valueElement.value = '';
					styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
					styleElement.style.color = styleElement.jscStyle.color;
					this.exportColor(leaveValue | leaveStyle);

				} else if(this.fromString(valueElement.value)) {
					// OK
				} else {
					this.exportColor();
				}
			}
		};


		this.exportColor = function(flags) {
			if(!(flags & leaveValue) && valueElement) {
				var value = this.toString();
				if(this.caps) { value = value.toUpperCase(); }
				if(this.hash) { value = '#'+value; }
				valueElement.value = value;
			}
			if(!(flags & leaveStyle) && styleElement) {
				styleElement.style.backgroundColor =
					'#'+this.toString();
				styleElement.style.color =
					0.213 * this.rgb[0] +
					0.715 * this.rgb[1] +
					0.072 * this.rgb[2]
					< 0.5 ? '#FFF' : '#000';
			}
			if(!(flags & leavePad) && isPickerOwner()) {
				redrawPad();
			}
			if(!(flags & leaveSld) && isPickerOwner()) {
				redrawSld();
			}
		};


		this.fromHSV = function(h, s, v, flags) { // null = don't change
			h<0 && (h=0) || h>6 && (h=6);
			s<0 && (s=0) || s>1 && (s=1);
			v<0 && (v=0) || v>1 && (v=1);
			this.rgb = HSV_RGB(
				h===null ? this.hsv[0] : (this.hsv[0]=h),
				s===null ? this.hsv[1] : (this.hsv[1]=s),
				v===null ? this.hsv[2] : (this.hsv[2]=v)
			);
			this.exportColor(flags);
		};


		this.fromRGB = function(r, g, b, flags) { // null = don't change
			r<0 && (r=0) || r>1 && (r=1);
			g<0 && (g=0) || g>1 && (g=1);
			b<0 && (b=0) || b>1 && (b=1);
			var hsv = RGB_HSV(
				r===null ? this.rgb[0] : (this.rgb[0]=r),
				g===null ? this.rgb[1] : (this.rgb[1]=g),
				b===null ? this.rgb[2] : (this.rgb[2]=b)
			);
			if(hsv[0] !== null) {
				this.hsv[0] = hsv[0];
			}
			if(hsv[2] !== 0) {
				this.hsv[1] = hsv[1];
			}
			this.hsv[2] = hsv[2];
			this.exportColor(flags);
		};


		this.fromString = function(hex, flags) {
			var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i);
			if(!m) {
				return false;
			} else {
				if(m[1].length === 6) { // 6-char notation
					this.fromRGB(
						parseInt(m[1].substr(0,2),16) / 255,
						parseInt(m[1].substr(2,2),16) / 255,
						parseInt(m[1].substr(4,2),16) / 255,
						flags
					);
				} else { // 3-char notation
					this.fromRGB(
						parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
						parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
						parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
						flags
					);
				}
				return true;
			}
		};


		this.toString = function() {
			return (
				(0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
				(0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
				(0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
			);
		};


		function RGB_HSV(r, g, b) {
			var n = Math.min(Math.min(r,g),b);
			var v = Math.max(Math.max(r,g),b);
			var m = v - n;
			if(m === 0) { return [ null, 0, v ]; }
			var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
			return [ h===6?0:h, m/v, v ];
		}


		function HSV_RGB(h, s, v) {
			if(h === null) { return [ v, v, v ]; }
			var i = Math.floor(h);
			var f = i%2 ? h-i : 1-(h-i);
			var m = v * (1 - s);
			var n = v * (1 - s*f);
			switch(i) {
				case 6:
				case 0: return [v,n,m];
				case 1: return [n,v,m];
				case 2: return [m,v,n];
				case 3: return [m,n,v];
				case 4: return [n,m,v];
				case 5: return [v,m,n];
			}
		}


		function removePicker() {
			delete jscolor.picker.owner;
			jscolor.picker.boxB.parentNode.removeChild(jscolor.picker.boxB);
			delete jscolor.picker;
		}


		function drawPicker(x, y) {
			if(!jscolor.picker) {
				jscolor.picker = {
					box : document.createElement('div'),
					boxB : document.createElement('div'),
					pad : document.createElement('div'),
					padB : document.createElement('div'),
					padM : document.createElement('div'),
					sld : document.createElement('div'),
					sldB : document.createElement('div'),
					sldM : document.createElement('div')
				};
				for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize) {
					var seg = document.createElement('div');
					seg.style.height = segSize+'px';
					seg.style.fontSize = '1px';
					seg.style.lineHeight = '0';
					jscolor.picker.sld.appendChild(seg);
				}
				jscolor.picker.sldB.appendChild(jscolor.picker.sld);
				jscolor.picker.box.appendChild(jscolor.picker.sldB);
				jscolor.picker.box.appendChild(jscolor.picker.sldM);
				jscolor.picker.padB.appendChild(jscolor.picker.pad);
				jscolor.picker.box.appendChild(jscolor.picker.padB);
				jscolor.picker.box.appendChild(jscolor.picker.padM);
				jscolor.picker.boxB.appendChild(jscolor.picker.box);
				jscolor.picker.boxB.setAttribute('id', 'divcolorpicker');
			}

			var p = jscolor.picker;

			// recompute controls positions
			posPad = [
				x+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset,
				y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ];
			posSld = [
				null,
				y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ];

			// controls interaction
			p.box.addEventListener('mouseup', function() { target.focus(); }, false);
			p.box.addEventListener('mouseout', function() { target.focus(); }, false);
			p.box.addEventListener('mousedown', function() { abortBlur=true; }, false);
			p.box.addEventListener('mousemove', function(e) { holdPad && setPad(e); holdSld && setSld(e); }, false);
			p.padM.addEventListener('mouseup', function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change'); } }, false);
			p.padM.addEventListener('mouseout', function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change'); } }, false);
			p.padM.addEventListener('mousedown', function(e) { holdPad=true; setPad(e); }, false);
			p.sldM.addEventListener('mouseup', function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change'); } }, false);
			p.sldM.addEventListener('mouseout', function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change'); } }, false);
			p.sldM.addEventListener('mousedown', function(e) { holdSld=true; setSld(e); }, false);

			// picker
			p.box.style.width = 4*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] + 'px';
			p.box.style.height = 2*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[1] + 'px';

			// picker border
			p.boxB.style.position = 'absolute';
			p.boxB.style.clear = 'both';
			p.boxB.style.left = x+'px';
			p.boxB.style.top = y+'px';
			p.boxB.style.zIndex = THIS.pickerZIndex;
			p.boxB.style.border = THIS.pickerBorder+'px solid';
			p.boxB.style.borderColor = THIS.pickerBorderColor;
			p.boxB.style.background = THIS.pickerFaceColor;

			// pad image
			p.pad.style.width = jscolor.images.pad[0]+'px';
			p.pad.style.height = jscolor.images.pad[1]+'px';

			// pad border
			p.padB.style.position = 'absolute';
			p.padB.style.left = THIS.pickerFace+'px';
			p.padB.style.top = THIS.pickerFace+'px';
			p.padB.style.border = THIS.pickerInset+'px solid';
			p.padB.style.borderColor = THIS.pickerInsetColor;

			// pad mouse area
			p.padM.style.position = 'absolute';
			p.padM.style.left = '0';
			p.padM.style.top = '0';
			p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px';
			p.padM.style.height = p.box.style.height;
			p.padM.style.cursor = 'crosshair';

			// slider image
			p.sld.style.overflow = 'hidden';
			p.sld.style.width = jscolor.images.sld[0]+'px';
			p.sld.style.height = jscolor.images.sld[1]+'px';

			// slider border
			p.sldB.style.position = 'absolute';
			p.sldB.style.right = THIS.pickerFace+'px';
			p.sldB.style.top = THIS.pickerFace+'px';
			p.sldB.style.border = THIS.pickerInset+'px solid';
			p.sldB.style.borderColor = THIS.pickerInsetColor;

			// slider mouse area
			p.sldM.style.position = 'absolute';
			p.sldM.style.right = '0';
			p.sldM.style.top = '0';
			p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px';
			p.sldM.style.height = p.box.style.height;
			try {
				p.sldM.style.cursor = 'pointer';
			} catch(eOldIE) {
				p.sldM.style.cursor = 'hand';
			}

			// load images 
			switch(modeID) 
			{
				case 0: 
					var padImg ="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"; 
				break;//hs
				
				case 1: 
					var padImg = "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"; 
				break;//hv
			}
			p.padM.style.background = "url(data:image/png;base64,R0lGODlhDwAPAKEBAAAAAP///////////yH5BAEKAAIALAAAAAAPAA8AAAIklB8Qx53b4otSUWcvyiz4/4AeQJbmKY4p1HHapBlwPL/uVRsFADs=) no-repeat";
			p.sldM.style.background = "url(data:image/png;base64,R0lGODlhBwALAKECAAAAAP///6g8eKg8eCH5BAEKAAIALAAAAAAHAAsAAAITTIQYcLnsgGxvijrxqdQq6DRJAQA7) no-repeat";
			p.pad.style.background = "url(data:image/png;base64,"+padImg+") 0 0 no-repeat";

			// place pointers
			redrawPad();
			redrawSld();


			jscolor.picker.owner = THIS;
			document.getElementsByTagName('body')[0].appendChild(p.boxB);
		}


		function redrawPad() {
			// redraw the pad pointer
			switch(modeID) {
				case 0: var yComponent = 1; break;
				case 1: var yComponent = 2; break;
			}
			var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1));
			var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1));
			jscolor.picker.padM.style.backgroundPosition =
				(THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
				(THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px';

			// redraw the slider image
			var seg = jscolor.picker.sld.childNodes;

			switch(modeID) {
				case 0:
					var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1);
					for(var i=0; i<seg.length; i+=1) {
						seg[i].style.backgroundColor = 'rgb('+
							(rgb[0]*(1-i/seg.length)*100)+'%,'+
							(rgb[1]*(1-i/seg.length)*100)+'%,'+
							(rgb[2]*(1-i/seg.length)*100)+'%)';
					}
					break;
				case 1:
					var rgb, s, c = [ THIS.hsv[2], 0, 0 ];
					var i = Math.floor(THIS.hsv[0]);
					var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i);
					switch(i) {
						case 6:
						case 0: rgb=[0,1,2]; break;
						case 1: rgb=[1,0,2]; break;
						case 2: rgb=[2,0,1]; break;
						case 3: rgb=[2,1,0]; break;
						case 4: rgb=[1,2,0]; break;
						case 5: rgb=[0,2,1]; break;
					}
					for(var i=0; i<seg.length; i+=1) {
						s = 1 - 1/(seg.length-1)*i;
						c[1] = c[0] * (1 - s*f);
						c[2] = c[0] * (1 - s);
						seg[i].style.backgroundColor = 'rgb('+
							(c[rgb[0]]*100)+'%,'+
							(c[rgb[1]]*100)+'%,'+
							(c[rgb[2]]*100)+'%)';
					}
					break;
			}
		}


		function redrawSld() {
			// redraw the slider pointer
			switch(modeID) {
				case 0: var yComponent = 2; break;
				case 1: var yComponent = 1; break;
			}
			var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1));
			jscolor.picker.sldM.style.backgroundPosition =
				'0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px';
		}


		function isPickerOwner() {
			return jscolor.picker && jscolor.picker.owner === THIS;
		}


		function blurTarget() {
			if(valueElement === target) {
				THIS.importColor();
			}
			if(THIS.pickerOnfocus) {
				THIS.hidePicker();
			}
		}


		function blurValue() {
			if(valueElement !== target) {
				THIS.importColor();
			}
		}


		function setPad(e) {
			var posM = jscolor.getMousePos(e);
			var x = posM[0]-posPad[0];
			var y = posM[1]-posPad[1];
			switch(modeID) {
				case 0: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld); break;
				case 1: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld); break;
			}
		}


		function setSld(e) {
			var posM = jscolor.getMousePos(e);
			var y = posM[1]-posPad[1];
			switch(modeID) {
				case 0: THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad); break;
				case 1: THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad); break;
			}
		}


		var THIS = this;
		var modeID = this.pickerMode.toLowerCase()==='hvs' ? 1 : 0;
		var abortBlur = false;
		var
			valueElement = jscolor.fetchElement(this.valueElement),
			styleElement = jscolor.fetchElement(this.styleElement);
		var
			holdPad = false,
			holdSld = false;
		var
			posPad,
			posSld;
		var
			leaveValue = 1<<0,
			leaveStyle = 1<<1,
			leavePad = 1<<2,
			leaveSld = 1<<3;

		// target
		jscolor.addEvent(target, 'focus', function() {
			if(THIS.pickerOnfocus) { THIS.showPicker(); }
		});
		jscolor.addEvent(target, 'blur', function() {
			if(!abortBlur) {
				window.setTimeout(function(){ abortBlur || blurTarget(); abortBlur=false; }, 0);
			} else {
				abortBlur = false;
			}
		});

		// valueElement
		if(valueElement) {
			var updateField = function() {
				THIS.fromString(valueElement.value, leaveValue);
			};
			jscolor.addEvent(valueElement, 'keyup', updateField);
			jscolor.addEvent(valueElement, 'input', updateField);
			jscolor.addEvent(valueElement, 'blur', blurValue);
			valueElement.setAttribute('autocomplete', 'off');
		}

		// styleElement
		if(styleElement) {
			styleElement.jscStyle = {
				backgroundColor : styleElement.style.backgroundColor,
				color : styleElement.style.color
			};
		}

		// require images
		switch(modeID) {
			case 0: jscolor.requireImage('hs.png'); break;
			case 1: jscolor.requireImage('hv.png'); break;
		}
		jscolor.requireImage('cross.gif');
		jscolor.requireImage('arrow.gif');

		this.importColor();
	}

};