2010-12-21 12 views
7

Questo è un problema abbastanza discusso sui forum di jQuery ma non riesco a trovare una soluzione per la mia situazione.jQuesta funzione text() perde interruzioni di riga in IE

Ho un elenco non ordinato con alcuni elementi di testo in loro ... l'utente può creare nuovi elementi di elenco tramite jQuery, che vengono salvati in un database SQL. Possono anche modificare voci di elenchi esistenti. Inoltre, poiché il testo di ogni elemento della lista può essere piuttosto lungo, ha la possibilità di "nascondere" ogni voce dell'elenco in modo che mostri una versione troncata della stringa. Questo è gestita da un plugin jQuery personalizzata che tronca le voci di elenco che sono oltre una certa lunghezza ... ecco cosa ogni elemento della lista si presenta come una volta il plugin Tronca ha formattato:

<li id="item_1"> 
<div class="note"> 
    This is the text that shows when this element is truncated <span style="display: none;" class="truncate_ellipsis">...</span> 
<span style="display: inline;" class="truncate_more">This is the text that will be hidden if the user clicks on the 'hide' button</span> 
</div> 
<div class="toggle_wrapper"> 
    <div class="note_toggle"> 
     <a href="#" class="truncate_more_link">Hide note</a> 
    </div> 
    <div style="display: block;" class="note_controls"> 
     <span class="edit_note"><a href="#note_textfield" id="edit_note_1">Edit</a></span> | <span class="delete_note"><a href="#" id="delete_note_1">Delete</a></span> 
    </div> 
</div> 
</li> 

Il problema che ho è che il l'utente fa clic su "modifica" e prende il contenuto del div con la "nota" della classe e lo assegna a un'area di testo. L'utente può quindi modificare il testo e salvarlo. Sto usando il seguente script per afferrare il contenuto del div e assegnarlo alla textarea:

$('.edit_note a').click(function(event){ 

    // Get the parent li of the 'edit' link that was clicked 
    var parentLi = $(this).closest('li'); 

    // fade out the li that's being edited 
    parentLi.fadeOut('fast'); 

    // remove the '...' that shows when the note is truncated 
    parentLi.find('.truncate_ellipsis').remove(); 

    // find the 'note' div within the li that's being edited 
    var currentNote = parentLi.find('.note'); 

    // grab the id of this note... used when saving to the DB 
    var noteId = $(this).attr('id').substr(10); 

    // Set the current note id variable and editing status 
    currentNoteId = noteId; 
    currentNoteStatus = 'edit'; 

    //add the note ID as a hidden field to the text editor form 
    $('input[name$="note_id"]').val(noteId); 

    // grab the text from this note and add it to the text area 
    // (textarea id is 'notes_content') 
    $('#notes_content').val($.trim(currentNote.text()); // this is the text area 

    // fade in the text area so the user can edit 
    $('div.notes_textarea').fadeIn(); 

}); 

una volta salvato Sto usando una funzione che ho trovato online per convertire le interruzioni di riga per regolamenti di base, prima di assegnare il contenuto dell'area di testo al div 'notare' all'interno della voce di elenco appropriato:

function nl2br (str, is_xhtml) { 
var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />' : '<br>';  
return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ breakTag +'$2'); 
} 

tutto questo funziona bene in Firefox/Chrome/Opera/safari ... tuttavia, IE si libera della linea si rompe quando afferra il testo tramite la funzione jQuery text(). Questo è discusso nei commenti di questa pagina sulla documentazione jQuery:

http://api.jquery.com/text/

Alcune persone hanno avuto successo clonando l'elemento di origine, avvolgendolo in tag 'pre', poi prendendo il contenuto di quella e mettendo nell'area di testo. Questo funziona per le interruzioni di riga, ma porta anche spazi extra, schede ecc. E sembra un po 'un disastro. Una soluzione migliore sembra essere quella di utilizzare la funzione jQuery html() per afferrare il testo, quindi sostituire br's per le interruzioni di riga e rimuovere ogni altra formattazione html.

Sono nuovo di Javascript, tuttavia, e sono schifoso alle espressioni regolari, quindi non avrei la minima idea di come farlo e ho poco tempo! Ho bisogno di un'espressione regolare, o semplicemente un po 'di aiuto con formattazione di stringhe per effettuare le seguenti operazioni:

  • Rimuovere tutti i tag span da una stringa senza rimuovere il contenuto della campata (la mia funzione Tronca aggiunge un arco con la classe " truncate_more" ... vedi codice html sopra)

  • rimozione di BR e sostituirli con caratteri di nuova riga che verranno visualizzati correttamente in un elemento textarea garantendo la coerenza tra i vari browser

O .. se qualcuno sa di una soluzione migliore a questo problema di IE/textarea/linebreak, apprezzerei davvero una guida idiota :)

Un bel po 'di informazioni per quella che probabilmente è una soluzione semplice ma ho pensato di provare a spiegare la situazione nel modo migliore possibile ! Qualsiasi aiuto sarebbe enormemente apprezzato ....

EDIT: 'La risposta di TheJuice seguito lavorato per le BR/linea IE rompe questione (grazie!), Ma ho bisogno di effettuare una regex simile a sbarazzarsi del si estende, poiché incapsulano solo parte del testo.Ho provato il seguente, che sembra funzionare bene in Firefox, ma in IE campate rimangono:

 var withBRs = currentNote.html(); 
    var textWithBreaks = withBRs.replace(/\<br\>/gi,'\r'); 
    textWithBreaks = textWithBreaks.replace(/\<.*span.*\>/g, ''); 

ALTRO EDIT: 'TheJuice' risolto anche questo problema ... ignorare il mio regex orribile e solo fare quello che lui dice se ti trovi nella stessa situazione! Grazie a tutti coloro che hanno offerto suggerimenti ...

risposta

6

Ecco una soluzione molto più semplice per convertire qualsiasi HTML in testo normale con interruzioni di riga basate sull'utilizzo dei tag <br> o <p>.

function htmlDecodeWithLineBreaks(html) { 
    var breakToken = '_______break_______', 
     lineBreakedHtml = html.replace(/<br\s?\/?>/gi, breakToken).replace(/<p\.*?>(.*?)<\/p>/gi, breakToken + '$1' + breakToken); 
    return $('<div>').html(lineBreakedHtml).text().replace(new RegExp(breakToken, 'g'), '\n'); 
} 

Per esempio, chiamando il seguente metodo:

htmlDecodeWithLineBreaks('line 1<br>line &amp; 2<br />' + 
    'line &gt; 3<p>paragraph 1</p>line 4') 

rendimenti:

line 1 
line & 2 
line > 3 
paragraph 1 
line 4 

Speranza che aiuta;)

+0

Super questo funziona con jQuery 'cheerio' per Node.js - consultare https://github.com/cheeriojs/cheerio/issues/839 – loretoparisi

6

Penso che qualcosa del genere funzionerà per voi. http://jsfiddle.net/6qbxn/2/. Ho provato questo in IE 7 FF 4.0b7 e funziona come previsto.

JS:

var withBRs = $('#brText').html(); 
var textWithBreaks = withBRs.replace(/\<br\>/gi,'\r'); 
$('#area').text(textWithBreaks); 

HTML:

<HTML> 
<body> 
    <div id="brText">Hello <br>How<br>Are<br>You?</div> 
    <textarea rows="10" id="area"> 

    </textarea> 
</body> 

Edit: Questo risolve il tuo punto di proiettile secondo.

+0

Come per il primo proiettile, se i vostri campate Basta avvolgere il testo che ti serve può cambiare il tuo selettore per sbarazzartene. http://jsfiddle.net/6qbxn/4/ – offner

+0

Grazie mille ragazzi, è esattamente quello che stavo cercando! Sapevo che sarebbe stato qualcosa di semplice. Tuttavia, ho ancora un piccolo problema; la span non incapsula tutto il testo, inizia a metà strada. Il div si apre, poi c'è del testo, poi c'è una span che contiene il resto del testo, quindi in realtà devo eliminare i tag di apertura e di chiusura (a mente vuota viene aggiunto al tag di apertura tramite jQuery per il troncato funzione - vedi markup sopra). C'è un modo semplice per farlo con una funzione di sostituzione simile? Sono nuovo di regex così i miei sforzi sono piuttosto patetici! –

+0

@Mr_Beagle: selezionerei l'HTML dalla prima span e aggiungerò l'HTML dalla seconda span ad esso (supponendo che tu abbia sempre solo 2 span). Successivamente, sostituisci lo
. Probabilmente vuoi evitare di usare espressioni regolari se puoi, anche se il codice che ti ho mostrato potrebbe rompersi se qualcuno fa un tag come "
". – offner

Problemi correlati