2010-03-19 6 views
10

Pracuję nad edytorem tekstu sformatowanego, takim jak aplikacja internetowa, w zasadzie edytor XML napisany w javascript.Użyj javascript, aby rozszerzyć zakres DOM, aby pokryć częściowo wybrane węzły.

Mój kod javascript musi zawijać wybrane węzły z kontenera div divider contentEditable. Używam metod opisanych pod adresem MDC. Ale ponieważ muszę synchronizować pojemniki div zawartości do mojego XML DOM Chciałbym uniknąć częściowych wyborów, jak to opisano w w3c ranges:

<BODY><H1>Title</H1><P>Blah xyz.</P></BODY

............^----------------^............

Ten wybór rozpoczyna wewnątrz H1 i kończy się wewnątrz P, Chciałbym, żeby całkowicie zawierał H1, P.

Czy istnieje prosty sposób na rozszerzenie wyboru w celu pokrycia częściowo wybranych dzieci? Zasadniczo chcę użyć range.surroundContents() bez uruchamiania wyjątku.

(Kod nie musi pracować z Opera/IE)

Odpowiedz

8

Patrząc na dokumentacji MDC, udaje mi zrobić coś takiego:

Selection.prototype.coverAll = function() { 
    var ranges = []; 
    for(var i=0; i<this.rangeCount; i++) { 
     var range = this.getRangeAt(i); 
     while(range.startContainer.nodeType == 3 
       || range.startContainer.childNodes.length == 1) 
      range.setStartBefore(range.startContainer); 
     while(range.endContainer.nodeType == 3 
       || range.endContainer.childNodes.length == 1) 
      range.setEndAfter(range.endContainer); 
     ranges.push(range); 
    } 
    this.removeAllRanges(); 
    for(var i=0; i<ranges.length; i++) { 
     this.addRange(ranges[i]); 
    } 
    return; 
}; 

Można spróbować tu: http://jsfiddle.net/GFuX6/9/

edit: Updated mieć wyświetlacz przeglądarki poprawnie z rozszerzoną wybór. Robi to, o co prosiłeś, nawet jeśli wybór zawiera kilka zakresów (z Ctrl).

dokonać kilku częściowe węzły Bold, oto rozwiązanie:

Selection.prototype.boldinize = function() { 
    this.coverAll(); 
    for(var i=0; i<this.rangeCount; i++) { 
     var range = this.getRangeAt(i); 
     var parent = range.commonAncestorContainer; 
     var b = document.createElement('b'); 
     if(parent.nodeType == 3) { 
      range.surroundContents(b); 
     } else { 
      var content = range.extractContents(); 
      b.appendChild(content); 
      range.insertNode(b); 
     } 
    } 
}; 
+0

Rzeczywiście, ale myślę, że jest to właściwy tor. Spróbuję utworzyć niestandardową selekcję z oryginalnej, która ma te właściwości. –

+0

Przedłużę moje pytanie, aby było jaśniejsze. Również zaktualizowałem przykład na http://jsfiddle.net/GFuX6/5/ –

+0

Wybierz tekst, naciśnij klawisz escape, a tekst staje się pogrubiony. W skrzypcach jest długa linia: 'window.getSelection(). GetRangeAt (0) .surroundContents (tag);' Obecne skrzypce rozszerzają granice węzłów tekstowych, ale nie jestem w stanie znaleźć sposobu na pokrycie części. włączone węzły. –

0

Jeśli masz na myśli chcesz zawierać znaczniki H1 i P (tj prawidłowych znaczników), nie martw się. Dostajesz to za darmo. Jeśli chcesz, aby zawierał całą zawartość w ramach (częściowej) selekcji, musisz uzyskać dostęp do obiektu Selection. Przeczytaj o tym na Quirksmode's introduction to Range.

+0

Jak stanach Quirks Mode artykułu, przeglądarek naprawić ten „nieprawidłowy” HTML „przeglądarek dodać minimalną ilość HTML, aby Zakres ważny”. Wolę nie mieć niepoprawnych selekcji;) –

0

Dzięki Alsciende I wreszcie przyszedł z kodem na http://jsfiddle.net/wesUV/21/. Ta metoda nie jest tak zachłanna jak druga. Po coverAll(), surroundContents() powinien zawsze działać.

Selection.prototype.coverAll = function() { 
    var ranges = []; 
    for(var i=0; i<this.rangeCount; i++) { 
    var range = this.getRangeAt(i); 
    var ancestor = range.commonAncestorContainer; 
    if (ancestor.nodeType == 1) {    
     if (range.startContainer.parentNode != ancestor && this.containsNode(range.startContainer.parentNode, true)) { 
      range.setStartBefore(range.startContainer.parentNode); 
     } 
     if (range.endContainer.parentNode != ancestor && this.containsNode(range.endContainer.parentNode, true)) { 
       range.setEndAfter(range.endContainer.parentNode); 
     } 
    } 
    ranges.push(range); 
    } 
    this.removeAllRanges(); 
    for(var i=0; i<ranges.length; i++) { 
    this.addRange(ranges[i]); 
    } 
    return; 
}; 

a funkcja boldinize:

Selection.prototype.boldinize = function() { 
    for(var i=0; i<this.rangeCount; i++) {   
    var range = this.getRangeAt(i); 
    var b = document.createElement('b'); 
    try { 
     range.surroundContents(b); 
    } catch (e) { 
     alert(e); 
    } 
    } 
}; 
Powiązane problemy