DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Migrating from React Router v5 to v6: A Comprehensive Guide
  • Playwright: Filter Visible Elements With locator.filter({ visible: true })
  • React Callback Refs: What They Are and How to Use Them
  • Process Mining Key Elements

Trending

  • SaaS in an Enterprise - An Implementation Roadmap
  • Go 1.24+ Native FIPS Support for Easier Compliance
  • Intro to RAG: Foundations of Retrieval Augmented Generation, Part 2
  • Implementing API Design First in .NET for Efficient Development, Testing, and CI/CD
  1. DZone
  2. Data Engineering
  3. Databases
  4. DOM Mouse-Over Element Selection And Isolation

DOM Mouse-Over Element Selection And Isolation

By 
Jon C user avatar
Jon C
·
Sep. 09, 07 · Code Snippet
Likes (0)
Comment
Save
Tweet
Share
2.1K Views

Join the DZone community and get the full member experience.

Join For Free
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



(function() {
	//GLOBALS
		//globals for classMausWork
		var gSelectedElement;	//currently only one selection
		var gHoverElement;		//whatever element the mouse is over
		var gHovering=false;	//mouse is over something
		var gObjArrMW=[];	//global array of classMausWork objects.  for removing event listeners when done selecting.
		
		//extended	
		var infoDiv;		//currently just container for InfoDivHover, might add more here
		var infoDivHover;	//container for hoverText text node.
		var hoverText;		//show information about current element that the mouse is over
		//const EXPERIMENTAL_NEW_CODE=true;	//debugging. new features.
	
	
	//START
	SetupDOMSelection();	



		
	//(Section 1) Element Selection
	function SetupDOMSelection()
	{

		{
			//setup event listeners
			//var pathx="//div | //span | //table | //td | //tr | //ul | //ol | //li | //p";
			var pathx="//div | //span | //table | //th | //td | //tr | //ul | //ol | //li | //p | //iframe";
			var selection=$XPathSelect(pathx);
			for(var element, i=0;element=selection(i);i++)
			{			
				if(element.tagName.match(/^(div|span|table|td|tr|ul|ol|li|p)$/i))	//redundant check.
				{
					var m = new classMausWork(element);
					gObjArrMW.push(m);
					attachMouseEventListeners(m);
				}
			}
			document.body.addEventListener('mousedown',MiscEvent,false);
			document.body.addEventListener('mouseover',MiscEvent,false);
			document.body.addEventListener('mouseout',MiscEvent,false);
			document.addEventListener('keypress',MiscEvent,false);
		}
		{
			//setup informational div to show which element the mouse is over.
			infoDiv=document.createElement('div');
			var s=infoDiv.style;
			s.position='fixed';
			s.top='0';
			s.right='0';
			
			s.display='block';
			s.width='auto';
			s.padding='0px';

			document.body.appendChild(infoDiv);
			infoDivHover=document.createElement('div');

			s=infoDivHover.style;
			s.fontWeight='bold';			
			s.padding='3px';
			s.Opacity='0.8';
			s.borderWidth='thin';
			s.borderStyle='solid';
			s.borderColor='white';
			s.backgroundColor='black';
			s.color='white';
			
			infoDiv.appendChild(infoDivHover);			
			hoverText=document.createTextNode('selecting');
			infoDivHover.appendChild(hoverText);
		}
	}
	
	function CleanupDOMSelection()
	{
		for(var m; m=gObjArrMW.pop(); )
		{
			detachMouseEventListeners(m);
		}
		ElementRemove(infoDiv);
		document.body.removeEventListener('mousedown',MiscEvent,false);
		document.body.removeEventListener('mouseover',MiscEvent,false);
		document.body.removeEventListener('mouseout',MiscEvent,false);		
		document.removeEventListener('keypress',MiscEvent,false);
	}	

	function attachMouseEventListeners(c)
	{
		//c is object of class classMausWork
		c.element.addEventListener("mouseover",c.mouse_over,false);				
		c.element.addEventListener("mouseout",c.mouse_out,false);	
		c.element.addEventListener("mousedown",c.mouse_click,false);		
	}

	function detachMouseEventListeners(c)
	{
		//c is object of class classMausWork
		c.resetElementStyle();
		c.element.removeEventListener("mouseover",c.mouse_over,false);				
		c.element.removeEventListener("mouseout",c.mouse_out,false);	
		c.element.removeEventListener("mousedown",c.mouse_click,false);		
	}

	//mouse event  handling class for element, el.
	function classMausWork(element)
	{	
		//store information about the element this object is assigned to handle. element,  original style, etc.	
		this.element=element;
		
		var elementStyle=element.getAttribute('style');
		var target;
		
		this.mouse_over=function(ev)
		{	
			if(gHovering)return;
			var e=element;			
			var s=e.style;
			s.backgroundColor='yellow';
			s.borderWidth='thin';
			s.borderColor='lime';
			s.borderStyle='solid';					
			InfoMSG(ElementInfo(e),'yellow','blue','yellow');
			gHoverElement=e;
			gHovering=true;
			target=ev.target;
			ev.stopPropagation();		
		};
		
		this.mouse_out=function(ev)
		{
			if(!gHovering)return;
			if(gHoverElement!=element ||ev.target!=target)return;
			var e=element;
			e.setAttribute('style',elementStyle);
			InfoMSG('-','white','black','white');	
			gHoverElement=null;
			gHovering=false;
			target=null;
			//ev.stopPropagation();
		};
		
		this.mouse_click=function(ev)
		{
			if(!gHovering)return;
			if(gHoverElement!=element ||ev.target!=target)return;
			var e=element;
			e.setAttribute('style',elementStyle);
			ev.stopPropagation();			
			CleanupDOMSelection();			
			gHoverElement=null;
			gHovering=false;
			target=null;
			
			if(ev.button==0)
			{
				gSelectedElement=e;
				ElementSelected(e);	//finished selecting, cleanup then move to next part (section 2), element isolation.
			}
		};
		
		this.resetElementStyle=function()
		{
			element.setAttribute('style',elementStyle);
		};		
	}

	function MiscEvent(ev)		//keypress, and mouseover/mouseout/mousedown event on body.  cancel selecting.
	{
		if(ev.type=='mouseout' && !gHovering)
		{
			InfoMSG('-','white','black','white');
		}
		else if(ev.type=='mouseover' && !gHovering)
		{
			InfoMSG('cancel','yellow','red','yellow');
		}
		else //keypress on document or mousedown on body, cancel ops.
		{
			CleanupDOMSelection();
		}
	}
	
	function InfoMSG(text,color,bgcolor,border)
	{
		
		var s=infoDivHover.style;
		if(color)s.color=color;
		if(bgcolor)s.backgroundColor=bgcolor;
		if(border)s.borderColor=border;
		if(text)hoverText.data=text;
	}
	


	
	
	//(Section 2) Element Isolation
	function ElementSelected(element)	//finished selecting element.  setup string to prompt user.
	{
		PromptUserXpath(ElementInfo(element));
	}
	
	
	function PromptUserXpath(defaultpath)		//prompt user, isolate element.
	{
		var userpath = prompt("XPath of elements to isolate : ", defaultpath);
		if(userpath && userpath.length>0)
		{
			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
			var addPath = "//script | //form | //object | //embed";	//include these elements in selection for removal
			var pathx=TransformXPath_NoAncestorDescendentSelf(userpath, addPredicate, addPath);		//the xpath selection of all elements to be removed/deleted.
			
			try
			{
				var element;
				var elements=$XPathSelect(pathx);	
				for(var i=0;element=elements(i);i++)
				{			

					if(!element.nodeName.match(/^(head|title)$/i))	//redundant check.
					{
						ElementRemove(element);
					}
				}
			}
			
			catch(err)
			{
				alert("wtf: "+err);
			}
			
		}
	}
	
		
	
	//support
	function $XPathSelect(p, context) 
	{
	  if (!context) context = document;
	  var i, arr = [], xpr = document.evaluate(p, context, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	  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).
	}
	
	function ElementRemove(e)
	{
		if(e)e.parentNode.removeChild(e);
	}
	
	function ElementInfo(element)
	{
		var txt='';
		if(element)
		{
			txt=element.tagName.toLowerCase();		//txt=element.tagName;
			txt=attrib(txt,element,'id');
			txt=attrib(txt,element,'class');	
			txt='//'+txt;
		}
		return txt;
		
		function attrib(t,e,a)
		{			
			if(e.hasAttribute(a))
			{
				t+="[@"+a+"='"+e.getAttribute(a)+"']";
			}
			return t;
		}
		
	}


	
	//function to 'invert' the XPath by selecting all elements that are not ancestor and not descendent and not self.
	function TransformXPath_NoAncestorDescendentSelf(u, includePredicates, includePaths)
	{	
		
		//sample input (u):					//div[@class='sortbox']
		//sample output						//*[  not(./descendant-or-self::*=//div[@class='sortbox'])][  not(./ancestor-or-self::*=//div[@class='sortbox'])]
		//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]
		
			//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.
			//input:			table[@id='topbar']
			//output:			//*[not(./descendant-or-self::table[@id='topbar']) and not(./ancestor-or-self::table[@id='topbar'])]
			//output (alternative):	//*[count(./descendant-or-self::table[@id='topbar'])=0 and count(./ancestor-or-self::table[@id='topbar'])=0]
		
		
		var o1=	'./descendant-or-self::*='+gr(u);
		o1=	'not' + gr(o1);
		o1=	nt(o1);	
		var o2= './ancestor-or-self::*='+gr(u);
		o2=	'not' + gr(o2);
		o2=	nt(o2);

		var o=	'//*'+o1+o2;
		if(includePredicates && includePredicates.length>0)	o += includePredicates;
		if(includePaths && includePaths.length>0) o += ' | ' + includePaths;
		return o;
		
		
		function nt(term){return wrap(term,'[]');}	//node test; predicate - enclose with bracket.
		function gr(term){return wrap(term,'()');}	//group - parenthesize.
		function wrap(term, enclosure){return enclosure.charAt(0)+term+enclosure.charAt(1);}
	}	
	


	
})();

Isolation (database systems) Element

Opinions expressed by DZone contributors are their own.

Related

  • Migrating from React Router v5 to v6: A Comprehensive Guide
  • Playwright: Filter Visible Elements With locator.filter({ visible: true })
  • React Callback Refs: What They Are and How to Use Them
  • Process Mining Key Elements

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!