How to get all attributes or ids by selecting html text with mouse

Viewed 65

let me first explain my issue.
I'm working on a webpage which prints a long text with data retrieved from a db. Each word of the text has is own id (which in turn is a primary key).
I'm wondering if it is possible to select portion of text with mouse and contextually collect all the ids of this selection. At present, I tried with a very simple click function:

var idList = []
$('.tags').click(function() {
   var feature = [this.id, this.text];
   idList.push(feature);
   info.innerHTML = idList;
});

However, it is not very handy becouse of users must click on every word to collect data. At the same time I tried withwindow.getSelection() and the way it works is perfect for my needs, but as far I can understand it returns only a string with all selected words and does not their attributes.

EDIT, Oct 10 2017
This question may already have an answer here:
Get span Id's of selected text using getSelected()

Yes, this is true indeed, but the solution proposed are fairly different. I find very interesting this solution because it is a true selection method and it seems to work pretty well on multi line texts. At the same time the solution proposed here by Taurus is very interesting: as far as I can understand it does not fit well for multline selelctions (example), but anyway it offers the opportunity of selecting non-contiguous portions of text, as well as to deselect a single selection, which are both very important for my small project.

2 Answers

Here is another approach:

$(document).ready(function(){

var word_list = [];
var add_mousemove_event = true;

$(document).on("mousedown", "p > span", function(){

if($(this).hasClass("word_selected")) {
$(this).removeClass("word_selected"); 
remove_word_from_array($(this).attr("id"));
} 
else {
event_callback.call($(this)); 
} 

}).on("mouseup", "p > span", function(){
$(document).off("mousemove", "p > span", event_callback); 
add_mousemove_event = true;
});

function remove_word_from_array(word_id) {
for(let i = 0; i < word_list.length; i++) {
if(word_list[i]["word_id"] === word_id) {
word_list.splice(i, 1);
break;
}
} 
show_selected_word_ids();
}


function event_callback() {
exec($(this)); 
}
 
 
function exec(elem) {
if(add_mousemove_event === true) {
$(document).on("mousemove", "p > span", event_callback); 
add_mousemove_event = false;
}

select_words.call(elem); 
} 
 
function select_words() {
if(!$(this).hasClass("word_selected")) { 
word_list.push({
"word_id": $(this).attr("id"),
"word_text": $(this).text() 
});

$(this).addClass("word_selected"); 
show_selected_word_ids();
}
}

function show_selected_word_ids() {
var word_list_container = $("#word_list_container");
word_list_container.html("");
for(let i = 0; i < word_list.length; i++) {
word_list_container.append(word_list[i]["word_id"] + (i !== word_list.length - 1 ? "," : ""));
} 
}
 
});
.word_selected {
background-color: lightsteelblue;
border-bottom: 2px solid indigo;
}

p {
user-select: none;
cursor: default;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
<span id="1">My</span>
<span id="2">Name</span>
<span id="3">Is</span>
<span id="4">Jon</span>
<span id="5">Snow</span>
<span id="6">And</span>
<span id="7">I</span>
<span id="8">Know</span>
<span id="9">Nothing</span>
</p>

<p id="word_list_container">
</p>

Obviously, this won't work on mobile because the events are browser-based, but you get the idea, you just have to change the events to touch-based ones and everything should work just fine. Also, you can embellish this snippet as much as you want, I recommend adding a "clear all" button as well.

In the meantime, feel free to ask any questions you might have on the snippet I provided. I would have commented it but I am going to sleep right now, I will possibly comment the code tomorrow, it should be fairly easy to read though.

This is an approach:

1) Create an array with all words and their IDs, as objects.

var arr = [{"id":1111, "text":"Hello"},
           {"id":2222, "text":"World"}]

2) With window.getSelection().toString() you should have exactly the string selected by the user. Adding .split(' ') you will have an array with the words. There could be a problem with other symbols (?!@ etc) but you could easily fix it (for example, you may want to use regex or filtering, in order to have a 'clean' array of words).

var words = window.getSelection().toString().split(' ')

3) Once you have the array of selected words, loop through each one and push each id to your idList array.

for (var i=0;i<words.length;i++) {
    for (var j=0;j<arr.length;j++) {
        if words[i] == arr[j].text {
            idList.push(arr[j]);
            break;
        }
    }
}
Related