Проблема с обнаружением новых строк в объекте диапазона JavaScript

У меня есть javascript, который манипулирует html на основе того, что выбрал пользователь. Для реальных браузеров методы, которые я использую, используют объект Range, полученный как таковой:

    var sel = window.getSelection();
    var range = sel.getRangeAt(0);
    var content = range.toString();

Переменная содержимого содержит весь выделенный текст, который отлично работает. Однако я обнаружил, что не могу обнаружить новые строки в результирующей строке. Например:

Выбранный текст:

азбука

деф

гхи

range.toString() оценивается как «abcdefghi».

Любой поиск по специальным символам не возвращает ни одного экземпляра \n ​​\f \r или даже \s. Если, однако, я записываю переменную в редактируемый элемент управления, переводы строк снова присутствуют.

Кто-нибудь знает, что мне не хватает?

Может быть важно, чтобы эти выборки и манипуляции находились в редактируемых элементах div. Такое же поведение наблюдается в Chrome, FireFox и Opera. Удивительно, но IE в любом случае нужен совершенно другой код, но там нет никаких проблем, кроме того, что это просто IE.

Большое спасибо.


person Timbo    schedule 18.07.2009    source источник
comment
Что вы подразумеваете под «range.toString() оценивается как abcdefghi»? Что вы используете для проверки этого значения? Отладчик? тревога()?   -  person Ben Dunlap    schedule 18.07.2009
comment
Вы записываете значение range в редактируемый элемент управления или range.toString()?   -  person RaYell    schedule 18.07.2009
comment
@Ben Dunlap все вышеперечисленное с использованием внешних отладчиков, предупреждений или отладчиков на основе браузера. Например, попадание в точку останова в Visual Studio. @RaYell - я попытался записать содержимое, полученное в результате моего вызова range.toString(), в редактируемый div, чтобы доказать, что он поддерживает информацию о новой строке. 1-й ответ прибил это, однако, sel.toString() имеет новые строки, а range.toString() - нет. Спасибо всем.   -  person Timbo    schedule 18.07.2009


Ответы (3)


Редактирую свой пост:

Немного поэкспериментировав, я обнаружил, что sel.toString() возвращает новые строки в редактируемых элементах div, а range.toString() правильно возвращает новые строки в обычных нередактируемых элементах div, но не в редактируемых, как вы сообщили.

Однако объяснения такому поведению найти не удалось.

Это полезная ссылка http://www.quirksmode.org/dom/range_intro.html

person Narayan Raman    schedule 18.07.2009
comment
Отлично, да, sel.toString() имеет новые строки. Большое спасибо! - person Timbo; 18.07.2009
comment
Объяснение простое и изложено в спецификации DOM Range: Range.toString() включает только содержимое текстовых узлов. Поэтому элементы <br> и разрывы строк, подразумеваемые блочными элементами, не включены. - person Tim Down; 14.08.2014
comment
document.getSelection().toString() не работает в IE 11. Он объединяет весь текст новой строки в один. - person agpt; 01.04.2016
comment
Ты самый лучший . Это одно из самых уродливых проявлений ужасов JS, которые я когда-либо видел. До сих пор я искал способ получить выделенный текст (включая новые строки) в течение нескольких часов. Большое тебе спасибо!!! - person Gabo Alvarez; 22.07.2018

Я нашел по крайней мере два других способа, так что вы все еще можете использовать диапазон, чтобы найти положение каретки в Mozilla.

Один из способов - позвонить

var documentFragment = rangeObj.cloneContents ();

который содержит массив дочерних узлов, и любые разрывы строк будут отображаться как узел класса «HTMLBRElement».


Другой способ — убедиться, что за каждым тегом "br" следует символ новой строки (0x0a)!

Это не повредит содержимому HTML каким-либо видимым образом, но теперь все разрывы HTML преобразуются в разрывы строк обычного текста, как только вызывается range.toString()!


Я надеюсь, что это поможет, даже если эта тема очень старая. (я уже некромант, хе-хе) :)

person Gerrit Volkenborn    schedule 14.08.2014
comment
Использование чего-то вроде [].slice.call(window.getSelection().getRangeAt(0)).reduce(...) и замена узлов HTMLBRElement разрывами строк — единственный способ заставить IE11 копировать новые строки. - person Morgan Delaney; 26.05.2018

Благодаря OP я смог сделать это, используя window.getSelection(), как он предложил. Мне нужно было получить текст до позиции курсора в InputEvent , что дает мне статический диапазон со вставленным текстом. Итак, у меня есть диапазон, но не обязательно диапазон текущего выбора.

function richToPoorText(range){
    //Caso base, está colapsado.
        console.log(range);
        var restoreRange=document.createRange(); //needed for restoring the caret pos.
        restoreRange.setStart(range[0].endContainer, range[0].endOffset);
        restoreRange.setEnd(range[0].endContainer, range[0].endOffset);
        rangeClone=document.createRange();
        rangeClone.setStart(__baseEditor,0);
        rangeClone.setEnd(range[0].endContainer, range[0].endOffset);
        var str;
        var sel=window.getSelection();
        sel.removeAllRanges();
        sel.addRange(rangeClone);   //sel does converts the br to newlines
        str=sel.toString();
        sel.removeAllRanges();
        sel.addRange(restoreRange);
        return str;

}

Большое спасибо ОП. И если у кого-то есть такой же вариант использования, вы можете использовать этот фрагмент

Редактировать: __baseEditor — это глобальная переменная, указывающая на главный div contenteditable редактора.

person Gabo Alvarez    schedule 22.07.2018