Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Jon C

« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS 

DOM Mouse-Over Element Selection and Isolation

DOM ISO.v.0.3.0.7.bookmarklet.js
bookmarklet for selecting and isolating an element on a page.

two sections:
section 1: Mouseover DOM, setup and handle mouse events and show information about element in informational div. Click to select, Any key to cancel.
section 2: Element Isolation with help of XPath. prompt user for XPath expression e.g., //DIV[@id='post-body']. then use XPath to select all elements not(ancestor or descendant or self), then delete those elements. also ignore self-or-descendants of head and title.

tools:
Ruderman's javascript development environment: https://www.squarefree.com/bookmarklets/webdevel.html#jsenv
Mielczarek's js to bookmarklet generator: http://ted.mielczarek.org/code/mozilla/bookmarklet.html

   1  
   2  
   3  (function() {
   4  	//GLOBALS
   5  		//globals for classMausWork
   6  		var gSelectedElement;	//currently only one selection
   7  		var gHoverElement;		//whatever element the mouse is over
   8  		var gHovering=false;	//mouse is over something
   9  		var gObjArrMW=[];	//global array of classMausWork objects.  for removing event listeners when done selecting.
  10  		
  11  		//extended	
  12  		var infoDiv;		//currently just container for InfoDivHover, might add more here
  13  		var infoDivHover;	//container for hoverText text node.
  14  		var hoverText;		//show information about current element that the mouse is over
  15  		//const EXPERIMENTAL_NEW_CODE=true;	//debugging. new features.
  16  	
  17  	
  18  	//START
  19  	SetupDOMSelection();	
  20  
  21  
  22  
  23  		
  24  	//(Section 1) Element Selection
  25  	function SetupDOMSelection()
  26  	{
  27  
  28  		{
  29  			//setup event listeners
  30  			//var pathx="//div | //span | //table | //td | //tr | //ul | //ol | //li | //p";
  31  			var pathx="//div | //span | //table | //th | //td | //tr | //ul | //ol | //li | //p | //iframe";
  32  			var selection=$XPathSelect(pathx);
  33  			for(var element, i=0;element=selection(i);i++)
  34  			{			
  35  				if(element.tagName.match(/^(div|span|table|td|tr|ul|ol|li|p)$/i))	//redundant check.
  36  				{
  37  					var m = new classMausWork(element);
  38  					gObjArrMW.push(m);
  39  					attachMouseEventListeners(m);
  40  				}
  41  			}
  42  			document.body.addEventListener('mousedown',MiscEvent,false);
  43  			document.body.addEventListener('mouseover',MiscEvent,false);
  44  			document.body.addEventListener('mouseout',MiscEvent,false);
  45  			document.addEventListener('keypress',MiscEvent,false);
  46  		}
  47  		{
  48  			//setup informational div to show which element the mouse is over.
  49  			infoDiv=document.createElement('div');
  50  			var s=infoDiv.style;
  51  			s.position='fixed';
  52  			s.top='0';
  53  			s.right='0';
  54  			
  55  			s.display='block';
  56  			s.width='auto';
  57  			s.padding='0px';
  58  
  59  			document.body.appendChild(infoDiv);
  60  			infoDivHover=document.createElement('div');
  61  
  62  			s=infoDivHover.style;
  63  			s.fontWeight='bold';			
  64  			s.padding='3px';
  65  			s.Opacity='0.8';
  66  			s.borderWidth='thin';
  67  			s.borderStyle='solid';
  68  			s.borderColor='white';
  69  			s.backgroundColor='black';
  70  			s.color='white';
  71  			
  72  			infoDiv.appendChild(infoDivHover);			
  73  			hoverText=document.createTextNode('selecting');
  74  			infoDivHover.appendChild(hoverText);
  75  		}
  76  	}
  77  	
  78  	function CleanupDOMSelection()
  79  	{
  80  		for(var m; m=gObjArrMW.pop(); )
  81  		{
  82  			detachMouseEventListeners(m);
  83  		}
  84  		ElementRemove(infoDiv);
  85  		document.body.removeEventListener('mousedown',MiscEvent,false);
  86  		document.body.removeEventListener('mouseover',MiscEvent,false);
  87  		document.body.removeEventListener('mouseout',MiscEvent,false);		
  88  		document.removeEventListener('keypress',MiscEvent,false);
  89  	}	
  90  
  91  	function attachMouseEventListeners(c)
  92  	{
  93  		//c is object of class classMausWork
  94  		c.element.addEventListener("mouseover",c.mouse_over,false);				
  95  		c.element.addEventListener("mouseout",c.mouse_out,false);	
  96  		c.element.addEventListener("mousedown",c.mouse_click,false);		
  97  	}
  98  
  99  	function detachMouseEventListeners(c)
 100  	{
 101  		//c is object of class classMausWork
 102  		c.resetElementStyle();
 103  		c.element.removeEventListener("mouseover",c.mouse_over,false);				
 104  		c.element.removeEventListener("mouseout",c.mouse_out,false);	
 105  		c.element.removeEventListener("mousedown",c.mouse_click,false);		
 106  	}
 107  
 108  	//mouse event  handling class for element, el.
 109  	function classMausWork(element)
 110  	{	
 111  		//store information about the element this object is assigned to handle. element,  original style, etc.	
 112  		this.element=element;
 113  		
 114  		var elementStyle=element.getAttribute('style');
 115  		var target;
 116  		
 117  		this.mouse_over=function(ev)
 118  		{	
 119  			if(gHovering)return;
 120  			var e=element;			
 121  			var s=e.style;
 122  			s.backgroundColor='yellow';
 123  			s.borderWidth='thin';
 124  			s.borderColor='lime';
 125  			s.borderStyle='solid';					
 126  			InfoMSG(ElementInfo(e),'yellow','blue','yellow');
 127  			gHoverElement=e;
 128  			gHovering=true;
 129  			target=ev.target;
 130  			ev.stopPropagation();		
 131  		};
 132  		
 133  		this.mouse_out=function(ev)
 134  		{
 135  			if(!gHovering)return;
 136  			if(gHoverElement!=element ||ev.target!=target)return;
 137  			var e=element;
 138  			e.setAttribute('style',elementStyle);
 139  			InfoMSG('-','white','black','white');	
 140  			gHoverElement=null;
 141  			gHovering=false;
 142  			target=null;
 143  			//ev.stopPropagation();
 144  		};
 145  		
 146  		this.mouse_click=function(ev)
 147  		{
 148  			if(!gHovering)return;
 149  			if(gHoverElement!=element ||ev.target!=target)return;
 150  			var e=element;
 151  			e.setAttribute('style',elementStyle);
 152  			ev.stopPropagation();			
 153  			CleanupDOMSelection();			
 154  			gHoverElement=null;
 155  			gHovering=false;
 156  			target=null;
 157  			
 158  			if(ev.button==0)
 159  			{
 160  				gSelectedElement=e;
 161  				ElementSelected(e);	//finished selecting, cleanup then move to next part (section 2), element isolation.
 162  			}
 163  		};
 164  		
 165  		this.resetElementStyle=function()
 166  		{
 167  			element.setAttribute('style',elementStyle);
 168  		};		
 169  	}
 170  
 171  	function MiscEvent(ev)		//keypress, and mouseover/mouseout/mousedown event on body.  cancel selecting.
 172  	{
 173  		if(ev.type=='mouseout' && !gHovering)
 174  		{
 175  			InfoMSG('-','white','black','white');
 176  		}
 177  		else if(ev.type=='mouseover' && !gHovering)
 178  		{
 179  			InfoMSG('cancel','yellow','red','yellow');
 180  		}
 181  		else //keypress on document or mousedown on body, cancel ops.
 182  		{
 183  			CleanupDOMSelection();
 184  		}
 185  	}
 186  	
 187  	function InfoMSG(text,color,bgcolor,border)
 188  	{
 189  		
 190  		var s=infoDivHover.style;
 191  		if(color)s.color=color;
 192  		if(bgcolor)s.backgroundColor=bgcolor;
 193  		if(border)s.borderColor=border;
 194  		if(text)hoverText.data=text;
 195  	}
 196  	
 197  
 198  
 199  	
 200  	
 201  	//(Section 2) Element Isolation
 202  	function ElementSelected(element)	//finished selecting element.  setup string to prompt user.
 203  	{
 204  		PromptUserXpath(ElementInfo(element));
 205  	}
 206  	
 207  	
 208  	function PromptUserXpath(defaultpath)		//prompt user, isolate element.
 209  	{
 210  		var userpath = prompt("XPath of elements to isolate : ", defaultpath);
 211  		if(userpath && userpath.length>0)
 212  		{
 213  			var addPredicate = "[count(./ancestor-or-self::head)=0][count(./ancestor-or-self::title)=0]";	//exclude head & title elements from selection so they aren't removed
 214  			var addPath = "//script | //form | //object | //embed";	//include these elements in selection for removal
 215  			var pathx=TransformXPath_NoAncestorDescendentSelf(userpath, addPredicate, addPath);		//the xpath selection of all elements to be removed/deleted.
 216  			
 217  			try
 218  			{
 219  				var element;
 220  				var elements=$XPathSelect(pathx);	
 221  				for(var i=0;element=elements(i);i++)
 222  				{			
 223  
 224  					if(!element.nodeName.match(/^(head|title)$/i))	//redundant check.
 225  					{
 226  						ElementRemove(element);
 227  					}
 228  				}
 229  			}
 230  			
 231  			catch(err)
 232  			{
 233  				alert("wtf: "+err);
 234  			}
 235  			
 236  		}
 237  	}
 238  	
 239  		
 240  	
 241  	//support
 242  	function $XPathSelect(p, context) 
 243  	{
 244  	  if (!context) context = document;
 245  	  var i, arr = [], xpr = document.evaluate(p, context, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
 246  	  return function(x) { return xpr.snapshotItem(x); };	//closure.  wooot!  returns function-type array of elements (usually elements, or something else depending on the xpath expression).
 247  	}
 248  	
 249  	function ElementRemove(e)
 250  	{
 251  		if(e)e.parentNode.removeChild(e);
 252  	}
 253  	
 254  	function ElementInfo(element)
 255  	{
 256  		var txt='';
 257  		if(element)
 258  		{
 259  			txt=element.tagName.toLowerCase();		//txt=element.tagName;
 260  			txt=attrib(txt,element,'id');
 261  			txt=attrib(txt,element,'class');	
 262  			txt='//'+txt;
 263  		}
 264  		return txt;
 265  		
 266  		function attrib(t,e,a)
 267  		{			
 268  			if(e.hasAttribute(a))
 269  			{
 270  				t+="[@"+a+"='"+e.getAttribute(a)+"']";
 271  			}
 272  			return t;
 273  		}
 274  		
 275  	}
 276  
 277  
 278  	
 279  	//function to 'invert' the XPath by selecting all elements that are not ancestor and not descendent and not self.
 280  	function TransformXPath_NoAncestorDescendentSelf(u, includePredicates, includePaths)
 281  	{	
 282  		
 283  		//sample input (u):					//div[@class='sortbox']
 284  		//sample output						//*[  not(./descendant-or-self::*=//div[@class='sortbox'])][  not(./ancestor-or-self::*=//div[@class='sortbox'])]
 285  		//sample output with additional conditions:		//*[  not(./descendant-or-self::*=//div[@class='sortbox'])][  not(./ancestor-or-self::*=//div[@class='sortbox'])][count(./ancestor-or-self::head)=0][count(./ancestor-or-self::title)=0]
 286  		
 287  			//obsolete method.  much faster but can only be used for limited types of (simple) xpath expressions -- unlike the current version, which should be able to convert any xpath.
 288  			//input:			table[@id='topbar']
 289  			//output:			//*[not(./descendant-or-self::table[@id='topbar']) and not(./ancestor-or-self::table[@id='topbar'])]
 290  			//output (alternative):	//*[count(./descendant-or-self::table[@id='topbar'])=0 and count(./ancestor-or-self::table[@id='topbar'])=0]
 291  		
 292  		
 293  		var o1=	'./descendant-or-self::*='+gr(u);
 294  		o1=	'not' + gr(o1);
 295  		o1=	nt(o1);	
 296  		var o2= './ancestor-or-self::*='+gr(u);
 297  		o2=	'not' + gr(o2);
 298  		o2=	nt(o2);
 299  
 300  		var o=	'//*'+o1+o2;
 301  		if(includePredicates && includePredicates.length>0)	o += includePredicates;
 302  		if(includePaths && includePaths.length>0) o += ' | ' + includePaths;
 303  		return o;
 304  		
 305  		
 306  		function nt(term){return wrap(term,'[]');}	//node test; predicate - enclose with bracket.
 307  		function gr(term){return wrap(term,'()');}	//group - parenthesize.
 308  		function wrap(term, enclosure){return enclosure.charAt(0)+term+enclosure.charAt(1);}
 309  	}	
 310  	
 311  
 312  
 313  	
 314  })();
 315  
« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS