2012-03-30 7 views
1
<div id="content" contenteditable="false" style="margin:-0.2em 1em; font-family:New Century Schoolbook; font-size:20; color:black; line-height:170%"> 
     <span style="margin-left:1.7em">Jenny was cute!</span> 
     <span style="margin-left:1.7em">She looked happy with the instructor.</span> 
     <span style="margin-left:1.7em">Can we meet her again?</span><br> 
     <span style="margin-left:18em">Sakura</span> 
    </div> 

Hier ist einige HTML, die ich erstellt habe, um die Bedürfnisse eines Kunden zu erfüllen. Der linke Rand ist so, dass ich zwischen jedem Satz ein separates Bild einfügen kann (die Benutzerauswahl wird völlig komisch, wenn Bilder im HTML sind). Der Benutzer muss in der Lage sein, Abschnitte wie in der iBook App auszuwählen, zu markieren und hinzuzufügen. Im Gegensatz zur iBook-App muss dies jedoch mit formatierten Text geschehen. Also muss es auswählbar, editierbar und unterstützt fett, kursiv und unterstrichen in der gleichen Ansicht sein. Hier ist das Javascript, das ich mir ausgedacht habe (der HTML und das Ergebnis vom Javascript sind nicht standardkonform, aber das ist mir egal, da dies keine Webseite sein wird und ich die Nase voll habe):Wie kann ich diese Javascript-Highlighting-Technik erreichen?

function addHighlight(className, id) 
{ 
    var html = ''; 
    var sel = window.getSelection().getRangeAt(0); 
    var container = document.createElement('JimSpan'); 
    container.id = id; 
    container.className = className; 
    container.appendChild(sel.extractContents()); 

    var arrElements = document.getElementsByTagName('span'); 
    for(i = 0; i < arrElements.length-1; i++) 
    { 
     if(!arrElements[i].innerText.match(/\S/)) 
     { 
      arrElements[i].parentNode.removeChild(arrElements[i]); 
     } 
    } 

    sel.insertNode(container); 

    return 'js: ADDED HIGHLIGHT'; 
} 

Der Grund, warum ich "JimSpan" und nicht "Span" verwenden muss, ist, dass der Benutzer die Notizen löschen muss, während die Seite nicht angezeigt wird, was bedeutet, dass ich sie manuell mit regulären Ausdrücken bearbeiten muss. Da es Tonnen von Spannweiten gibt, werde ich keine Ahnung haben, wann meine eigentlich endet. Dies funktioniert mit einer Ausnahme gut. Wenn der Benutzer alle ein Element und Teil eines anderen wählt, ist das Ergebnis folgendermaßen aus:

<div id="content" contenteditable="false" style="margin:-0.2em 1em; font-family:New Century Schoolbook; font-size:20; color:black; line-height:170%"> 
    <jimspan id="memo0" class="pinkHilite"><span style="margin-left:1.7em">Jenny was cute!</span> 
    <span style="margin-left:1.7em">She</span></jimspan><span style="margin-left:1.7em"> looked happy with the instructor.</span> 
    <span style="margin-left:1.7em">Can we meet her again?</span><br> 
    <span style="margin-left:18em">Sakura</span> 
</div> 

Wie Sie in der Mitte sehen kann, ist die Spaltung der Satz führte Sie mit dem Lehrer glücklich sah in aufgeteilt werden zwei Spannen, jeder mit dem linken Rand, und ich bin mit einer riesigen Lücke in der Mitte des Satzes verlassen. Ich werde eines der folgenden akzeptieren:

1) Eine Möglichkeit für mich, die folgende (technisch ungültige, aber feine Anzeige) HTML (Ich habe nichts dagegen, den aktuellen Bereich mit Regex zu bearbeiten, wenn es eine Möglichkeit gibt das):

<div id="content" contenteditable="false" style="margin:-0.2em 1em; font-family:New Century Schoolbook; font-size:20; color:black; line-height:170%"> 
    <jimspan id="memo0" id="pinkHilite"><span style="margin-left:1.7em">Jenny was cute!</span> 
    <span style="margin-left:1.7em">She</jimspan> looked happy with the instructor.</span> 
    <span style="margin-left:1.7em">Can we meet her again?</span><br> 
    <span style="margin-left:18em">Sakura</span> 
</div> 

2) Ein Weg, um die Benutzerauswahl zu zwingen, nur die Innenseite von 1 Spanne umfasst (die Auswahl muß, ändert den betroffenen Hervorhebungsbereich nicht gerade).

Bitte helfen Sie meine Gesundheit zu retten - _ _-;

+0

Versuchte 'document.execCommand ("HiliteColor" false "pink")'? Oder benötigen Sie mehr Kontrolle über das Highlight Styling als nur eine Hintergrundfarbe? –

+0

Ja, das wird es nicht schneiden. Es ist nicht konsistent. Manchmal fügt es einen Bereich hinzu und fügt dem aktuellen DOM-Gestaltungselement manchmal eine Klasse hinzu ( wird usw.). Außerdem verwende ich ein Bild, keine Farbe. Zu guter Letzt muss ich in der Lage sein, einen Bereich zu haben, der dem Bereich des Memos entspricht, das der Benutzer geschrieben hat, und execCommand teilt den Bereich manchmal in mehrere Bereiche auf. – borrrden

+0

Ich muss in der Lage sein, die Hervorhebung zu entfernen, so dass sie in den Zustand zurückkehrt, in dem sie vor der Hervorhebung war, und das wird mit dieser Inkonsistenz nicht passieren. – borrrden

Antwort

1

Option 2 ist die einfachste Lösung, und ganz erreichbar mit Range und Selection Objekten (Ausschluss IE < 9, die nicht für ein UIWebView egal aber jemanden könnte will in einem Browser ähnlich zu tun). Im Folgenden wird die Auswahl auf das Element begrenzt den Punkt enthält, bei dem der Benutzer der Auswahl gestartet (Anmerkung: aus Gründen der Darstellung, es funktioniert nur mit Maus-basierten Auswahl):

Live-Demo: http://jsfiddle.net/U4smu/

-Code :

function isOrIsDescendantOf(node, ancestor) { 
    while (node) { 
     if (node === ancestor) { 
      return true; 
     } 
     node = node.parentNode; 
    } 
} 

function selectionIsBackwards(sel) { 
    var range = document.createRange(); 
    range.setStart(sel.anchorNode, sel.anchorOffset); 
    range.setEnd(sel.focusNode, sel.focusOffset); 
    var backwards = range.collapsed; 
    range.detach(); 
    return backwards; 
}  

document.onmouseup = function() { 
    var sel = window.getSelection(); 
    var containerEl = sel.anchorNode; 
    if (containerEl) { 
     if (containerEl .nodeType == 3) { 
      containerEl = containerEl.parentNode; 
     } 

     if (!isOrIsDescendantOf(sel.focusNode, containerEl)) { 
      var backwards = selectionIsBackwards(sel); 
      var range = document.createRange(); 
      if (backwards) { 
       range.setStart(containerEl, 0); 
       range.setEnd(sel.anchorNode, sel.anchorOffset); 
      } else { 
       range.setStart(sel.anchorNode, sel.anchorOffset); 
       range.setEnd(containerEl, containerEl.childNodes.length); 
      } 
      sel.removeAllRanges(); 
      sel.addRange(range); 
     } 
    } 
}; 
+0

Vielen Dank dafür!Sie sind wirklich ein Javascriptspezialist, wie Ihr Profil anzeigt;). Ich bin ein Javascript primate> _ < – borrrden

+0

@borrrden: Dies ist auch mein Fachgebiet in JavaScript :) –

Verwandte Themen