Функция jQuery text () теряет разрывы строк в IE - PullRequest
7 голосов
/ 21 декабря 2010

Это довольно обсуждаемая проблема на форумах jQuery, но я не могу найти решение для моей ситуации.

У меня есть неупорядоченный список с некоторыми текстовыми элементами в них ... пользователь может создавать новые элементы списка через jQuery, которые сохраняются в базе данных SQL. Они также могут редактировать существующие элементы списка. Кроме того, поскольку текст в каждом элементе списка может быть довольно длинным, у них есть возможность «скрыть» каждый элемент списка, чтобы он отображал усеченную версию строки. Это обрабатывается пользовательским плагином jQuery, который усекает элементы списка более определенной длины ... вот как выглядит каждый элемент списка после его форматирования плагином усечения:

<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>

Проблема, с которой я столкнулся, заключается в том, что пользователь нажимает «edit», и он берет содержимое div с классом «note» и назначает его текстовой области. Затем пользователь может отредактировать текст и сохранить его. Я использую следующий скрипт, чтобы получить содержимое div и присвоить его текстовой области:

$('.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();

});

Как только он сохранен, я использую функцию, которую я нашел в Интернете, чтобы преобразовать разрывы строк в БР, прежде чем присваивать содержимое текстовой области обратно div 'note' в соответствующем элементе списка:

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');
}

Все это прекрасно работает в firefox / chrome / opera / safari ... однако IE избавляется от разрывов строк, когда получает текст с помощью функции text () jQuery. Это обсуждается в комментариях этой страницы к документации jQuery:

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

Некоторые люди добились успеха, клонировав исходный элемент, обернув его в теги pre, затем взяв его содержимое и поместив в текстовую область. Это работает для разрывов строк, но также приводит к появлению лишних пробелов, табуляции и т. Д., И выглядит немного беспорядочно. Лучшим решением, по-видимому, является использование функции html () jQuery для захвата текста, затем замена br на разрывы строк и удаление любого другого html-форматирования.

Я новичок в Javascript, однако, и я мусор на регулярных выражениях, поэтому я не имею понятия, как это сделать, и у меня заканчивается время! Мне нужно регулярное выражение или просто некоторая помощь с форматированием строки, чтобы сделать следующее:

  • удалить все теги span из строки БЕЗ удаления содержимого диапазона (моя функция truncate добавляет диапазон с классом "truncate_more" ... см. Выше HTML-код)

  • Удалите символы br и замените их символами новой строки, которые будут правильно отображаться в элементе textarea и будут согласованы во всех браузерах

ИЛИ ... если кто-нибудь знает о лучшем обходном пути к этой проблеме IE / textarea / linebreak, я бы очень признателен за руководство для идиотов:)

Немного информации о том, что, вероятно, является простым решением, но я подумал, что постараюсь объяснить ситуацию как можно лучше! Любая помощь будет принята с благодарностью ....

EDIT : 'Ответ TheJuice ниже работал для проблемы разрывов строк в br / IE (спасибо!), Но мне нужно выполнить аналогичное регулярное выражение, чтобы избавиться от промежутков, поскольку они только инкапсулируют некоторые текста. Я попробовал следующее, которое, кажется, работает нормально в Firefox, но в IE, диапазоны остаются:

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

ДРУГОЕ РЕДАКТИРОВАНИЕ : «TheJuice» тоже решил эту проблему ... не обращайте внимания на мое ужасное регулярное выражение и просто делайте то, что он говорит, если вы попадаете в ту же ситуацию! Спасибо всем, кто предложил предложения ...

Ответы [ 2 ]

6 голосов
/ 14 марта 2012

Вот гораздо более простое решение для преобразования любого HTML в простой текст с разрывами строк на основе использования тегов <br> или <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');
}

Например, вызывая следующий метод:

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

возвращается:

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

Надеюсь, это поможет;)

6 голосов
/ 22 декабря 2010

Я думаю, что-то вроде этого будет работать для вас. http://jsfiddle.net/6qbxn/2/. Я протестировал это в IE 7 & 8 & FF 4.0b7, и все работает как положено.

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>

Редактировать: это адрес вашей второй точки пули.

...