Javascript-форум (https://javascript.ru/forum/)
-   Javascript под браузер (https://javascript.ru/forum/css-html/)
-   -   textarea scroll set problem (https://javascript.ru/forum/css-html/13311-textarea-scroll-set-problem.html)

fel1ow 25.11.2010 18:03

textarea scroll set problem
 
Доброго времени суток. При разработке сложилась проблема, которую уже два дня не можем решить. Попытаюсь изложить всё детально, буду очень признателен, если сможете помочь.

Есть TEXTAREA (дальше ТА), в ней много текста, где то в середине выделено мышью пару слов. Нужно проскролить ТА прямо к выделению. В Internet Explorere реализация проста (в одну строку):

document.selection.createRange().scrollIntoView();

Другие браузеры не понимают объекта selection.createRange() и насколько я знаю не имеют аналогичного ему объекта, поэтому нету возможности использовать метод scrollIntoView(), так как он скролит только к конкретному объекту\элементу.

Если аналог selection.createRange() есть, пожалуйста, сообщите.

Если кто то знает как решить данную проблему, пожалуйста, отпишитесь.

fel1ow 28.12.2010 19:30

Решение задачи.
 
Задачу решили следующим способом: делается клон упомянутого TA, от текста что внутри ТА берётся только часть от начала текста до выделения и запихивается в клон, который конечно же не просто лежит в памяти а уже подключён в DOM структуру, к примеру методом appendChild, в какой то див абсолютно расположенный вне зоны видимости экрана (top:-1000;left:-1000;). Далее смотрим у клона параметр scrollHeight который вернёт высоту скрола клона в пикселях. Теперь это значение можно задать нашей главной ТА через параметр scrollTop. Это всё, скрол должен опуститься на нужное расстояние к выделенному тексту. Может быть погрешность в одну строчку что решается отниманием высоты одной строки от значения которое мы получили. Вот код решения с использованием библиотеки ExtJS:

var obj = document.getElementById("text_area");
obj.focus();

var proxy = obj.cloneNode(false);
proxy.id = Ext.id();
var hidden_div = Ext.get("HIDDEN_CONTAINER");
var proxy_extjs = Ext.get(proxy);
hidden_div.appendChild(proxy_extjs);

// Opera and FF
if ( !Ext.isIE )
{
var start = obj.selectionStart;
var end = obj.selectionEnd;
}
else
{
var range = document.selection.createRange();
var stored_range = range.duplicate();
stored_range.moveToElementText( obj );
stored_range.setEndPoint( 'EndToEnd', range );
var start = stored_range.text.length - range.text.length;
var end = start + range.text.length;
}

if ( Ext.isIE )
var line_height = document.getElementById(obj.id).currentStyle["line-height"];
else
{
var elstyle = window.getComputedStyle(document.getElementById(ob j.id), "");
var line_height = elstyle.getPropertyValue("line-height");
}

line_height = parseInt(line_height.replace("px"));
proxy.value = obj.value.substr(0,start);

var new_scroll_value = proxy.scrollHeight - line_height;

if ( obj.clientHeight > new_scroll_value )
obj.scrollTop = 0;
else
obj.scrollTop = new_scroll_value;

proxy_extjs.remove();

Самое последнее условие написано для того что бы учесть такой момент: если текст в клоне влазит в область видимости клона и слишком мал для того что бы в клоне появился скрол то свойство клона scrollHeight вернёт минимально возможное значение скола для ТА такого размера, тоесть по сути вернёт рабочую область видимости ТА. Поэтому мы должны проверять этот момент проверять, и в случае если scrollHeight возвращает значение меньшее чем его рабочая область видимости то scrollTop нашей ТА мы присваиваем нулевое значение. Таким образом скол окажется в самом верхнем положении и выделение должно быть перед глазами пользователя.


Часовой пояс GMT +3, время: 04:19.