Как выделить произвольный текст на странице с помощью javascript?

Допустим, у меня есть contentEditable div, чтобы пользователь мог редактировать и изменять текст и элементы внутри него. Как произвольно изменить выбор в этом div с помощью javascript? Под «изменением» я не подразумеваю «изменение содержимого того, что выбрал пользователь», я имею в виду фактическое изменение того, что выбрано. Затем пользователь должен иметь возможность напечатать выделение, заменив его чем-то другим.

Это должно учитывать, что я могу захотеть выделить текст среди элементов. Например:

<p>Some text <span>goes</span> here.</p>

Например, я могу захотеть выбрать «Некоторый текст идти» или все внутри <p>.

Это должно работать только в Safari/Webkit.

Заранее спасибо. Как разработчик нативного кода, я нахожу DOM и Javascript в целом довольно разочаровывающими.


person Lucas    schedule 15.11.2009    source источник


Ответы (4)


Если вам не нужно писать свой собственный, вы можете взглянуть на tinyMCE, http://tinymce.moxiecode.com/, так как это хороший WYSIWYG-редактор в javascript.

Чтобы сделать это, вы, вероятно, захотите посмотреть что-то вроде этого: http://codingtricks.blogspot.com/2009/03/javascript-select-partial-text-in-div.html

Это также может быть полезно: Неправильный ранжирование JavaScript https://developer.mozilla.org/en/DOM/window.getSelection

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

person James Black    schedule 15.11.2009

Просто чтобы подробно ответить на мой собственный вопрос, чтобы любому, кто ищет что-то подобное, не приходилось искать в другом месте...

Код, который я в итоге использовал, был примерно таким:

var range = document.createRange();
range.setStart( <get the node the selection starts in>, <char offset in that node> );
range.setEnd( <get the node the selection ends in>, <char offset in that node> ); 

window.getSelection().removeAllRanges();
window.getSelection().addRange(range);

Большое спасибо Джеймсу Блэку за то, что указал мне правильное направление.

person Lucas    schedule 17.11.2009
comment
Спасибо, что выложили сюда :) - person Tomáš Zato - Reinstate Monica; 23.01.2014

Вы можете использовать document.getElementById('your_text_id').setSelectionRange(start, end); и Math.random() для генерации случайных чисел для start и end.

person Soufiane Hassou    schedule 15.11.2009
comment
Спасибо, но мне нужно иметь возможность выбирать и через границы элементов. И под произвольным я не подразумевал случайный. Я точно знаю элементы, с которых выделение должно начинаться и заканчиваться, вплоть до смещения символа. - person Lucas; 15.11.2009

Хотя ответ @Lucas хорош, многого не хватает, что позволило бы вам успешно использовать это. Узел, с которого начинается выбор, должен быть точным узлом, а не родителем. В нашем случае мы пытались поместить некоторый текст в элемент управления TextAngular, а затем выбрать текст, который выглядел как ____, чтобы пользователь мог «заполнить пробел».

Наш ввод был html порядка <p>Some text goes here: _____</p> или

<p>Some partial goes here
<ul>
    <li>Option 1</li>
    <li>_____</li>
</ul>

Чтобы заставить это работать, нам нужно было написать что-то, чтобы найти символы подчеркивания в правильном элементе.

function find_(node) {
    var i, n;
    // return the node with the _'s
    for(i=0; i < node.childNodes.length; ++i) {
        n = node.childNodes[i];
        console.debug(n);
        if(n.textContent) {
            console.debug(n, n.textContent);
            if(n.textContent.search(/___+/) > 0) {
                return n;
            }
        }
        if(n.childNodes) {
            console.debug(n, n.childNodes);
            n = find_(n);
            if(n) {
                return n;
            }
        }
    }
    return null;
}

Так что, в конце концов, найти узел, удовлетворяющий <get the node the selection starts in>, было намного сложнее, чем это простое предложение заставило меня поверить.

В случае <ul>. узел, содержащий ____, является первым дочерним элементом узла li.

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

IndexSizeError: Failed to execute 'setStart' on 'Range': There is no child at offset 65.

Когда проблема в том, что они просто смотрят не на тот узел.

person boatcoder    schedule 20.05.2014