PictureSelector

By kfx666 Last update Apr 21, 2008 — Installed 188 times.

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

// ==UserScript==
// @name           pSelRange2
// @namespace      pSelRange2
// @include        
// ==/UserScript==

// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
// #      all original thoughts by the author"thumbs" on this link : 
// #      Thumbs only gallery browser -  http://userscripts.org/scripts/show/3413
// #
// #     essentiol additions and functionality by "kfx666"
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 

 
function addGlobalStyle(css) {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
}


// PictureSelector Global Variable Initiation and functions START
// CONCEPT: // GALLERIE-LINK-PAGES // IMAGES // VIDEOS 

var kChoice = new Array(); // kChoice holds the Information for each picture whether it's selected by the user or not (for download of course)
var kColOff = '#44605C'; // kColOff is the Color for unselected pics
var kColOn =  '#99FF99'; // kColOn is the Color for selected pics
var kNumPicks = 0;	// kNumPicks is the total amount of currently selected pics
var kPicksPreview = '';	// kPicksPreview is the HTML-String for the little preview thumbs on the right side of the status bar, the "Collection Basket"

// toggle picture with the index "inp" on or off
function kToggle(inp) {
	var allElements, thisElement;
	kTmpChecker = false;
	allElements = document.getElementsByTagName('BUTTON');
	//iterate through every Button. EVERY Button is a picture in this Version, so we actually iterate through the pictures themselves
	for (var i = 0; i < allElements.length; i++) {
    	thisElement = allElements[i];
    	if (i==inp) {	// if the cylcle found the clicked one....
    		kTmpChecker = kChoice[i]; // will the Toggle be a Toggle-Off or Toggle-On ? save the current state to the temp variable kTmpChecker
    		kChoice[i] = !kTmpChecker; // apply the toggle to the global variable
    		if (kTmpChecker) {thisElement.innerHTML='<table bgcolor="'+kColOff  //this is a Toggle-Off
    							+'" width="69" border="0"><tr><td width="5" height="21">&nbsp;</td><td width="45" height="21">&nbsp;</td><td width="5" height="21">&nbsp;</td></tr><tr><td height="21">&nbsp;</td><td><img src="'+thumbLinks[i].getElementsByTagName('img')[0].src+'"></td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td><div align="center">'+i+'</div></td><td>&nbsp;</td></tr></table>';
    							kNumPicks--;} // decrease the Number of Selected Pictures by one
    					else {thisElement.innerHTML='<table bgcolor="'+kColOn // and a Toggle-On
    							+'" width="69" border="0"><tr><td width="5" height="21">&nbsp;</td><td width="45" height="21">&nbsp;</td><td width="5" height="21">&nbsp;</td></tr><tr><td height="21">&nbsp;</td><td><img src="'+thumbLinks[i].getElementsByTagName('img')[0].src+'"></td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td><div align="center">'+i+'</div></td><td>&nbsp;</td></tr></table>';
    							kNumPicks++;}} // increase the Number of Selected Pictures by one
    }
	kUpdateState(); // update the status bar to reflect these changes... two numbers have changed and one pic was added to or removed from the "Basket"
}

// update the "Status Bar"
function kUpdateState(){
 	var sH,sW; //sizeHeight and sizeWidth
 	var kSize = 25; //targetSize
 	kStatusBar.InnerHTML = ''; // "delete the Status Bar completely first
 	
 	// this is a string which consists of the small preview thumbs in the form <img 1> + <img 2> + .....
 	// the img-src is the same as on the buttons but have to be scaled down here first
 	kPicksPreview = '';
 	 	
 	for (t = 0; t < thumbLinks.length; t++){
 		if (kChoice[t]){ 		// if the pic is selected then scale it down and add it to the string kPicksPreview
 			sW =(thumbLinks[t].getElementsByTagName('img')[0].src.naturalHeight * kSize / thumbLinks[t].getElementsByTagName('img')[0].src.naturalWidth) +'px';
 			sH = kSize + 'px';
 			kPicksPreview += '<a href="'+thumbLinks[t].href+'"><img src="'+thumbLinks[t].getElementsByTagName('img')[0].src+'" alt=".." height="'+sH+'" width="'+sW+'" border="2"></a> ';}
  	}
	// now that kPicksPreview has been rebuilt, we can reconstruct the whole Status Bar

	aaa = 'Get these'+ kNumPicks + ' -'+(thumbLinks.length-kNumPicks)+ '(' + thumbLinks.length+')';


	kStatusBar.innerHTML = '<body style="color: rgb(103, 147, 167); '
	+ 'background-color: rgb(27, 51, 76);" alink="#ffcc00" link="#0686cf" vlink="#1970a1"><table' 
	+ 'style="text-align: left; width: 100%; color: rgb(109, 156, 177); '
	+ 'background-color: rgb(35, 49, 57); border="1" cellpadding="2"'
	+ 'cellspacing="2"><tbody><tr><td>' + aaa + '</td><td>'+ kPicksPreview + '</td></tr></tbody></table>';
	



}

// Invert can also functions as "Select All" if nothing is selected yet
function kInvertSelection(){
	// Basically this is a toggle for every pic... very similar to kToggle() thus self-explanitory
	var allElements, thisElement;
	var kTmpChecker = false;
	allElements = document.getElementsByTagName('BUTTON');
	for (var i = 0; i < allElements.length; i++) {
    	thisElement = allElements[i];
    	kTmpChecker = kChoice[i];
    	   			if (kTmpChecker) {thisElement.innerHTML='<table bgcolor="'+kColOff+'" width="69" border="0"><tr><td width="5" height="21">&nbsp;</td><td width="45" height="21">&nbsp;</td><td width="5" height="21">&nbsp;</td></tr><tr><td height="21">&nbsp;</td><td><img src="'+thumbLinks[i].getElementsByTagName('img')[0].src+'"></td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td><div align="center">'+i+'</div></td><td>&nbsp;</td></tr></table>';kNumPicks--;}
    					  else {thisElement.innerHTML='<table bgcolor="'+kColOn+'" width="69" border="0"><tr><td width="5" height="21">&nbsp;</td><td width="45" height="21">&nbsp;</td><td width="5" height="21">&nbsp;</td></tr><tr><td height="21">&nbsp;</td><td><img src="'+thumbLinks[i].getElementsByTagName('img')[0].src+'"></td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td><div align="center">'+i+'</div></td><td>&nbsp;</td></tr></table>';kNumPicks++;}
    	kChoice[i] = !kTmpChecker;
    	}
    kUpdateState();
}

function kNextPage() {
	
var xa = GM_getValue('kPages');
var xb = xa.split(" ");
var xc = new Array(100);

var xcnt = 0;

for (var t=0; t < xb.length; t++) {
	if (xb[t].length > 2) {	xc[xcnt] = xb[t];	xcnt++;
	}
}

var hier = GM_getValue('kCur');

hier++;
GM_setValue('kCur',hier);

var xHere = 'Page '+ hier + ' of ' + (xcnt-1);
GM_setValue('kHere',xHere);

var kb = xcnt - hier - 1;
var kBubble = "";

for (var r = 0; r < kb; r++) { kBubble += "o"};

GM_setValue('kProg',kBubble);

if (hier < (xcnt)) { window.location.href = xc[hier]; }


}

function kNextPageSkip() {
	
var xa = GM_getValue('kPages');
var xb = xa.split("� ");
var xc = new Array(100);

var xcnt = 0;

for (var t=0; t < xb.length; t++) {
	if (xb[t].length > 2) {	xc[xcnt] = xb[t];	xcnt++;
	}
}

var hier = GM_getValue('kCur');
hier++;
hier++;
GM_setValue('kCur',hier);

//alert(xc[hier]);
window.location.href = xc[hier];


}

// END PictureSelector Global Variable Initiation and functions
//             ...........    a lot of original stuff from "thumbs" again ...
// ==========================================================================

var imgMinSize = 50;
var bannerRatio = 1.8;

var reqTumbs = 5;
var reqVideos = 2;
var reqGalleries = 25;

var thumbLinks = [];
var videoLinks = [];
var galleryLinks = [];

var collectedGalleries = GM_getValue('collectedGalleries', '').split('|');

var scaleThumbs = GM_getValue('scaleThumbs', true);
var scaleSize = GM_getValue('scaleSize', 150);

var filterNestedUrls = GM_getValue('filterNestedUrls', true);
var modifyLinks = GM_getValue('modifyLinks', true);
var modifyAllLinks = GM_getValue('modifyAllLinks', true);

var linkFiltering = GM_getValue('linkFiltering', false);
var filterExpression = new RegExp(GM_getValue('filterExpression', 'unwanted'), 'i');

var i, a, img, button, label;

GM_registerMenuCommand('Visit random collected thumb gallery', visitRandomCollected);

function scaleFullImg(img) {
	if (img.naturalHeight > 0) {
		if (img.naturalHeight > document.body.parentNode.scrollHeight) {
			img.style.width = (img.naturalWidth * document.body.parentNode.scrollHeight / img.naturalHeight) +'px';
			img.style.height = document.body.parentNode.scrollHeight +'px';
		}
		else if (img.naturalWidth > document.body.parentNode.scrollWidth) {
			img.style.height = (img.naturalHeight * document.body.parentNode.scrollWidth / img.naturalWidth) +'px';
			img.style.width = document.body.parentNode.scrollWidth +'px';
		}
		else {
			img.style.height = img.naturalHeight +'px';
			img.style.width = img.naturalWidth +'px';
		}
		img.style.marginLeft = ((document.body.parentNode.scrollWidth - parseInt(img.style.width, 10)) / 2) + 'px';
		img.style.marginTop = ((document.body.parentNode.offsetHeight - parseInt(img.style.height, 10)) / 2) + 'px';
		img.style.display = 'block';
	}
	else {
		setTimeout(scaleFullImg, 100, img);
	}
}

function scaleImg(img) {
	if (img.naturalHeight > 0) {
		if (scaleThumbs) {
			if (img.naturalWidth > scaleSize && img.naturalWidth >= img.naturalHeight) {
				img.style.height = (img.naturalHeight * scaleSize / img.naturalWidth) +'px';
				img.style.width = scaleSize + 'px';
			}
			else if (img.naturalHeight > scaleSize && img.naturalHeight > img.naturalWidth) {
				img.style.width = (img.naturalWidth * scaleSize / img.naturalHeight) +'px';
				img.style.height = scaleSize +'px';
			}
		}
		else {
			img.style.width = img.naturalWidth +'px';
			img.style.height = img.naturalHeight +'px';
		}
	}
	else {
		setTimeout(scaleImg, 500, img);
	}
}

function scaleImages() {
	img = document.getElementsByTagName('img');
	if (img && img.length) {
		for (i = 0; i < img.length; i++) {
			scaleImg(img[i]);
		}
	}
}

function setLinkTypeClass(a) {
	if (a.host == document.location.host) {
		a.className = 'intLink';
		a.title = unescape(a.pathname + a.search);
	}
	else {
		a.className = 'extLink';
		a.title = a.host;
	}
}

// Remove links that match filterExpression
function filterLinks() {
	var links = div.getElementsByTagName('a');
	for (i = links.length - 1; i >= 0; i--) {
		if (links[i].href.match(filterExpression)) {
			links[i].parentNode.removeChild(links[i]);
		}
	}
}

// Modify links with nested URLs
function removeLinkNesting() {
	var links = div.getElementsByTagName('a');
	for (i = 0; i < links.length; i++) {
		// Needs improvement
		links[i].href = unescape(links[i]).replace(/^(http:\/\/.+)(http:\/\/[^&]+)(.*)$/, '$2');
		setLinkTypeClass(links[i]);
	}
}

function updateColList(colDiv, remove) {
	if (remove) {
		collectedGalleries = [];
		var checks = colDiv.getElementsByTagName('input');
		for (i = 0; i < checks.length; i++) {
			if (!checks[i].checked) collectedGalleries.push(checks[i].value);
		}
		if (collectedGalleries.length > 0) {
			GM_setValue('collectedGalleries', collectedGalleries.join('|'));
		}
		else {
			GM_setValue('collectedGalleries', '');
		}
	}
	collectedGalleries.sort();
	var newCol = '';
	document.body.className = '';
	for (i = 0; i < collectedGalleries.length; i++) {
		if (collectedGalleries[i] != '') {
			newCol += '<label><input type=checkbox value='+ collectedGalleries[i];
			if (collectedGalleries[i] == document.location.href) {
				document.body.className = 'inCol';
				newCol += ' checked';
			}
			newCol += '> <a href='+ collectedGalleries[i] +'>'+ collectedGalleries[i] +'</a></label>';
		}
	}
	colDiv.innerHTML = newCol;
}

function visitRandomCollected() {
	if (collectedGalleries.length > 1) {
		var url;
		do {
			url = collectedGalleries[Math.floor(collectedGalleries.length * (Math.random() - 0.0001))];
		}
		while (url == document.location.href);
		document.location.href = url;
	}
}

var img = document.getElementsByTagName('img');
if (img && img.length) {
	for (i = 0; i < img.length; i++) {
		if (img[i].parentNode.nodeName == 'A') {
			if (linkFiltering && img[i].parentNode.href.match(filterExpression)) {
				continue;
			}
			else if (img[i].parentNode.href.match(/\.jpe?g$/i)) {
				thumbLinks.push(img[i].parentNode.cloneNode(true));
			}
			else if (
				img[i].parentNode.href.match(/\.(mpe?g|wmv|asf|avi)$/i) &&
				img[i].width > imgMinSize &&
				img[i].height > imgMinSize &&
				img[i].width / img[i].height < bannerRatio &&
				img[i].height / img[i].width < bannerRatio
			) {
				videoLinks.push(img[i].parentNode.cloneNode(true));
			}
			else if (
				img[i].src.match(/\.jpe?g$/i) &&
				img[i].width > imgMinSize &&
				img[i].height > imgMinSize &&
				img[i].width / img[i].height < bannerRatio &&
				img[i].height / img[i].width < bannerRatio
			) {
				galleryLinks.push(img[i].parentNode.cloneNode(true));
			}
		}
	}
}

if (
	thumbLinks.length >= reqTumbs ||
	videoLinks.length >= reqVideos ||
	galleryLinks.length >= reqGalleries
) {
	document.body.innerHTML = '';

	for (i = 0; i < document.styleSheets.length; i++)
		document.styleSheets[i].disabled = true;

	for (i = document.body.attributes.length - 1; i >= 0; i--)
		document.body.removeAttribute(document.body.attributes[i].nodeName);

	GM_addStyle('html { min-height: 100%; }');
	GM_addStyle('body { min-height: 100%; margin: 0 5px; background: #344; }');
	GM_addStyle('body.inCol { background: #322; }');
	GM_addStyle('* { font-size: 11px; font-family: "Verdana"; }');
	GM_addStyle('h1 { font-size: 15px; }');
	GM_addStyle('a { color: #00e; }');
	GM_addStyle('a:visited { color: #551a8b; }');
	GM_addStyle('a:active { color: #e00; }');
	GM_addStyle('a img { margin: 1px; border-width: 2px; }');
	GM_addStyle('a:visited img { opacity: 0.5; }');
	GM_addStyle('button { margin: 4px 4px 0 0; padding: 0; }');
	GM_addStyle('p { margin: 4px 4px 0 0; padding: 0; color: #2CA7D0; border:4px; border-style:solid}');
	GM_addStyle('#thumbs { clear: both; }');

	var div = document.createElement('div');
	div.setAttribute('id', 'thumbs');
	document.body.appendChild(div);
}
// =======================================================================================
// =						IMAGES-MODE with "PictureSelector"
// =								added by kfx666
// =======================================================================================

// Images
if (thumbLinks.length >= reqTumbs) {
	document.title = 'Images - '+ document.title;
  	// add the Invert-"Button" .... i admit it's a workaround, it should actually be a real button
  	// Origin of the problem is: the script now treats every button as a picture ...
  	// so this thing which should not be treated as a picture, must be of a different type, "text" for example.

// 	kbtn = document.createElement('text');
// 	kbtn.innerHTML ='[_____INVERT SELECTION_____]';
// 	kbtn.setAttribute('name', 'kbtn');
//	kbtn.addEventListener('click', function(){kInvertSelection()}, false);
//	div.appendChild(kbtn);
	
	kStatusBar = document.createElement('kStatusBar');
	
	kHeader = document.createElement('kHeader');
	kHeader.innerHTML = '<table style="text-align: left; width: 100%;" border="1" cellpadding="2" cellspacing="2">'
	+'<tbody><tr><td> <div id="aaaa"></div> </td></tr><tr><td>'
	+'<table style="text-align: left; width: 100%;" border="1" cellpadding="2" cellspacing="2">'
	+'<tbody><tr><td> <div id="bbbb"></div> </td><td> <div id="cccc"></div> </td>'
	+'<td> <div id="dddd"></div> </td></tr></tbody></table></td></tr></tbody></table>';
	
	kHeader.addEventListener('click', function(){kNextPage()}, false);
	
	div.appendChild(kHeader);
	
 	kbtn = document.createElement('p');
	
	var xhier = GM_getValue('kHere');
	
	var bl = GM_getValue('kSource');
	var kback = '<a href="'+ bl +'" color="white"> back </a>';
	
	kbtn.innerHTML ='<center>' + kback + ' - ' + xhier + '</center>';
 	kbtn.setAttribute('name', 'kbtn');
	
	document.getElementById("bbbb").appendChild(kbtn);

	nextbtn = document.createElement('p');
 	//nextbtn.innerHTML ='<center><h4>N E X T</h4></center>';
	zz = GM_getValue('kProg');
	nextbtn.innerHTML ='<center>N E X T <br>'+ zz + '</center>';
 	nextbtn.setAttribute('name', 'nextbtn');
	nextbtn.addEventListener('click', function(){kNextPage()}, false);
  	document.getElementById("cccc").appendChild(nextbtn);
	
	nextskipbtn = document.createElement('p');
 	nextskipbtn.innerHTML ='<center>Invert</center>';
 	nextskipbtn.setAttribute('name', 'nextskipbtn');
	nextskipbtn.addEventListener('click', function(){kInvertSelection()}, false);
	document.getElementById("dddd").appendChild(nextskipbtn);
	
	aaa = 'Get:'+kNumPicks+'/'+(thumbLinks.length-kNumPicks)+'/'+thumbLinks.length;
	bbb = '>>>>';

kStatusBar.innerHTML = '<body style="color: rgb(103, 147, 167); '
+ 'background-color: rgb(27, 51, 76);" alink="#ffcc00" link="#0686cf" vlink="#1970a1"><table' + 'style="text-align: left; width: 100%; color: rgb(109, 156, 177); '
+ 'background-color: rgb(35, 49, 57); border="1" cellpadding="2"'
+ 'cellspacing="2"><tbody><tr><td>' + aaa + '</td><td>'+ bbb +'</td></tr></tbody></table>';

  
  kStatusBar.id = 'abc';
 	div.appendChild(kStatusBar);

  document.body.style.paddingBottom = "4em";
  window.addEventListener( "load", function() { document.body.appendChild(div); }, true);
  addGlobalStyle('#abc {position: fixed; left: 0; right: 0; bottom: 0;top: auto;' +
  '  border-top: 1px solid silver; background: black; color: white;  margin: 1em 0 0 0;' +
  '  padding: 5px 0 0.4em 0; width: 100%;');



	// now the pictures are added .... each "b" is a picture-button	
	for (i = 0; i < thumbLinks.length; i++) {
		imgStr = '<img src="'+thumbLinks[i].getElementsByTagName('img')[0].src+'">';
		b = document.createElement('button');
		b.innerHTML='<table bgcolor="'+kColOff+'" width="69" border="0"><tr><td width="5" height="21">&nbsp;</td><td width="45" height="21"></td><td width="5" height="21">&nbsp;</td></tr><tr><td height="21">&nbsp;</td><td>'+imgStr+'</td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td><div align="center">'+i+'</div></td><td>&nbsp;</td></tr></table>'
		b.setAttribute('type', 'button');
		b.setAttribute('name', i);
		b.addEventListener('click', function(e){kToggle(e.currentTarget.name)}, false);
		// all Pictures are initially unselected:
		kChoice.push(false);
		div.appendChild(b);
	}
}
// ============== END of kfx666-PictureSelector Modifications =================================

// Videos
else if (videoLinks.length >= reqVideos) {
	document.title = 'Videos   - '+ document.title;
	div.innerHTML = '';
	
	kHeader = document.createElement('kHeader');
	kHeader.innerHTML = '<table style="text-align: left; width: 100%;" border="1" cellpadding="2" cellspacing="2">'
	+'<tbody><tr><td> <div id="aaaa"></div> </td></tr><tr><td>'
	+'<table style="text-align: left; width: 100%;" border="1" cellpadding="2" cellspacing="2">'
	+'<tbody><tr><td> <div id="bbbb"></div> </td><td> <div id="cccc"></div> </td>'
	+'<td> <div id="dddd"></div> </td></tr></tbody></table></td></tr></tbody></table>';
	div.appendChild(kHeader);
	
 	kbtn = document.createElement('p');
	
	var xhier = GM_getValue('kHere');
	
	var bl = GM_getValue('kSource');
	var kback = '<a href="'+ bl +'"> BACK </a>';
	
	kbtn.innerHTML ='<center>' + ' -  ' + kback + ' - ' + xhier + '</center>';
 	kbtn.setAttribute('name', 'kbtn');
	document.getElementById("bbbb").appendChild(kbtn);

	nextbtn = document.createElement('p');
 	//nextbtn.innerHTML ='<center><h4>N E X T</h4></center>';
	zz = GM_getValue('kProg');
	nextbtn.innerHTML ='<center>N E X T <br>'+ zz + '</center>';
 	nextbtn.setAttribute('name', 'nextbtn');
	nextbtn.addEventListener('click', function(){kNextPage()}, false);
  	document.getElementById("cccc").appendChild(nextbtn);
	
	nextskipbtn = document.createElement('p');
 	nextskipbtn.innerHTML ='<center> v 0031 </center>';
 	nextskipbtn.setAttribute('name', 'nextskipbtn');
	//nextskipbtn.addEventListener('click', function(){kNextPageSkip()}, false);
	document.getElementById("dddd").appendChild(nextskipbtn);
	
	
	

	for (i = 0; i < videoLinks.length; i++) {
		a = document.createElement('a');
		a.href = videoLinks[i].href;
		div.appendChild(a);

		img = document.createElement('img');
		img.src = videoLinks[i].getElementsByTagName('img')[0].src;
		a.appendChild(img);
	}
}

// Gallery
else if (galleryLinks.length >= reqGalleries) {
	div.className = 'gallery';
	div.innerHTML = '<h1>'+ document.title +'</h1>';
	document.title = 'Gallery   - '+ document.title;

	GM_addStyle('fieldset { height: 200px; -moz-border-radius: 8px; border: 1px solid #aaa; margin-top: -5px; padding-bottom: 0; }');
	GM_addStyle('label { display: block; cursor: pointer; line-height: 18px; }');
	GM_addStyle('.indent { margin-left: 17px; }');
	GM_addStyle('.indent.double { margin-left: 34px; }');
	GM_addStyle('input[type="checkbox"] { width: 12px; height: 12px; margin: 0; }');
	GM_addStyle('input[type="text"] { padding: 1px; border: 1px solid #aaa; width: 100%; }');
	GM_addStyle('input[type="text"][size] { width: auto; }');
	GM_addStyle('fieldset hr { height: 6px; display: block; border: 0; margin: 0; }');
	GM_addStyle('#thumbs.gallery { position: absolute; top: 220px; right: 0; bottom: 0; left: 0; overflow: auto; padding: 0 8px; }');
	GM_addStyle('#thumbs.gallery a.intLink img { border-color: #900; }');
	GM_addStyle('#thumbs.gallery a.extLink img { border-color: #090; }');
	GM_addStyle('#colFs { width: 400px; margin-right: 10px; float: left; }');
	GM_addStyle('#setFs { width: 240px; float: left; }');
	GM_addStyle('#colDiv { height: 154px; white-space: nowrap; overflow: auto; border: 1px solid #aaa; padding: 0 4px; background: #222; }');

	var form = document.createElement('form');

	// Gallery collection
	var fs = document.createElement('fieldset');
	form.appendChild(fs);
	fs.setAttribute('id', 'colFs')
	fs.innerHTML = '<legend>Gallery collection</legend>';

	var colDiv = document.createElement('div');
	fs.appendChild(colDiv);
	colDiv.setAttribute('id', 'colDiv');
	updateColList(colDiv, false);

	// Delete selected galleries
	button = document.createElement('button');
	button.innerHTML = '<u>D</u>elete selected';
	button.setAttribute('type', 'button');
	button.setAttribute('accesskey', 'd');
	button.addEventListener('click', function(e){
		if (confirm('Delete selected galleries?')) {
			updateColList(colDiv, true);
		}
	}, false);
	fs.appendChild(button);

	// Add current gallery
	button = document.createElement('button');
	button.innerHTML = '<u>A</u>dd current';
	button.setAttribute('type', 'button');
	button.setAttribute('accesskey', 'a');
	button.addEventListener('click', function(e){
		collectedGalleries = GM_getValue('collectedGalleries', '').split('|');
		if (collectedGalleries.join('|').indexOf(document.location.href) == -1) {
			collectedGalleries.push(document.location.href);
			GM_setValue('collectedGalleries', collectedGalleries.join('|').replace(/^\||\|$/, ''));
			updateColList(colDiv, false);
		}
	}, false);
	fs.appendChild(button);

	// Visit random gallery
	button = document.createElement('button');
	button.innerHTML = 'Visit <u>r</u>andom';
	button.setAttribute('type', 'button');
	button.setAttribute('accesskey', 'r');
	button.addEventListener('click', visitRandomCollected, false);
	fs.appendChild(button);

	// Settings
	var fs = document.createElement('fieldset');
	form.appendChild(fs);
	fs.setAttribute('id', 'setFs')
	fs.innerHTML = '<legend>Settings</legend>';

	// Scale thumbs
	label = document.createElement('label');
	label.innerHTML = '<input type=checkbox> Scale thumbnails down to:';
	if (scaleThumbs) label.firstChild.setAttribute('checked', 'checked');
	label.firstChild.addEventListener('click', function(e){
		scaleThumbs = !scaleThumbs;
		GM_setValue('scaleThumbs', scaleThumbs);
		if (scaleThumbs) e.currentTarget.setAttribute('checked', 'checked');
		else e.currentTarget.removeAttribute('checked');
		scaleImages();
	}, false);
	fs.appendChild(label);

	// Scale size
	label = document.createElement('label');
	label.innerHTML = '<input type=text size=3 value='+ scaleSize +'> pixels';
	label.className = 'indent';
	label.firstChild.addEventListener('change', function(e){
		scaleSize = parseInt(e.currentTarget.value, 10);
		GM_setValue('scaleSize', scaleSize);
		scaleImages();
	}, false);
	fs.appendChild(label);

	fs.appendChild(document.createElement('hr'));

	// Nested URLs
	label = document.createElement('label');
	label.innerHTML = '<input type=checkbox> Try to use URL nested in link';
	if (filterNestedUrls) label.firstChild.setAttribute('checked', 'checked');
	label.firstChild.addEventListener('click', function(e){
		filterNestedUrls = !filterNestedUrls;
		GM_setValue('filterNestedUrls', filterNestedUrls);
		if (filterNestedUrls) e.currentTarget.setAttribute('checked', 'checked');
		else e.currentTarget.removeAttribute('checked');
	}, false);
	fs.appendChild(label);

	// Modify links with nested URL on click
	label = document.createElement('label');
	label.innerHTML = '<input type=checkbox> Modify link on click';
	label.className = 'indent';
	if (modifyLinks) label.firstChild.setAttribute('checked', 'checked');
	label.firstChild.addEventListener('click', function(e){
		modifyLinks = !modifyLinks;
		GM_setValue('modifyLinks', modifyLinks);
		if (modifyLinks) e.currentTarget.setAttribute('checked', 'checked');
		else e.currentTarget.removeAttribute('checked');
	}, false);
	fs.appendChild(label);

	// Modify all links with nested URL on load
	label = document.createElement('label');
	label.innerHTML = '<input type=checkbox> Modify <em>all</em> links on page load';
	label.className = 'indent';
	if (modifyAllLinks) label.firstChild.setAttribute('checked', 'checked');
	label.firstChild.addEventListener('click', function(e){
		modifyAllLinks = !modifyAllLinks;
		GM_setValue('modifyAllLinks', modifyAllLinks);
		if (modifyAllLinks) e.currentTarget.setAttribute('checked', 'checked');
		else e.currentTarget.removeAttribute('checked');
	}, false);
	fs.appendChild(label);

	// Modify all links with nested URL now
	var bdiv = document.createElement('div');
	bdiv.innerHTML = '<button type=button accesskey=M><u>M</u>odify all now</button>';
	bdiv.className = 'indent double';
	bdiv.firstChild.addEventListener('click', removeLinkNesting, false);
	fs.appendChild(bdiv);

	fs.appendChild(document.createElement('hr'));

	// Filter links
	label = document.createElement('label');
	label.innerHTML = '<input type=checkbox> Remove links matching expression:';
	if (linkFiltering) label.firstChild.setAttribute('checked', 'checked');
	label.firstChild.addEventListener('click', function(e){
		linkFiltering = !linkFiltering;
		GM_setValue('linkFiltering', linkFiltering);
		if (linkFiltering) {
			e.currentTarget.setAttribute('checked', 'checked');
			filterLinks();
		}
		else e.currentTarget.removeAttribute('checked');
	}, false);
	fs.appendChild(label);

	// Filter expression
	label = document.createElement('label');
	label.innerHTML = '<input type=text value='+ GM_getValue('filterExpression', 'unwanted') +'>';
	label.className = 'indent';
	label.firstChild.addEventListener('change', function(e){
		try {
			filterExpression = new RegExp(e.currentTarget.value, 'i');
			GM_setValue('filterExpression', e.currentTarget.value);
			if (linkFiltering) filterLinks();
		}
		catch (ex) {
			alert('Invalid expression!');
		}
	}, false);
	fs.appendChild(label);

	document.body.insertBefore(form, document.body.firstChild);

	for (i = 0; i < galleryLinks.length; i++) {
		a = document.createElement('a');
		a.href = galleryLinks[i].href;
		setLinkTypeClass(a);
		div.appendChild(a);

		img = document.createElement('img');
		img.src = galleryLinks[i].getElementsByTagName('img')[0].src;
		a.appendChild(img);
		a.setAttribute('onclick', 'return false');
		
		a.addEventListener('click', function(e){
			if (filterNestedUrls) {
				if (modifyLinks) {
					// Needs improvement
					e.currentTarget.href = unescape(e.currentTarget.href)
						.replace(/^(http:\/\/.+)(http:\/\/[^&]+)(.*)$/, '$2');
					setLinkTypeClass(e.currentTarget);
					GM_openInTab(e.currentTarget.href);
				}
				else {
					GM_openInTab(
						unescape(e.currentTarget.href)
						.replace(/^(http:\/\/.+)(http:\/\/[^&]+)(.*)$/, '$2')
					);
				}
			}
			else {
				GM_openInTab(e.currentTarget.href);
			}
		}, false);
		
	}
}

if (
	thumbLinks.length >= reqTumbs ||
	videoLinks.length >= reqVideos ||
	galleryLinks.length >= reqGalleries
) {

	// Scale images
	scaleImages();

	// Modify links with nested URLs
	if (filterNestedUrls && modifyAllLinks) {
		removeLinkNesting();
	}

	// Retry images
 	 		
	div.childNodes[1].focus();
	
}


function getElementsFromSelection(){
   var nodes=null, candidates=[], children, el, parent, rng;

   // Main
   rng=getSelectionRange();
   if(rng) {
     parent=getCommonAncestor(rng);
     if(parent) {
       // adjust from text node to element, if needed
       while(parent.nodeType!=1) parent=parent.parentNode;

       // obtain all candidates from parent (excluded)
       // up to BODY (included)
       if(parent.nodeName.toLowerCase()!="body") {
         el=parent;
         do {
           el=el.parentNode;
           candidates[candidates.length]=el;
         } while(el.nodeName.toLowerCase()!="body");
       }

       // obtain all candidates down to all children
       children=parent.all||parent.getElementsByTagName("*");
       for(var j=0; j<children.length; j++)
         candidates[candidates.length]=children[j];

       // proceed - keep element when range touches it
       nodes=[parent];
       for(var ii=0, r2; ii<candidates.length; ii++) {
         r2=createRangeFromElement(candidates[ii]);
         if(r2 && rangeContact(rng, r2))
           nodes[nodes.length]=candidates[ii];
       }
     }
   }
   return nodes;

   // Helpers
   function getSelectionRange() {
     var rng=null;
     if(window.getSelection) {
       rng=window.getSelection();
       if(rng && rng.rangeCount && rng.getRangeAt) {
         rng=rng.getRangeAt(0);
       }
     } else if(document.selection && document.selection.type=="Text") {
       rng=document.selection.createRange();
     }
     return rng;
   }

   function getCommonAncestor(rng) {
     return rng.parentElement ?
              rng.parentElement() : rng.commonAncestorContainer;
   }

   function rangeContact(r1, r2) {
     var p=null;
     if(r1.compareEndPoints) {
       p={
         method:"compareEndPoints",
         StartToStart:"StartToStart",
         StartToEnd:"StartToEnd",
         EndToEnd:"EndToEnd",
         EndToStart:"EndToStart"
       }
     } else if(r1.compareBoundaryPoints) {
       p={
         method:"compareBoundaryPoints",
         StartToStart:0,
         StartToEnd:1,
         EndToEnd:2,
         EndToStart:3
       }
     }
     return p && !(
           r2[p.method](p.StartToStart, r1)==1 &&
           r2[p.method](p.EndToEnd, r1)==1 &&
           r2[p.method](p.StartToEnd, r1)==1 &&
           r2[p.method](p.EndToStart, r1)==1
           ||
           r2[p.method](p.StartToStart, r1)==-1 &&
           r2[p.method](p.EndToEnd, r1)==-1 &&
           r2[p.method](p.StartToEnd, r1)==-1 &&
           r2[p.method](p.EndToStart, r1)==-1
         );
   }

   function createRangeFromElement(el) {
     var rng=null;
     if(document.body.createTextRange) {
       rng=document.body.createTextRange();
       rng.moveToElementText(el);
     } else if(document.createRange) {
       rng=document.createRange();
       rng.selectNodeContents(el);
     }
     return rng;
   }

};

// Test
function jojo() {

	var buf=[];
	var nodes=getElementsFromSelection();
	if(nodes) {
	 for(var ii=0; ii<nodes.length; ii++) { buf[buf.length]=nodes[ii].href; }
	 
	
	var xa = buf.join("� ");
	GM_setValue('kPages', xa);
	GM_setValue('kCur','0');
	GM_setValue('kHere','...');
	
	var xb = xa.split("� ");
	var xc = new Array(100);

	var xcnt = 0;

	for (var t=0; t < xb.length; t++) {
		if (xb[t].length > 2) {	xc[xcnt] = xb[t];	xcnt++;
		}
	}
	
	GM_setValue('kSource',window.location.href);
	window.location.href = xc[0];
	
	// -------------
		for (i = 0; i < xcnt; i++) {
		a = document.createElement('a');
		a.innerHTML = hc[i] + "<br>";
		div.appendChild(a);

		img = document.createElement('img');
		img.src = videoLinks[i].getElementsByTagName('img')[0].src;
		a.appendChild(img);
	}
	// -----------------------
	
   }
	
}

GM_registerMenuCommand("KONTEXT" , jojo)