Cambia CSS del testo selezionato usando Javascript

Sto cercando di creare un bookmarklet javascript che funga da evidenziatore, cambiando lo sfondo del testo selezionato in una pagina Web in giallo quando viene premuto il bookmarklet.

Sto usando il seguente codice per ottenere il testo selezionato, e funziona bene, restituendo la stringa corretta

function getSelText() { var SelText = ''; if (window.getSelection) { SelText = window.getSelection(); } else if (document.getSelection) { SelText = document.getSelection(); } else if (document.selection) { SelText = document.selection.createRange().text; } return SelText; 

}

Tuttavia, quando ho creato una funzione simile per cambiare il CSS del testo selezionato usando jQuery, non funziona:

 function highlightSelText() { var SelText; if (window.getSelection) { SelText = window.getSelection(); } else if (document.getSelection) { SelText = document.getSelection(); } else if (document.selection) { SelText = document.selection.createRange().text; } $(SelText).css({'background-color' : 'yellow', 'font-weight' : 'bolder'}); 

}

Qualche idea?

Il modo più semplice per farlo è usare execCommand() , che ha un comando per cambiare il colore di sfondo in tutti i browser moderni.

Il seguente dovrebbe fare quello che vuoi su qualsiasi selezione, compresi quelli che si estendono su più elementi. Nei browser non-IE triggers designMode , applica un colore di sfondo e quindi distriggers nuovamente designMode .

AGGIORNARE

Risolto in IE 9.

 function makeEditableAndHighlight(colour) { var range, sel = window.getSelection(); if (sel.rangeCount && sel.getRangeAt) { range = sel.getRangeAt(0); } document.designMode = "on"; if (range) { sel.removeAllRanges(); sel.addRange(range); } // Use HiliteColor since some browsers apply BackColor to the whole block if (!document.execCommand("HiliteColor", false, colour)) { document.execCommand("BackColor", false, colour); } document.designMode = "off"; } function highlight(colour) { var range, sel; if (window.getSelection) { // IE9 and non-IE try { if (!document.execCommand("BackColor", false, colour)) { makeEditableAndHighlight(colour); } } catch (ex) { makeEditableAndHighlight(colour) } } else if (document.selection && document.selection.createRange) { // IE <= 8 case range = document.selection.createRange(); range.execCommand("BackColor", false, colour); } } 

Ecco un esempio grezzo di come potrebbe funzionare. Come sottolinea Zack, devi essere consapevole dei casi in cui la selezione si estende su più elementi. Questo non è destinato ad essere usato così com’è, solo qualcosa per aiutare a far fluire le idee. Testato in Chrome.

 var selection = window.getSelection(); var text = selection.toString(); var parent = $(selection.focusNode.parentElement); var oldHtml = parent.html(); var newHtml = oldHtml.replace(text, ""+text+""); parent.html( newHtml ); 

In Firefox, puoi usare la class psuedo ::-moz-selection .
In Webkit, puoi usare la pseudo-class ::selection .

Dai un’occhiata ad un piccolo esempio che ho fatto su http://www.jsfiddle.net/hbwEE/3/

Non tiene conto delle selezioni che si estendono su più elementi .. ( IE lo farà, ma pasticcia un po ‘l’html .. )

Per rendere permanente la barra di evidenziazione, credo che dovrai avvolgere la selezione in un nuovo elemento DOM (dovrebbe fare lo span ), a cui puoi quindi aggiungere proprietà di stile. Non so se jQuery possa farlo per te. Tieni presente che le selezioni possono estendersi sui limiti degli elementi, quindi nel caso generale dovrai iniettare un sacco di nuovi elementi

Mi piace la risposta di Tim, è pulita e veloce. Ma spegne anche le porte per fare qualsiasi interazione con i punti salienti.

Inserire elementi inline direttamente attorno ai testi è una ctriggers scelta, poiché hanno rotto il stream del testo e fatto confusione in situazioni complesse,

Quindi suggerisco un trucco sporco

  1. calcola il layout assoluto di ogni riga del testo selezionato (indipendentemente da dove si trovano),
  2. quindi inserire elementi di blocco in linea colorati semitrasparenti nella parte finale del corpo del documento.

Questa estensione di Chrome è un esempio di come questo può essere fatto.

Usa API da questa libreria per ottenere il layout assoluto di ogni linea selezionata.