Got selected text, but can I get surrounding context?

D

Dekortage

Hi all...

I am able to grab the text that a user has selected on a web page,
using this code:

function moreInfo() {
if (!isIE) {
var t = window.getSelection();
// act on variable "t";

} else if (document.selection && document.selection.createRange) {
var t = document.selection.createRange();
if (document.selection.type == 'Text' && t.text>'') {
document.selection.empty();
// act on variable "t";

}
}
}

(the boolean "isIE" is established earlier in the code)

This works. However, I'm wondering how to get the words *around* the
selected word. Take these sentences for example: "If you need to
framglubble the zartbox, then you should buy the red widget.
Otherwise you can buy the blue widget and save some money."

My code will tell me if the person has selected the word "widget".
But I'd like to know if the selection is after "red" or "blue". Is
this possible? I've been scouring the Internet for some advice, and
I'm having trouble finding an answer.

Many thanks in advance for your time.
 
V

VK

My code will tell me if the person has selected the word "widget".
But I'd like to know if the selection is after "red" or "blue". Is
this possible?

Not in any straightforward way AFAIK.

You may extend/shift range left or right to see what words will be
added. In any case it presumes some fixed content you know in advance
so able to recognize by fragments. In this case wouldn't it be much
more easy to mark all needed segments in advance? Just a suggestion:

<p>If you need to framglubble the zartbox, then you should buy the
<span onclick="f(this)">red widget</span>.
Otherwise you can buy the <span click="f(this)">blue widget</span> and
save some money.</p>
 
D

Dekortage

You may extend/shift range left or right to see what words will be
added. In any case it presumes some fixed content you know in advance
so able to recognize by fragments. In this case wouldn't it be much
more easy to mark all needed segments in advance? Just a suggestion:

<p>If you need to framglubble the zartbox, then you should buy the
<span onclick="f(this)">red widget</span>.
Otherwise you can buy the <span click="f(this)">blue widget</span> and
save some money.</p>

Thanks for your response, VK.

I hear ya. I have specific reasons for doing it the other way. I'm
trying to develop a definition system so someone can select text on a
page and hit button to get a definition. Using the example above,
they could select "widget" or "framglubble" or "money". But there are
many words which have different meanings depending on context, so the
definition system could be more accurate/useful if I could
intelligently scan context.

I'm intrigued about shifting the range to the left. I expect to be
working with fairly fixed content (or at least indexable content that
would be intelligently tied to the definition system). How would I do
that?
 
D

Dekortage

Okay. I have a really rough, unoptimized version of what I want. The
IE part is pretty simple, since it can move the selection boundary
range around. The Mozilla part is a bit more of a hack: I get the
full text of the node that the selection resides in, then based on the
selection offset within the node, I chop up the text around it to
determine the words just before and after the selected word. It
doesn't work quite perfectly, but it's close. It doesn't work with
Safari but I've tested it succesfully with Firefox (Mac) and IE 6
(Windows). (Safari has some weird text range issues...?!?)

Below is the code for an entire HTML page. Hopefully the word wrap
won't kill it. I freely admit it is an ugly, unoptimized hack thrown
together as a proof of concept, so you're welcome to clean it up, fix
bugs, add features, etc.




<html>
<head>
<title>Framglubble the Zartbox: getting selection context via
JavaScript</title>
<script language="javascript">

// Original author: Dekortage @ a server called Gmail.com
// You're free to copy this but leave the "Original author" line
intact.
//
// This deliberately returns a "null" value if it determines that the
previous
// or next word is separated from the selected word by a comma or
period.

// determine browsers
var isIE = document.all;
var isN6 = document.getElementById && !document.all;
var isN4 = document.layers;
var detect = navigator.userAgent.toLowerCase();
var isSafari = ( detect.indexOf("safari") > 0 );

function trim(x) { return x.replace(/^\s*|\s*$/g,''); }

function moreInfo() {
if (!isIE) {
var t = window.getSelection(); // selected text
tx = t+"";
preWord = null;
postWord = null;

if (!isSafari) { // Safari does not work with this

origNode = t.anchorNode;
orig = origNode.textContent + "";

// get previous word
preTxt = orig.slice(0,t.anchorOffset);
preArray = preTxt.split(" ");
preCount = preArray.length;
while ((preWord == null) && (preCount >= 0)) {
preCount -= 1;
if ((preArray[preCount] != null) && (preArray[preCount] != "") &&
(preArray[preCount] != " ")) {
preWord = preArray[preCount];
if ((preWord.charAt(preWord.length-1) == ",")) preWord = null;
}
}

// get next word
postTxt = orig.slice((t.anchorOffset + tx.length + 1));
postArray = postTxt.split(" ");
if ((postArray[0] != ".") && (postArray[0] != ",") &&
(postArray[0] != "--") && (postArray[0] != "") &&
(postArray[0] != " ")) { // if not end of sentence
postWord = postArray[0];
}

}

showWords(tx,preWord,postWord);

} else if (document.selection && document.selection.createRange) {
var t = document.selection.createRange(); // selected text
if ((document.selection.type == 'Text') && (t.text > '')) {

tx = trim(t.text);

t.moveStart("word",-1); // not sure why t.move() alone wouldn't work
t.moveEnd("word",-1);
preWord = trim(t.text);
if ((preWord == ",") || (preWord == ".")) {
preWord = null;
}

t.moveEnd("word",2);
t.moveStart("word",2);
postWord = trim(t.text);
if ((postWord == ",") || (postWord == ".")) {
postWord = null;
}

// need to fix this to work with hyphenated words

document.selection.empty();
showWords(tx,preWord,postWord);
}
}
}

function showWords(t,a,z) { window.alert("Sequence: "+a+","+t
+","+z); }

if (isIE) document.ondblclick=moreInfo;

</script>
</head>
<body ondblclick="if (!isIE) moreInfo()" style="font-size: 24px;
margin: 24px;">
<p>If you need to framglubble the zartbox, then you should buy the red
widget. Otherwise you can buy the blue widget and save some money.</p>
<p>(double-click on a word to see its context)</p>
</body>
</html>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top