Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 22.12.2009, 07:38
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

doc.designMode = 'Oon';
Как правильно 'on' или 'On' (большая "O")? Вроде и так и так работает.
Ответить с цитированием
  #2 (permalink)  
Старый 22.12.2009, 13:43
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Вроде бы для старых версий Gecko нужно было писать On/Off.

Тут с заглавной буквы пишут: "xbDesignMode a JavaScript helper class for easier cross-browser development using designMode".

В общем, лучше потестить самостоятельно потому что в MDC-документе 2005 года уже со строчной буквы написано, а в документе 2003 года и в MSDN с заглавной.

Последний раз редактировалось Octane, 22.12.2009 в 14:02.
Ответить с цитированием
  #3 (permalink)  
Старый 23.12.2009, 04:59
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Octane, спасибо. Вот еще здесь нашел:
var isGecko = navigator.userAgent.toLowerCase().indexOf("gecko") != -1;
iDoc.designMode = (isGecko) ? "on" : "On";


Только определение Gecko зацепляет и WebKit, но тем браузерам, которые на WebKit работают, похоже все равно 'on' или 'On'. Пока у себя буду делать почти также:
var isGecko = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') < 0;
iDoc.designMode = isGecko ? 'on' : 'On';


Определение Gecko из PrototypeJs взял. Позже, когда буду тестировать в более старых браузерах, если при таком способе что-нибудь вылезет, отпишусь здесь.
Ответить с цитированием
  #4 (permalink)  
Старый 23.12.2009, 05:45
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

А как получить только текст из WYSIWYG-а?

Я сейчас так делаю:
сначала удаляю все теги:
html = doc.body.innerHTML.replace(/<\/?[^>]+>/g, '');


потом заменяю все спецобозначения (&nbsp; ....) на нормальные символы:

var div = document.createElement('div');
div.innerHTML = html;
return div.firstChild ? div.firstChild.nodeValue : '';

.

Так нормально? Может я забыл что-то или проще можно сделать?
Ответить с цитированием
  #5 (permalink)  
Старый 23.12.2009, 11:27
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

txt = doc.body.innerText || doc.body.textContent

?
Ответить с цитированием
  #6 (permalink)  
Старый 24.12.2009, 03:18
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Octane
txt = doc.body.innerText || doc.body.textContent

?
Вроде подойдет, спасибо.
Ответить с цитированием
  #7 (permalink)  
Старый 24.12.2009, 07:09
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

В общем ситуация такая: есть wysiwyg, пользователь печатает в нем, и как только в тексте появляются какие-то определенные конструкции, их нужно подсвечивать. Я сначала хотел менять body.innerHTML , но наверно не получится т. к. при любом его изменении выделение с wysiwyg-а теряется и непонятно как его вернуть обратно (там просто много всяких тегов появляется при изменении innerHTML и они сильно мешают найти места начала и конца пропавшего выделения). Можно еще создавать Range объект и используя его метод surroundContents подсвечивать то, что нужно, но перед этим нужно удалить все предыдущие подсветки (текст постоянно меняется, какие-то подсветки должны появляться, другие исчезать, нужно просто при каждом mouseup все чистить и расцвечивать заново), непонятно как все очистить от тегов если нельзя трогать innerHTML. Есть вариант выделить все:
var r = iDoc.createRange();
r.selectNodeContents(iDoc.body);
var sel = regExpTextWin.getSelection();
sel.removeAllRanges();
sel.addRange(r);


и используя execCommand все очистить:
iDoc.execCommand('RemoveFormat', false, '');


, но опять же нужно как-то обратно вернуть выделение.

Такое ощущение что я велик изобретаю.
Octane, подскажи, пожалуйста, как все это надо делать.

Последний раз редактировалось Riim, 24.12.2009 в 07:12.
Ответить с цитированием
  #8 (permalink)  
Старый 24.12.2009, 14:45
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Эх… достать бы коды старой версии Etherpad, там в реальном времени подсветка синтаксиса в WYSIWYG работала и не тормозила.

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

1. Рекурсивно проходил по всему дереву или отдельной его ветке и запоминал ссылки на все непустые текстовые узлы, собирал со всех их inline-родителей computedStyle, вытаскивал из него только поддерживаемые редактором стили, получался двумерный массив объектов:
[
    [
        {node: textNode, style: {color: "#f00", "font-weight": bold}},
        {node: textNode, style: {…}},
        {node: textNode, style: {…}},
    ],
    [
        {node: textNode, style: {…}},
        …
    ]
]

из такого кода:
<div>
    text1
    <ul>
        <li>text2</li>
        <li>text3</li>
    </ul>
    text4<b>text5</b>text6
</div>

получался вот такой массив:
[
    [{node:  text1, style: {}}],
    [{node:  text2, style: {}}],
    [{node:  text3, style: {}}],
    [{node:  text4, style: {}}, {node:  text5, style: {}}, {node:  text6, style: {}}]

]

При первом проходе блочные элементы трогать не будем, оптимизация затрагивает только текстовые узлы и inline-элементы, поэтому и получаем двумерный массив, как бы уменьшаем многомерность задачи.
Внутри какого блока проводить оптимизацию, определяем с помощью range.getAncestorContainer/parentElement, чтобы всегда весь document.body не перестраивать.
Там правда еще много возни было с приведением значений стилей к единому виду, например font-weight может быть bold, 400 или 900, Opera возвращает некоторые значения в кавычках…

2. С помощью конечного автомата, на основе собранных стилей, собираем новый HTML-код (сводим многомерный алгоритм к линейному), проводя объединение одинаковых стилей, создавая <span style="…"> вместо невалидных <U> и т.д. Должен получится одномерный массив кусков HTML-кода.

3. Заменяем старые узлы на новые, полученные из кусочков HTML-кода. Использовать innerHTML не получится, так как, например, для верхнего div, заменив 1-й участок (text1), мы потеряем все остальные, поэтому создаем функцию:
var parseHTML = function () {
    var node = document.createElement("div"); // тут дорога каждая миллисекунда
    var fragment = document.createDocumentFragment(); // узлы будут переносится в дерево
    return function (htmlCode) {
        node.innerHTML = htmlCode;
        while (node.firstChild) fragment.appendChild(node.firstChild);
        return fragment;
    };
}();

Например, заменяем отрезок, полученный из text4–text6: для этого нужно получить самого верхнего inline-родителя узла text4 (если такого нет, то берем сам узел text4), вставить перед ним новый fragment, а затем удаляем все ненужные старые узлы text4–text6 и их inline-родителей.

Вот так вот громоздко и сложно, но эффективно Оптимизировать блочные элементы можно регулярными выражениями.

Возвращать курсор (каретку) в нужное место лучше всего следующим образом:
1. Так как мы уничтожаем старые узлы, то никакой связи с range-объетакми не остается и они нам не помогут, поэтому просто при помощи execCommand вставляем на месте каретки <font face="fake"> (потому что работает везде).
2. Заменяем <font face="fake"> на какой-нибудь элемент с классом.
3. В алгоритме, описанном выше, делаем специальные условия, чтобы этот узел со специальным классом остался в нужном месте.
4. После преобразования кода, находим этот элемент, ставим курсор в него selectNodeContent/moveToElementText.
5. Сдвигаем курсор setStart/moveStart.
6. Удаляем служебный элемент.

В твоей задаче конечный автомат, собирающий новый HTML-код, должен еще и подсвечивать необходимые слова. Но ведь они могут быть "разорваны" на несколько текстовых узлов. Вот с этим хз что делать. Наверное, тогда не в конечном автомате это делать, а сначала оптимизировать код, потом найти эти слова и обернуть в теги для подсветки. Хотя тоже не факт, что пол слова как-нибудь не оформлено по другому было… В общем писать модуль поиска слов мне не досталось, но знаю, что там ппц)))

В IE множественные выделения не работают, поэтому только тегами получится подсвечивать. Разрывать части слов (текстовых узлов) опять же удобнее с помощью execCommand("fontFace", "fake"), предварительно выделив область.

Исходников не осталось, да показывать я их не в праве бы был, проект коммерческий был со всеми вытекающими, хотя он вроде так и не вышел)

Последний раз редактировалось Octane, 24.12.2009 в 14:54.
Ответить с цитированием
  #9 (permalink)  
Старый 17.01.2010, 11:39
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Octane
Возвращать курсор (каретку) в нужное место лучше всего следующим образом: .... 6. Удаляем служебный элемент.
Спасибо, с этой идеей все получилось.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск