2015-05-04 2 views
7

Lets sagen, ich habe einen Satz: "Dies ist ein Testsatz." Ich möchte, dass ein Benutzer Unterabschnitte des Textes auswählen kann, jedoch ohne Interpunktion oder unvollständige Wörter.Wie ausgewählter Text erweitert werden, um ganze Wörter zu enthalten

So "Testsatz." werden "Testurteil" und "est sentenc" auch "Testsatz" sollte

werden

Hier ist meine aktuellen Code ist:

var getSelectedText = function() { 
    var text = ""; 
    if (window.getSelection) { 
     text = window.getSelection().toString().trim(); 
    } else if (document.selection && document.selection.type != "Control") { 
     text = document.selection.createRange().text; 
    } 
    return text; 
} 

FYI: jQuery-Code ist in Ordnung.

EDIT für Bender:

Ok das ist fast da. Ich habe mehr als 50k Sätze und die Benutzerauswahl ist variabel, so dass ich, so etwas zu tun haben:

var selection = getSelectedText(); 
var exp = new RegExp("\\w*" + selection + "\\w+"); 
text.match(exp); 

Dies wird jedoch nicht überein, wenn ein Benutzer „Testurteil“ auswählt, die eher als nicht.

+4

Ich würde eine Regex verwenden, um das gesamte Wort zu entsprechen. Dies ist ein grundlegendes Beispiel: https://regex101.com/r/xW0mR8/1 Sie müssen es verbessern, damit es mit jedem Auswahlfall richtig funktioniert – BeNdErR

+0

@BeNdErR Clever! :) – Nico

+0

@BeNdErR Bitte sehe meine Bearbeitung. –

Antwort

2

Interessante Herausforderung. Der folgende Code umschließt die Auswahl in einem Bereich mit der Klasse selected.

Es packt die nodeValue der previousSibling und nextSibling des neuen Elements – den entsprechenden Text durch Spalte auf Nicht-Wort-Zeichen bekommen, und knallt (previousSibling) oder Verschiebung (nextSibling).

Es entfernt dann die selected span (während der Inhalt bleibt). Dies muss innerhalb eines Zeitlimits erfolgen, damit das Element Zeit hat, dem DOM hinzugefügt zu werden.

An diesem Punkt sind wir mit drei benachbarten Textknoten übrig. Der Code verbindet sie durch den Aufruf normalize() für den Dokumentkörper.

$(document).mouseup(function() { 
 
    alert(getSelectedText()); 
 
}); 
 

 
var getSelectedText = function() { 
 
    var el= document.createElement('span'), 
 
     sel= window.getSelection().getRangeAt(0), 
 
     prev= '', 
 
     next= ''; 
 
    
 
    el.className= 'selected'; 
 
    sel.surroundContents(el); 
 
    if(!sel.toString().match(/^\W/)) { 
 
    prev= el.previousSibling.nodeValue; 
 
    if(prev.match(/\W$/)) { 
 
     prev= ''; 
 
    } 
 
    else { 
 
     prev= prev.split(/\W/).pop(); 
 
    } 
 
    } 
 
    if(!sel.toString().match(/\W$/)) { 
 
    next= el.nextSibling.nodeValue; 
 
    if(next.match(/^\W/)) { 
 
     next= ''; 
 
    } 
 
    else { 
 
     next= next.split(/\W/).shift(); 
 
    } 
 
    } 
 
    setTimeout(function() { 
 
    $('.selected').contents().unwrap() 
 
    $('.selected').remove(); 
 
    document.body.normalize(); 
 
    }); 
 
    return prev+sel.toString()+next; 
 
}
.selected { 
 
    color: red; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
This is a test sentence. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

0

schaffte ich es durch Zugabe von Spannweiten zu jedem Wort zum Laufen zu bringen. Die Idee ist, dass Sie nicht weniger als eine Spanne/Wort auswählen können, auf diese Weise wird die gesamte Spanne ausgewählt. Diese Antwort hängt nicht von jQuery ab.

function customSelect(target, onSelect) { 
 
    var oldHTML = target.innerHTML; 
 
    
 
    // this is the regex that wraps the words with spans: 
 
    target.innerHTML = oldHTML.replace(/[\d\w']+[\s,.]*/g, '<span>$&</span>'); 
 
    var spans = target.querySelectorAll('span'); 
 
    
 
    // I used a basic blue/white style, but you can change it in the CSS 
 
    // using the ".text-selected" selector 
 
    var alreadySelected = []; 
 
    var setSpanOn = function(span) { 
 
    alreadySelected.push(span); 
 
    span.className = 'text-selected'; 
 
    }; 
 
    var setSpanOff = function(span) { 
 
    span.className = ''; 
 
    }; 
 
    
 
    // here starts the logic 
 
    var isSelecting = false; 
 
    for (var i=0, l=spans.length; i<l; i++) { 
 
    (function span_handlers(span, pos) { 
 
    
 
     // when the user starts holding the mouse button 
 
     span.onmousedown = function() { 
 
     // deselect previous selection, if any: 
 
     alreadySelected.splice(0).forEach(setSpanOff); 
 
     
 
     // and enable selection: 
 
     isSelecting = true; 
 
     span.onmouseenter(); 
 
     }; 
 
     
 
     // the main logic, we check if we need to set or not this span as selected: 
 
     span.onmouseenter = function() { 
 
     if (!isSelecting) 
 
      return; 
 
     
 
     // if already selected 
 
     var j = alreadySelected.indexOf(span); 
 
     if (j >= 0) { 
 
      // then deselect the spans that were selected after this span 
 
      alreadySelected.splice(j+1).forEach(setSpanOff); 
 
     } 
 
     else { 
 
      // else if is not the first, check if the user selected another word 
 
      // one line down or up. This is done by checking the indexes: 
 
      if (alreadySelected.length) { 
 
      var last = alreadySelected[alreadySelected.length-1]; 
 
      var posLast = [].indexOf.call(spans, last); 
 
      var typeSibling = pos > posLast ? 'nextSibling' : 'previousSibling'; 
 
      while (1) { 
 
       last = last[typeSibling]; 
 
       if (last !== span) 
 
       setSpanOn(last); 
 
       else break; 
 
      } 
 
      } 
 
      setSpanOn(span); 
 
     } 
 
     }; 
 
     
 
     // when the user hold up the mouse button: 
 
     span.onmouseup = function() { 
 
     isSelecting = false; 
 
     
 
     // call the onSelect function passing the selected spans content: 
 
     if (typeof onSelect === 'function') { 
 
      var spansSelected = target.querySelectorAll('.text-selected'); 
 
      var text = [].map.call(spansSelected, function(span) { 
 
      return span.textContent || ''; 
 
      }).join('').trim(); 
 
      onSelect(text); 
 
     } 
 
     }; 
 
    })(spans[i], i); 
 
    } 
 
}; 
 

 
// Usage: 
 
var element = document.getElementById('target'); 
 
var onSelect = function(text) { 
 
    console.log(text); 
 
}; 
 
customSelect(element, onSelect);
#target { 
 
    user-select: none; 
 
} 
 

 
.text-selected { 
 
    background-color: blue; 
 
    color: white; 
 
}
<div id="target"> 
 
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. 
 
</div>

dokumentiert ich den Code mit einigen Kommentaren, aber wenn Sie irgendwelche Zweifel zu fragen, fühlen Sie sich frei.

Hoffe es hilft :)

Verwandte Themen