Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> 4 пробела для Python-а (продолжение) + баги IE, сдвиг строк вправо-влево в textarea 
:(
    Опции темы
12345c
Дата 10.10.2006, 07:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Попытался сделать операцию средствами скриптов Винграда и наткнулся на баг TextRange в IE, не позволяющий это сделать (простыми методами, в 2-10 строчек).

Суть в том, что если выделение текста в Textarea начинается с 1-го символа не 1-й строки, то выделение (selection) "проглатывает" символ переноса строки, и анализом состыкованных объектов Textrange нельзя узнать, стоит ли между ними перенос. Из этого немедленно следует, что таким способом нельзя выполнить сдвиг группы строк - мы не будем знать, сделано выделение в середине или в начале строки. Конечно, другим способом анализа (пересчётом суммы символов) узнать это можно. Но глюк интересен теоретически сам по себе, поэтому вынес его в новую тему. Заодно, несколько развита тема сдвига строк.

В настоящий момент в архиве лежит скрипт, имеющий 2 кнопки - Ctrl+[, Ctrl+] над Textarea, срабатывающий по клавишам, т.е. совместимый по управлению с Винградом. Но действие наблюдается только в IE, и то неправильное, но уже более-менее локализованное, имеющее наглядность. Вся функция лежит в MyLib.js архива под именем TextAreaSelectionHelper.prototype.move4p . Часть, относящаяся к Опере и FF не затрагивалась вследствие таких интересных событий с IE. Если кто желает переписать или поотладить - архив в http://js2.ru/files/vingradScripts.rar (29 К). 

Правила, которые достигались и достигаются пока что - 
* Если курсора в поле нет, реакции на Ctrl+[ нет;
* Если курсор есть, но нет выделения текста или выделение в пределах строки, ставится/удаляется до 4 пробелов в начале строки;
* Если есть выделение, охватывающее переносы строк, ставится/удаляется группа пробелов в каждом начале строки в выделении и в строке в начале выделения;
* позиции выделения или курсора сохраняются относительно существовавшего текста.

Добавлено @ 07:34 
Исходная тема: http://forum.vingrad.ru/index.php?showtopic=113416 - "вставка/удаление 4-х пробелов при нажатии "Ctrl+]"/"Ctrl+[" "

Это сообщение отредактировал(а) 12345c - 3.3.2008, 13:36


--------------------
Google Code Playground - онлайн-отладка своих примеров HTML+JS без регистрации, с сохранением по URL, без кириллицы. Go
PM WWW   Вверх
12345c
Дата 10.10.2006, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Код
IE6-Глюк-демо-код с Textarea+TextRange.<br><br>

<textarea cols=70 rows=20 id=t1>
123
A 3
BB3
</textarea><br><button onmousedown=cl1()>Check selection</button>
<script>t11=(d=document).getElementById('t1')
cl1=function(){if(d.all){
  sel=d.selection.createRange()
  tR=d.body.createTextRange();
  tR2=d.body.createTextRange(); //контрольный объект
  tR.moveToElementText(t11);
  tR2.moveToElementText(t11);
  tR.setEndPoint('EndToStart',sel); //делаем слеплённый textRange
  tR2.setEndPoint('EndToEnd',sel);
alert([sel.text.length,'+',tR.text.length,'=',tR2.text.length,
'\nЧисло должно быть равно сумме двух других',
'\nНо при выделении первого символа во 2-й строке'
+'\nили при курсоре в 1-й позиции сумма на 2 меньше'])
}else{alert("For IE only!");}
}</script>

Хуже того, как узнать, сколько мы выделили пустых переносов строки, как в следующем примере? (Длина выделения равна 0.) Проползанием с помощью moveStart()? А если переносов будет тысячи?
Код
IE6-Глюк-демо-код-2 с Textarea+TextRange.<br><br>
<textarea cols=70 rows=20 id=t1>123



A 3
BB3</textarea><br><button onmousedown=cl1()>Check selection</button>
<script>onload=function(){
  t11=(d=document).getElementById('t1');
  tR=d.body.createTextRange();
  tR.moveToElementText(t11);
  tR.collapse();
  tR.moveEnd('character',7);
  tR.moveStart('character',4);
tR.select();}
cl1=function(){if(d.all){  sel=d.selection.createRange();
  tR2=d.body.createTextRange(); //контрольный объект
  tR.moveToElementText(t11);
  tR2.moveToElementText(t11);
  tR.setEndPoint('EndToStart',sel); //делаем слеплённый textRange
  tR2.setEndPoint('EndToEnd',sel);
alert([sel.text.length,'+',tR.text.length,'=',tR2.text.length,
'\nДлина выделенной пустой строки оказывается равной 0'])
}else{alert("For IE only!");}}</script>

(Ещё не пропало желание сделать отличный редактор для Питона в IE? Интересно, какую длину займёт каждая из предположенных Girder-om пары строк кода? Правильно, настоящим джедаям любая длина не помеха.)

То-то я регулярно замечал, что хорошо отлаженные скрипты вставки BB-кодов иногда выдают ошибку, выражающуюся в "слипании" двух соседних строк после вставки. Смотришь, думаешь, что неудачно выделил, вставляешь перенос и идёшь дальше. Вот где собака зарыта - IE не замечает ("проглатывает") любое количество переносов строк, стоящее на краях области выделения. И это остаётся после действия замены document.selection - перенос строки или несколько переносов перестают существовать.

Задача, стало быть, заключается в том, чтобы вычислить (нащупать) то, сколько переносов строк находится на краях области выделения. Метод имеется единственный - moveStart/moveEnd. (При этом надо учитывать, что он понимает перенос как 1 символ, а выделение считает его внутри себя - как 2 (\d\n).)

(Наверняка, задача с другими бр-рами в этом плане будет неизмеримо проще.)

Это сообщение отредактировал(а) 12345c - 10.10.2006, 21:54


--------------------
Google Code Playground - онлайн-отладка своих примеров HTML+JS без регистрации, с сохранением по URL, без кириллицы. Go
PM WWW   Вверх
Zeroglif
Дата 10.10.2006, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



Цитата(12345c @  10.10.2006,  07:32 Найти цитируемый пост)
Суть в том, что если выделение текста в Textarea начинается с 1-го символа не 1-й строки, то выделение (selection) "проглатывает" символ переноса строки

Если перенос (\r\n) находится на правом краю текстового диапазона, то он не виден, не считается IE. Мне пришлось это вычислять, если ты видел, в своём скрипте. 

У тебя почти такая же байда, но под другим соусом. Когда курсор стоит в начале второй строки (перед A), то tR (также как и tR2) должны показать длину = 5 (1 плюс 2 плюс 3 плюс \r плюс \n), а мы имеем 3, перенос не учтён, т.к. он у обоих диапазонов с краю. 

Если же мы выделим A, то tR так и останется равным 3, а tR2 уже учтёт перенос правильно, т.к. он у этого диапазона уже не с краю, а вложен внутрь, и учтён IE. Получается разница в 2.

PM MAIL WWW   Вверх
12345c
Дата 11.10.2006, 01:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Zeroglif
Цитата(Zeroglif @  10.10.2006,  22:01 Найти цитируемый пост)
Если перенос (\r\n) находится на правом краю текстового диапазона, то он не виден, 
 - это не вся правда - вся правда в том, как говорится в сказаниях, что не перенос, а переносЫ не видны и игнорируются на правом краю TextRange. Это поразительное явление в самом популярном браузере иллюстрируется не менее поразительным скриптом, который я сделал на базе верхних примеров: http://javascript.aho.ru/example/JsPrimeryCode-97.htm . Берём сумму длин областей, а результаты частенько плавают так, как им заблагорассудится - такое впечатление smile.

PM WWW   Вверх
Zeroglif
Дата 11.10.2006, 09:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



Цитата(12345c @  11.10.2006,  01:59 Найти цитируемый пост)
это не вся правда - вся правда в том, как говорится в сказаниях, что не перенос, а переносЫ не видны и игнорируются на правом краю TextRange


Диапазон отсекает правый крайний перенос, то есть условная правая граница диапазона с точки зрения TextRange.text стоит перед этим ближним переносом. Естесственно, не будет виден ни 2-ой, ни 3-ий, ни энный перенос справа, граница же уже установлена перед самым первым. Результаты твоего теста имхо не плавают, а как раз показывают это весёлое поведение IE. smile

PM MAIL WWW   Вверх
Sardar
Дата 11.10.2006, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 78
Всего: 317



Метод Zeroglif'а с "щупом" для начала и конца строки ИМХО самый действенный, вчера часа два убил что бы перенести на форумские скрипты smile

Споткнулся о селекцию, я её сохраняю как на была. При unindent'е если от курсора до начала строки меньше tab'а, то курсор должен остаться на начале строки и не прыгать на предидущую. Сейчас добью фишку и выложу с обильными коментариями.


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
12345c
Дата 11.10.2006, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Я обошёл нащупывание в большинстве случаев через взятие разности длин двух TextRange, когда работает правильная левая граница. (Для примера, когда нужно взять длину выделенной строки.) В малом числе случаев, когда выделение происходит в сплошных переносах в конце поля ввода, такое простое решение перестаёт работать, и нужно нащупывание символа, отличного от переноса, через moveStart|moveEnd('character',-1). Это реализовано в примере http://javascript.aho.ru/example/JsPrimeryCode-97.htm (дополнил его сейчас) для выполнения вроде бы простенькой задачи - взять длину строки выделенных символов в Textarea. И оно стало работать. Теперь Ctrl+A не даёт чудеса в результате.

Подковавшись в методах определения длин строк, можно возвращаться к основной задаче :). Правда, тебе, Sardar, это сподручнее, а то я там наделаю своего кода.
PM WWW   Вверх
12345c
Дата 12.10.2006, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Вот она, функция вычисления длины любой области TextRange, лежащей в поле textarea:
Код
lenTR=function(oTR,oTa){var ltr; //длина объекта TextRange oTR в области Textarea oTa (IE only)
  var tR=document.body.createTextRange();  tR.moveToElementText(oTa);
  var tR1=tR.duplicate();  tR1.setEndPoint('StartToEnd',oTR);
  var tR2=tR.duplicate();  tR2.setEndPoint('StartToStart',oTR);
  var lenSel=tR2.text.length-tR1.text.length;
  if(tR1.text.length>0||oTa.value.length<=tR.text.length)return lenSel;
  else{
    var lenCorr=0;
    var lenCorr2=0;
    var tR3=oTR.duplicate();
    var i,i0;  i=i0=tR3.text.length;
    while(i>=i0&&tR1.text.length==0){
      if(i==0){tR3.moveStart('character',-1);lenCorr--;lenCorr2=1;}
      tR3.moveEnd('character',-1);
      i=tR3.text.length;
      tR1.setEndPoint('StartToEnd',tR3);
      lenCorr++; //чис. переносов в конце
  };return lenSel+(lenCorr+lenCorr2-1)*2;}
}


Дополнение: выставление и убирание пробелов сделано в IE с помощью написанной функции (конец строки не очень правильно обрабатывается), осталось выставлять выделение. Поскольку при работе с this.iesel появляется новый букет глюков, подумал, что проще будет работать с правильными вычисленными смещениями краёв выделения, но при выставлении выделения требуется перевести его снова в глючный формат (ожидается ради этого новая страница примера). Промежуточный результат в 
http://javascript.aho.ru/files/vingradScripts.rar , где для наглядности пробелы заменены на "@".

Продолжение:
По скрипту остался "последний вздох" - правильно вычислить положение конца области выделения (скрипт для IE). От идеи менять this.iesel, чтобы не переустанавливать границы выделения, пришлось отказаться, потому что глючность всоприятия им краевых переносов строки привела к тому, что сделать корректное изменение не представилось возможным. Вместо этого продолжил подход, сделанный в скрипте "Сборная солянка" (вставка текстов под курсором; её надо поправить тоже в соответствии с этой темой) - вычислить корректные заменители .selectionStart, .selectionEnd в IE и пользоваться реальными строками из .value . При выставлении выделения нужно было учесть очередной глюк (или нестыковку) TextRange, когда он считает, что move() через перенос строки - это 1 символ, когда в коде Textarea их 2 (\r\n).

В http://javascript.aho.ru/files/vingradScripts.rar - обновлённая версия и комметарий того, что функция TextAreaSelectionHelper.prototype.move4p делает. Ещё 1 день - и можно проверять практичность работы.

Окончание для IE: функция для IE работает, можно тестировать юзабельность. Специально проработал начала и концы выделений в разных случаях. Срабатывает по кнопкам в конце списка кнопок над полем ввода под названием Ctrl_[  и Ctrl+], но сочетания клавиш не работают - что-то сломал в скриптах, потому что вначале работали. Вероятно, переустановить в скрипты не должно составить проблемы.

Sardar, доделывать ли дальше или ты сам сделаешь свой вариант? Для себя я задачу решил (могу подробно расписать процесс и полезные выводы здесь), дальше может интересовать, если только будет применяться. Если будет применяться, доделаю скрипт и подробно распишу процесс для всех браузеров.

Это сообщение отредактировал(а) 12345c - 13.10.2006, 01:41


--------------------
Google Code Playground - онлайн-отладка своих примеров HTML+JS без регистрации, с сохранением по URL, без кириллицы. Go
PM WWW   Вверх
pythonwin
Дата 7.11.2006, 06:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2529
Регистрация: 18.4.2006
Где: за компом

Репутация: 1
Всего: 36



потестировал - вроде нормально, но жаль что не работают клавиши (Ctrl+[  и Ctrl+])
+ хорошо бы сделать так чтобы при нажатии Enter в конце строки в новую строку добавлялось столько же пробелов как и у родительской строки. smile

Это сообщение отредактировал(а) pythonwin - 7.11.2006, 07:01
PM WWW GTalk Jabber   Вверх
12345c
Дата 2.12.2006, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Сделана совместимость с остальными бр-рами, просьба проверить в http://forum.vingrad.ru/topic-124918.html . Имеется как файл с внедрённым в скрипты форума кодом, так и демонстрационный пример, который достаточно скопировать в файл для выполнения.
PM WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0525 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.