// ==UserScript==
// @name		-	Snap Images
// @author		-	Ayush
// @version		-	-2
// @description	-	Select the images by holding -Alt- key and drawing a box around images then leave the mousebutton to show all the selected images in new tab.
//						Hold -Ctrl- to select image-links instead of images
//						Hold -Shift- key to select all images/image-links in rectangle (not just the big ones)
//					After selecting/opening the images, use the links panel to save/bookmark/open the images..
// ==/UserScript==

(function(opera,getSelection,addEventListener,selNode,getBoundingClientRect,window){var 
//..//
	showStatus=1 , // show # of selected links in status bar
	selAllLinks=0, // select all links
	dupIMGs=0, // select duplicate images/links
	rectBorder='2px dashed #1E90FF', rectBG='transparent', linksOutline='1px solid #ef0006'
//..//
	;var mdown,outRect,elms,mdElm,updateTimeout,visElms,x,y,x2,y2,ctKey,shKey,scrTm,visMinY=-1,visMaxY=-1,docMaxX,docMaxY,winFocused=1,
	lastTp,
	events={
		mousedown:function(ev){
			if(ev.dynamicEvent)return;
			sl.clear(0,0,1);
			if(ev.which!==1 || !ev.altKey || selNode.call(ev.target,'ancestor-or-self::node()[contains(",input,textarea,img,button,select,a,",concat(",",local-name(),",")) and (local-name()!="a" or @href)]'))return;
			x=x2=ev.pageX;y=y2=ev.pageY;
			//docMaxX=getComputedStyle(document.documentElement).width;docMaxY=getComputedStyle(document.documentElement).height;
			mdElm=[ev.srcElement];mdElm.push(mdElm[0].offsetLeft,mdElm[0].offsetTop,mdElm[0].offsetWidth,mdElm[0].offsetHeight);
			var cSty,pos;if((mdElm[0].tagName!='BODY' && mdElm[0].tagName!='HTML') && ((cSty=getComputedStyle(mdElm[0],null)).overflow!='visible' && cSty.overflow!='hidden') && ((((pos=sl.getPos(mdElm[0])).x+parseInt(cSty.borderLeftWidth,10)+mdElm[0].clientWidth)<ev.pageX && (pos.x2-parseInt(cSty.borderRightWidth,10))>ev.pageX) || ((pos.y+parseInt(cSty.borderTopWidth,10)+mdElm[0].clientHeight)<ev.pageY && (pos.y2-parseInt(cSty.borderBottomWidth,10))>ev.pageY)))return;
			mdown=1;
		},
		mousemove:function(ev){
			if(!mdown)return;
			x2=ev.pageX;
			y2=ev.pageY;
			
			ctKey=ev.ctrlKey;shKey=ev.shiftKey;
			
			var rect=sl.getRealXY([x,x2],[y,y2]);
			if(!outRect){
				if( winFocused && mdElm && mdElm[1]==mdElm[0].offsetLeft && mdElm[2]==mdElm[0].offsetTop && mdElm[3]==mdElm[0].offsetWidth && mdElm[4]==mdElm[0].offsetHeight)
					sl.createRect();
				else
					return (window.status='[ERROR] Resetting rectangle.. ')&&(sl.clear(0,0,1));
			};

			if(getSelection().rangeCount)getSelection().removeAllRanges();
			
			sl.setRectSize(rect,docMaxX,docMaxY)
			
			if(!updateTimeout)
			 updateTimeout=setTimeout(function(){updateTimeout=null;sl.selLinks()},66);
		},
		mouseup:function(ev){
			if(ev.which===1 && mdown){
			  var linksOpened;
			  ev.preventDefault();//ev.stopPropagation();
			  sl.selLinks();
			  
			  if(elms && elms.length){
				var docFrag = document.createDocumentFragment(),a,img,
					iX=0,elm;
				if(elms.ELMS_TYPE=='LINK')
					while(elm=elms[iX++]){
						elm.style.outline="none";
						img=(a=docFrag.appendChild(document.createElement('a'))).appendChild(document.createElement('img'));
						img.src=a.href=elm.href;
						img.addEventListener('error',function(){a.removeNode(true)},false);
					}
				else
					while(elm=elms[iX++]){
						elm.style.outline='none';
						(a=docFrag.appendChild(document.createElement('a'))).appendChild(elm.cloneNode(false));
						a.href=elm.src;
					}
				var win = window.open();
				if(win)win.document.body.appendChild(docFrag);else alert("window.open() failed");
			  }
			  sl.clear(0,0,linksOpened);
			}
		},
		keydown:function(ev){
			if(!mdown)return
			var kc=ev.keyCode;
			if(kc==16)
				shKey=1;
			else if(kc==17){
				ctKey=1;
				sl.clear(1)
				sl.createRect(null,null,null,0,1);
			}else{
			  if(kc==27)
				sl.clear();
				//ev.preventDefault();
			  return
			};
			sl.selLinks();
		},
		keyup:function(ev){
			if(!mdown)return;
			var kc=ev.keyCode;
			if(kc==16)
				shKey=0;
			else if(kc==17){
				ctKey=0;
				sl.clear(1)
				sl.createRect(null,null,null,0,1);
			}else return;
			sl.selLinks();
		},
		scroll:function(){
			if(mdown && outRect){
			  if(scrTm)clearTimeout(scrTm);
			  scrTm=setTimeout(function(){
				if(mdown)sl.createRect(lastTp,0,0,visElms,1);
				sl.selLinks()
			  },66+6);
			}
		},
		blur:function(){
			winFocused=0;
			//if(mdown)sl.clear(0,0,1)
		},
		focus:function(){
			winFocused=1;
			//if(mdown)sl.clear(0,0,1)
		}
	},
	sl={
		clear:function(noOutRect,noElms,noStat,noMDown){
			if(!noOutRect){
				if(outRect){
					outRect.parentNode.removeChild(outRect);
					outRect=null;
				}
				if(!noMDown)mdown=ctKey=shKey=mdElm=0;
			};
			if(!noElms && elms){
				for(var iX=0;iX<elms.length;iX++)
					elms[iX].style.outline="none";
				elms=null;
			}
			if(!noStat)status='';
		},
		createRect:function(loopElms,minY,maxY,addToElms,noNewRect){
			if(!noNewRect){
			  outRect=document.createElementNS("http://www.w3.org/1999/xhtml","outRect");
			  outRect.style='border:'+rectBorder+';background:'+rectBG+';opacity:1;margin:0;padding:0;position:absolute;z-index:999;left:'+x+'px;top:'+y+'px;';
			  (document.documentElement||document).appendChild(outRect);
			};
			
			minY=minY||pageYOffset;
			maxY=maxY||pageYOffset+(document.documentElement.clientHeight);
			var elms=loopElms||(ctKey?document.selectNodes('//a[descendant::img[@src]]'):document.images)
			if(visMinY==-1 || visMaxY==-1 || elms!=lastTp){
				visMinY=minY
				visMaxY=maxY
				visElms=null;
			}else if(minY<visMinY){
				maxY=visMinY;
				visMinY=minY;
			}else if(maxY>visMaxY){
				minY=visMaxY
				visMaxY=maxY;
			}else return;
			
			var i=0,elm;
				visElms=addToElms||visElms||{sizes:[],elms:[],pos:[]};
			var eSty,elFS,pos;
			var iX=0,cLnk,vEls=visElms.elms;
			if(ctKey){
				var imgLink=new RegExp('\\.(?:png|gif|jpe?g|bmp)(?:\\?|$)','i');
				visElms.ELMS_TYPE='LINK';
			}else
				visElms.ELMS_TYPE='IMGS';
			wOLoop:while(elm=elms[i++]){
				if(ctKey && !imgLink.test(elm.href))continue;
				if(addToElms)while(cLnk=vEls[iX++]){if(cLnk==elm)continue wOLoop};
				eSty=getComputedStyle(elm,null);
				if(eSty.visibility=="hidden")continue;
				pos=sl.getPos(elm);
				if( pos.y2<minY || pos.y>maxY || pos.y2==pos.y || pos.x2==pos.x)
					continue;
				if((eSty=eSty.fontSize).indexOf('px')!=-1)elFS=parseFloat(eSty);else elFS=0;
				visElms.sizes.push(elFS);visElms.elms.push(elm);visElms.pos.push(pos);
			};
			lastTp=elms;
		},
		setRectSize:function(rect,maxX,maxY,oRect){
			var tmpsty=(oRect||outRect).style;
			if(!maxX || rect.x[1]<maxX){
			  tmpsty.setProperty('left',rect.x[0]+"px",'important');
			  tmpsty.setProperty('width',(rect.x[1]-rect.x[0])+"px",'important');
			}
			if(!maxY || rect.y[1]<maxY){
			  tmpsty.setProperty('top',rect.y[0]+"px",'important');
			  tmpsty.setProperty('height',(rect.y[1]-rect.y[0])+"px",'important');
			}
		},
		getPos:function(el,arr){
			var pos;
			if(getBoundingClientRect){
				pos = getBoundingClientRect.apply(el);
				pos = {x:pos.left,y:pos.top,x2:pos.right,y2:pos.bottom}
			}else{
				pos = {x:0,y:0,x2:el.offsetWidth,y2:el.offsetHeight};
				while (el) {
					pos.x += el.offsetLeft;	pos.y += el.offsetTop;el = el.offsetParent;
				}
				pos.x2+=pos.x;pos.y2+=pos.y;
			}
			return (arr?[pos.x,pos.x2,pos.y,pos.y2]:pos);
		},
		getRealXY:function(x,y){
			return {x:(x[0]<x[1]?x:x.reverse()),y:(y[0]<y[1]?y:y.reverse())};
		},
		selLinks:function(allLinks){
			if(!outRect)return;
			var allLinks=allLinks || (selAllLinks?!shKey:shKey),uniqAttr=dupIMGs?undefined:(visElms.ELMS_TYPE=='LINK'?'href':'src'),dURLs=uniqAttr?{}:undefined,tempAttr;
			var rect=sl.getRealXY([x,x2],[y,y2]),X=rect.x[0],X2=rect.x[1],Y=rect.y[0],Y2=rect.y[1],
			iX=-1,Elms=visElms.elms,Elm,Poss=visElms.pos,Sizes=visElms.sizes,
			ePos,eX,eWid,eY,eHeight,sz,elNotInRect,largSz=0;elms=[];
			while(Elm=Elms[++iX]){
				if(uniqAttr)tempAttr=Elm.attributes[uniqAttr].value;
				ePos=Poss[iX];eX=ePos.x;eX2=ePos.x2;eY=ePos.y;eY2=ePos.y2;sz=Sizes[iX];
				elNotInRect=(eY > Y2 || eY2 < Y || eX2 < X ||eX > X2);
				if(elNotInRect || (tempAttr && (tempAttr in dURLs))){
					Elm.style.outline="";
				}else{
					if(!allLinks){
					  if(largSz>sz){
						Elm.style.outline="";
						continue
					  }else if(largSz<sz){
						sl.clear(1);elms=[];largSz=sz
					  };
					};
					Elm.style.outline=linksOutline;
					elms.push(Elm);
					if(tempAttr)dURLs[tempAttr]=1;
				}
			};
			elms.ELMS_TYPE=visElms.ELMS_TYPE;
			if(showStatus)window.status='Elements in selection: '+ elms.length;
		}
	};
	if(opera && opera.addEventListener){
		opera.addEventListener('BeforeEvent.mousedown',function(mdev){ return function(ujsev){ if(ujsev.event.dynamicEvent){ ujsev.preventDefault();return } mdev(ujsev.event) } }(events.mousedown),false);delete events.mousedown;
		opera.addEventListener('BeforeEvent.mouseup',function(mdev){ return function(ujsev){ mdev(ujsev.event) } }(events.mouseup),false);delete events.mouseup;
	};
	for(var i in events)addEventListener(i,events[i],true);
})(opera,getSelection,addEventListener,Node.prototype.selectSingleNode,null/*Element.prototype.getBoundingClientRect*/,window)