Подсветка синтаксиса в textarea
Добрый вечер!
Весь день ломаю себе голову над вопросом - как сделать такую "textarea", чтобы при введении кода он автоматом подсвечивался (по типу нотпада++ или типа того) Попробовал пойти по такому пути: <div contenteditable="true" class="redactor" id="content_textarea"></div> <textarea name="content" id="textarea_form"> var content_textarea = $('#content_textarea'); content_textarea.keyup(function(){ var string = content_textarea.html(); var reg = /<(.*?)>/ string = string.replace(reg,'<span style="color:blue;"><$1></span>'); content_textarea.html(string); Но получилась фигня :( У кого есть опыт в чём-то подобном, подскажите по какому пути нужно идти? |
BravoTwo,
Можно техтареа с позицией relative вынести z-index(ом) вперёд и скрыть visibility:hidden, а ниже расположить div cчитывающий по oninput значения из техареа и организующий подсветку. Сложность в позиционировании некого <span> по данному div иммитируюший текущую позицию курсора. |
Deff, спасибо за совет! я сейчас переписал код немного, но с курсором проблема. Может можно с этим что-то сделать? Как только текст подсвечивается, каретку магнитит в самое начало :(
Что можно сделать с этим? СЕйчас код выглядит так: var content_textarea = $('#content_textarea'); var textarea_form = $('#textarea_form'); content_textarea.keyup(function(){ textarea_form.html(content_textarea.text()); var string = textarea_form.html(); string = string.replace(/(".*?"|'.*?')/g, '<span class="green">$1</span>') // замена всех строк, обернутых в одинарные и двойные кавычки .replace(/(<[a-z]+)(.*?)(\s*\/?>)/gi, '<span class="blue">$1</span>$2<span class="blue">$3</span>') // обработка HTML-тегов .replace(/(<\/?[a-z]+>)/gi, '<span class="blue">$1</span>'); // обработка HTML-тегов (закрывающих) content_textarea.html(string); |
BravoTwo,
Ну от определения текущей позиции курсора в textarea - никуда не деться, а зная в в textarea , просто и её восстановить, после отображения в div и выдать аозицию для span - аналога... Вообще куча WYSIWYG в инете http://habrahabr.ru/search/?q=%5Bwys...get_type=posts |
я сейчас пишу для себя подсветку избавился от проблемы переноса в начало помощью работы с range объектом. а текст разбивал регулярными выражениями.есть неровности но если хочешь можем списаться для обмена наработками
|
jsbot, тот код,который выше хорошо подсвечивает код. единственное - проблему с кареткой щас пытаюсь решить. сижу, курю сайты всякие по теме. пока нихера не понятно :)
как разберусь - отпишусь здесь. |
var yakor=document.createElement('span'); yakor.setAttribute("name","koretka"); yakor.id="yakor"; if (document.getSelection) { var sel=document.getSelection().getRangeAt(0); html_tag=document.getSelection().anchorNode; do { html_tag=html_tag.parentElement; } while((html_tag.tagName!="DIV")/*&&((html_tag.name=="stroka")||(html_tag.class=="kod"))*/); if($.browser.mozilla) { sel.insertNode(yakor); } else { var rangeObj = document.createDocumentFragment(); rangeObj.appendChild(yakor); sel.isertNode(rangeObj); } } else if (document.selection) { Gavno = true; var selectedText=document.createRange(); selectedText.pasteHTML(yakor); selectedText.anchorNode; } ---------------------------------------------------------- var MyText = $(this).html(); MyText=MyText.replace(/<span id="yakor" name="koretka"><\/span>/gi,' ↔'); MyText=MyText.replace(/(<span class="koment">|<\/span>|<span class="oper">|<span>|<div onkeyup="Syntex(event.keyCode,this)|<\/div>">)/gi,''); --------------------------------------------------------------- txt=txt.replace(/↔/gi,'<span id="yakor" name="koretka"><\/span> '); $(this).html(txt); }); } var koretka = document.getElementsByName("koretka")[0]; if ( document.createRange ) { rng = document.createRange(); rng.selectNode(koretka); sel = document.getSelection(); sel.removeAllRanges(); sel.addRange( rng ); } else { var rng = document.body.createTextRange(); rng.moveToElementText(koretka); rng.select(); } извиняюсь за низкое качество я начинающий ,советы по оптимизации очень принимаются. |
этот код корректно работает?(проверить не смогу сегодня, ибо баиньки)
я пока добился того, что каретка в конец магнитится теперь. всё бы ничего, но текст в середине не исправить. п.с. Gavno = true; - воодушевляет)) ппс Пока не лёг. вот что у мя пока есть: $.fn.focusEnd = function() { $(this).focus(); var tmp = $('<span />').appendTo($(this)), node = tmp.get(0), range = null, sel = null; if (document.selection) { range = document.body.createTextRange(); range.moveToElementText(node); range.select(); } else if (window.getSelection) { range = document.createRange(); range.selectNode(node); sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } tmp.remove(); return this; } $(function(){ var content_textarea = $('#content_textarea'); var textarea_form = $('#textarea_form'); content_textarea.keyup(function(){ textarea_form.html(content_textarea.text()); var string = textarea_form.html(); string = string.replace(/(".*?"|'.*?')/g, '<span class="green">$1</span>') // замена всех строк, обернутых в одинарные и двойные кавычки .replace(/(<[a-z]+)(.*?)(\s*\/?>)/gi, '<span class="blue">$1</span>$2<span class="blue">$3</span>') // обработка HTML-тегов .replace(/(<\/?[a-z]+>)/gi, '<span class="blue">$1</span>'); // обработка HTML-тегов (закрывающих) content_textarea.html(string).focusEnd; }); }); |
BravoTwo,
Я давал полную библиотеку (там есть ф-ия bbcode()) bbcode('[выделенный текст]','[/выделенный текст]') , - исправляешь в тегах, затем теги убираешь .replace(/\[?\/выделенный текст\]/ig,'') |
BravoTwo, готовые решения не устраивают?
|
danik.js, спасибо за ссылку! пригодится для изучения, но хотелось бы свой велосипед состряпать (а главное понять как он работает) в целях набивания опыта. Тема интересная и для меня сложная достаточно, так что это уже дело принципа :)
|
Если вкратце, то редактор состоит из следующих составляющих:
1) Элемент ввода-вывода текста. Как правило это невидимая textarea, которой и принадлежит фокус ввода, и которая подставляется под мышку при правом клике. Все изменения содержимого отлавливаются редактором и отражаются в области отображения кода. Впринципе, вместо текстарии можно использовать div.contenteditable для всего редактора и либо ставить курсор в невидимый элемент и эмулировать его через какойнибудь span, либо оставить реальным. Однако тут будут проблемы с firefox, так как он не позволяет отлавливать копирование/вставку текста. Плюс много других проблем. 2) Область отображения текста. Тут все довольно просто, если не нужно особой производительности. Имеем кучу div-ов - каждый div представляет собой строку. В нем уже идут span-ы, представляющие собой токены. Все изменения содержимого редактора отражаются тут. Для больших документов используется хитрый трюк - создаются div-ы только для видимых в данный момент элементов, а при прокрутке они меняются, создается впечатление прокрутки. При этом скроллбар выносится в отдельный элемент. Прокрутка колесом мыши полностью управляется редактором. 3) область подсветки выделенного текста, и других выделений. Тоесть тут отображаем фэйковое выделение. Внутри же редактор это обычно: Selection - отвечает за выделение Tokenizer - обычно работает в отдельном потоке как webworker, чтоб не тормозить UI. Берет набор правил ввиде массива состояний и регулярок. Запоминает начальные состяния каждой строки, чтоб при изменении пере-размечать текст начиная с измененной линии, а не с начала. Должен уметь прерываться, чтоб при частом изменении документа не выполнять лишнюю работу. UndoManager - запоминает изменения. В хорошей реализации держит в памяти только дельты, то-есть разницы, а не целиком тексты CommandManager - набор команд и управление ими. Часто даже элементарные действия как перемещение курсора стрелкой также хранятся и управляются тут же. Как я помню, CodeMirror изначально работал на iframe+designMode, имел натуральный курсор и выделение. (прошлый век) Потом стал использоваться contenteditable. (много проблем, особенно из-за FireFox) Затем если не ошибаюсь - textarea для ввода + имитация выделения и курсора. (самый эффективный способ, хотя и тут есть куча недостатков) Я не рекомендую CodeMirror для изучения, хотя он проще чем Ace. Дело в том что в нем все свалено в одну кучу, в один файл. Код не особо читабелен. Разработчик одно время считал что это улучшает производительность (я про один файл, а не читабельность) В Ace все сделано очень грамотно и красиво (местами не очень), рекомендую для изучения исходников. Хотя реализация достаточно сложная (в угоду производительности и функциональности) Кстати, ща работаю над расширением для Chrome, которое позволит заменять на сайтах текстарии редактором (Ace). Например на этом сайте будет удобно писать куски кода на javascript. Можно сказать, будет встроенный Sublime Text в браузер, причем на любом желаемом сайте. |
Занимаюсь примерно тем же. Проблемы с курсором решил так. В Опере цвет текста в textarea делаю transparent т.е прозрачный . Текст не виден зато курсор маячит. А хроме и фире opacity:0.3; Правда надо с позиционировать текст в textarea и div так чтоб полупрозрачный текст не был виден.
p.s У меня проблемы с выводом номера строки.Может есть какие решения? |
Кажется в EditArea используется подобный подход - отображается прозрачная textarea + подсветка другим слоем. Для небольших документов такой подход сгодится.
Может окажется полезным: http://en.wikipedia.org/wiki/Compari...e_code_editors |
Часовой пояс GMT +3, время: 10:03. |