New York Times-Style Text Selection Widget Using MooTools or jQuery
Aaron Newton made a great request to me last week: why not make my MooTools Documentation Bookmarklet function more like the New York Time's text selection widget. NYT's text selection widget listens for text selection and presents the user with a "search" icon they may click on to learn more about that term. I've tried to answer that challenge -- not in bookmarklet form but in website widget form.
The Sample HTML
<div id="content-area"> .htaccess AJAX Apache / Server APIs Blog Bookmarking / Social Books Browsers CSS / Design Google Guest Blogger Hosting / Domain JavaScript jQuery link() Microsoft MooTools MySQL Optimization PHP Poll rand() Security Shell Theory / Ideas Usability / Accessibility XML / XHTML This blog is targeted toward all levels of web designers and developers. All web topics are discussed, including CSS, JavaScript (MooTools and jQuery), PHP, and more. </div>
The above code is next to meaningless per the widget -- I simply want to illustrate the area I'd like it to work in has an ID of content-area.
The MooTools JavaScript
window.addEvent('domready',function(){ (function($) { //gets the selected text var getSelection = function() { return $try( function() { return window.getSelection(); }, function() { return document.getSelection(); }, function() { var selection = document.selection && document.selection.createRange(); if(selection.text) { return selection.text; } return false; } ) || false; }; //vars var url = 'https://davidwalsh.name/?s={term}', selectionImage; //event to listen $('content-area').addEvent('mouseup',function(e) { var selection = getSelection(); if(selection && (selection = new String(selection).replace(/^\s+|\s+$/g,''))) { //ajax here { https://davidwalsh.name/text-selection-ajax } if(!selectionImage) { selectionImage = new Element('a',{ href: url, opacity:0, id: 'selection-image', title: 'Click here to learn more about this term', target: '_blank' }).inject(document.body,'top'); } //handle the every-time event //alert(selection); selectionImage.set('href',url.replace('{term}',encodeURI(selection))).setStyles({ top: e.page.y - 30, //offsets left: e.page.x - 13 //offsets }).tween('opacity',0); } }); $(document.body).addEvent('mousedown',function() { //hider if(selectionImage) { selectionImage.tween('opacity',1); } }); })(document.id); });
During the mouseup event within the selected container (content-area), we determine if any text has been highlighted. If so, we:
- Insert the A element if it has not yet been injected into the body.
- Change the A element's URL to accommodate for the new search term.
- Position the element to at an offset position above where the mouse goes up.
During every mousedown event we hide the A element.
The jQuery JavaScript
/* attempt to find a text selection */ function getSelected() { if(window.getSelection) { return window.getSelection(); } else if(document.getSelection) { return document.getSelection(); } else { var selection = document.selection && document.selection.createRange(); if(selection.text) { return selection.text; } return false; } return false; } /* create sniffer */ $(document).ready(function() { var url = 'https://davidwalsh.name/?s={term}', selectionImage; $('#content-area').mouseup(function(e) { var selection = getSelected(); if(selection && (selection = new String(selection).replace(/^\s+|\s+$/g,''))) { //ajax here { https://davidwalsh.name/text-selection-ajax } if(!selectionImage) { selectionImage = $('<a>').attr({ href: url, title: 'Click here to learn more about this term', target: '_blank', id: 'selection-image' }).hide(); $(document.body).append(selectionImage); } selectionImage.attr('href',url.replace('{term}',encodeURI(selection))).css({ top: e.pageY - 30, //offsets left: e.pageX - 13 //offsets }).fadeIn(); } }); $(document.body).mousedown(function() { if(selectionImage) { selectionImage.fadeOut(); } }); });
Follows the same principal as above.
Ideas & Enhancements
- Depending on your philosophy, you may want to implement a minimum character check as well:
if(selection && (selection = new String(selection).replace(/^\s+|\s+$/g,'')) && selection.length > 4) { //5 char min
- You may want to also fidget with adding/modifying text selection with keyboard keys as well. I've chosen to pass on that.
- Saving the selection content via AJAX for analytical reasons may not be a bad idea either.
Have any other ideas for improvement? Would you have any use for this on your website(s)?
This is totally cool, and I KNOW this would be a great feature to add to a hyperlocal blog that I work for.
Nice use! Could be a little neater on the MooTools side though…
Nice man. very cool and you got the jquery version which makes it so much better for me. I might have to try this on a project. thanks again for all the work you put into your blog. Its much appreciated.
Very nice thanks!
I am with a PHP web development company http://www.rightwaysolution.com
Very nice article thanks for explaining this. i am bookmarking this and will surely return for more knowledge:)
Pretty sweet, always enjoy your blog.
nice article dev….:)
Is the plugin you’re using on this website?
Yep — it was really easy to implement too!
The mootools demo isn’t working for me (the jqery one does).
@Graeme Coultrip: Updated!
@David Walsh: It was simple opacity mistake.
Cool. I think this could be very useful.
Hi,
How can I change getSelected function to return the start and end position index?
hi devid.
i am following Your blog for Years.
first of all , i appreciate you for your knowledge sharing ;)
i am using Joomla 1.5 in my New Project and as you may know, Joomla Is using Mootools 1.11 in its core.
So by know , i want to use this Useful plug-in and it does not work with this mootools version.
how do you see this problem? any solution?
i had updated the Joomla Mootools version, but some other part of the website drops :D
best Regards,
M.Rashidi
That’s really wow I say because this would be a source of getting inspiration and that is all what is required to start the things, thank you.
How can I use colorbox to open the search results page instead of a new window? I hve tried onclick attribute for $(‘‘) but it doesnt work.
The mootools demo isn’t working for me, too. It bothers me a lot. Who can help?