Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Отмена вставки текста из буффера во фрейм wysiwyg-редактора (https://javascript.ru/forum/misc/5154-otmena-vstavki-teksta-iz-buffera-vo-frejjm-wysiwyg-redaktora.html)

mcfly 21.09.2009 09:05

Отмена вставки текста из буффера во фрейм wysiwyg-редактора
 
Клиент захотел сделать мини-wysiwyg редактор, как в одноклассниках. Все функции я сделал (вставку смайликов, размеры, цвет текста, итп), но осталась одна проблема - когда пользователь вставляет текст из буффера он не очищается.

Висивиг находится в iframe, который потом NewTextArea.document.designMode

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

Прошу помощи, хотя бы, в плане-минимум :)

Заранее благодарствую

B~Vladi 21.09.2009 11:30

Насколько я понял, форматированный текст вставляецо только в ИЕ... Если так, то у него есть инструменты для работы с буфером:

Цитата:

Свойство clipboardData
Синтаксис: window.clipboardData
Изменяемое: нет
Значением свойства clipboardData является объект, обеспечивающий доступ к системному буферу сохранения. Буфер сохранения в Windows поддерживает пять форматов хранения данных, которые в DHTML обозначаются так:

Обозначение Описание
"Text" Текстовый формат
"URL" Формат URI
"File" Файловый формат
"HTML" Формат HTML
"Image" Формат графического образа

Этот объект не имеет свойств и поддерживает следующие методы:

Метод Описание
clearData(формат?) Удаляет заданный формат из буфера сохранения. Если формат не задан, то удаляются все форматы.
getData(формат) Извлекает данные из буфера сохранения заданного формата, который может иметь значение "Text" или "URL", и возвращает их в виде строки.
setData(формат, данные) Помещает в буфер сохранения строку данные в заданном формате, который может иметь значение "Text" или "URL". Возвращает true в случае успеха и false в противном случае.

Пример использования clipboardData для вырезания текста на Веб-странице и вставки его в другое место:

<HTML>
<META http-equiv="Content-Type" content="text/html; charset=windows-1251">
<HEAD>
<SCRIPT>

// Выделяем текст, который следует вырезать
function selectText() {
  var r = document.body.createTextRange();
  r.findText(divSource.innerText);
  r.select();
}
// По умолчанию вырезание текста в IE запрещено. Следующая функция его разрешает.
function enableCut() {
  event.returnValue = false;
}
// По умолчанию вставка из буфера в IE запрещена. Следующая функция его разрешает.
function enablePaste() {
  event.returnValue = false;
}
// Вставляем текст из буфера сохранения и сбрасываем returnValue,
// чтобы отменить реакцию обозревателя по умолчанию.
function pasteText() {
  var r = document.selection.createRange();
  r.text = clipboardData.getData("Text");
}

</SCRIPT>
</HEAD>
<BODY onload="selectText()">
<DIV ID="divSource" onbeforecut="enableCut()">Вырежьте этот текст</DIV>
<DIV onbeforepaste="enablePaste()" onpaste="pasteText()">
  Вставьте текст сюда
</DIV>
</BODY>
</HTML>


mcfly 21.09.2009 12:19

Цитата:

Сообщение от B~Vladi (Сообщение 30530)
Насколько я понял, форматированный текст вставляецо только в ИЕ...

Работа с буфером не желательна, ибо это поддерживает только ИЕ. Надо сделать функционал максимально удобный для пользователя + чтобы работало в пятерке распространенных браузеров.

Мне вот сейчас какой алгоритм пришел в голову:
1. Пользователь вставляет текст
2. Срабатывает событие onbeforepaste
3. Обработчик на этом событии открывает див с текстареа и ставит туда курсор (в данном случае возможно, что текст туда вставиться?)
4. Если текст туда не вставиться автоматом, то в этом окне указать, что нужно тут вставить текст и нажать на ОК
5. ПРи нажатии на ОК скрипт вставляет этот текст в позицию курсора в висивиге

Это оптимальный алгоритм, если не получится в браузерах, кроме ИЕ, автоматом очистить текст и сразу вставить в висивиг

Вот и возникает главный вопрос: Куда указывать обработчик этого события.

Дополнительная инфа:

Поле висивига находится во фрейме: <iframe id='frm' class='editor_iframe'></iframe>

Инициализация висивига:
var NewTextArea={
  frame:{},
  document:{},
  window:{},
  init:function(frame){
    NewTextArea.frame=frames[frame]?frames[frame]:document.getElementById(frame);//IE, Opera - frames.document, другие - ById.document

    if (!NewTextArea.frame){
      //alert("Ошибка ID");
      return -1;
    }

    //1) получить указатель
    NewTextArea.document=NewTextArea.frame.contentDocument || NewTextArea.frame.document;
    if (!NewTextArea.document){
      //alert("Ошибка iframe");
      return -2;
    }

    NewTextArea.window=NewTextArea.frame.contentWindow || NewTextArea.frame.window;
    if (!NewTextArea.window){
      //alert("window");
      return -2;
    }

    //2) Оформить iframe HTML документ
    var HTML = "<html><head></head>";
    HTML += "<body></body></html>"

    NewTextArea.document.open();
    NewTextArea.document.write(HTML);
    NewTextArea.document.close();

    //3) Установить designMode
    if (NewTextArea.document.designMode){
      NewTextArea.document.designMode='on';
    }else{
      alert("Ошибка designMode");
      return -3;
    }
  }
}


Обязательно прописать в боди: <BODY onload="NewTextArea.init('frm');">

Octane 21.09.2009 19:01

В CKEditor не прбовали посмотреть, как работает?

Предположительно в файле _source\plugins\clipboard\plugin.js функция onKey (line #116).

mcfly 22.09.2009 15:00

Цитата:

Сообщение от Octane (Сообщение 30573)
В CKEditor не прбовали посмотреть, как работает?

Там просто обработчик события. А как этот обработчик прописать? Только скажите, плиииз, на моем примере. Просто как сделать так, чтобы хотя бы при вставке текста в поле редактора выполнялось alert("УРААА!!!");

mcfly 22.09.2009 15:37

Нашел на форуме тему тема. Там указано как вешать событие на нажатие кнопки в iframe

Вот это:
var iframe = document.getElementById("идентификатор_фрейма");
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
 
iframeDocument.designMode = "On";
 
iframeDocument.onkeypress = function(e) {
    …
};


Его адаптировал для своего скрипта:
var NewTextArea={
  frame:{},
  document:{},
  window:{},
  init:function(frame){
    NewTextArea.frame=frames[frame]?frames[frame]:document.getElementById(frame);//IE, Opera - frames.document, другие - ById.document

    if (!NewTextArea.frame){
      //alert("Ошибка ID");
      return -1;
    }

    //1) получить указатель
    NewTextArea.document=NewTextArea.frame.contentDocument || NewTextArea.frame.document || NewTextArea.frame.contentWindow.document;
    if (!NewTextArea.document){
      //alert("Ошибка iframe");
      return -2;
    }

    NewTextArea.window=NewTextArea.frame.contentWindow || NewTextArea.frame.window;
    if (!NewTextArea.window){
      //alert("window");
      return -2;
    }

    //2) Оформить iframe HTML документ
    var HTML = "<html><head></head><body>";
    HTML += "</body></html>"

    NewTextArea.document.open();
    NewTextArea.document.write(HTML);
    NewTextArea.document.close();

    //3) Установить designMode
    if (NewTextArea.document.designMode){
      NewTextArea.document.designMode='on';
    }else{
      alert("Ошибка designMode");
      return -3;
    }

    NewTextArea.document.onkeypress = function(e) {
      alert('УРААА!!!');
    };

  }
}


Но все ровно при вводе текста в редактор, "УРААА!!!" не выводится :(

Что я неправильно делаю?

mcfly 23.09.2009 11:30

Вот скрипт. Подскажите, пожалуйста, как указать обработчик события onbeforepast.

Заранее благодарен

B~Vladi 23.09.2009 11:31

Цитата:

Сообщение от mcfly
обработчик события onbeforepast

Такого обработчика нет...

mcfly 23.09.2009 11:43

Цитата:

Сообщение от B~Vladi (Сообщение 30721)
Такого обработчика нет...

В смысле вообще нету или нет для данного случая?

Тогда хотя бы на вставку текста или как минимум на нажатие кнопки клавиатуры

B~Vladi 23.09.2009 11:49

Цитата:

Сообщение от mcfly
В смысле вообще нету или нет для данного случая?

В спецификации DOM обработчика с таким названием нет вообще для любых элементов. В ишаке можно такое реализовать.

Цитата:

Сообщение от mcfly
нажатие кнопки клавиатуры

keypress, keydown.

mcfly 23.09.2009 11:52

Цитата:

Сообщение от B~Vladi (Сообщение 30723)
keypress, keydown.

Хорошо, как повесить событие onkeydown? Только на примере скрипта, ссылку на который я указал выше

B~Vladi 23.09.2009 11:59

NewTextArea.onkeydown=function(){
...
}

Вобщем, как обычно:)
Если фрейм это не схавает, то можно поступить так:
Вещаем событие на body, проверяем цель события (target==NewTextArea) и если совпадает - обрабатываем.

mcfly 23.09.2009 12:03

Цитата:

Сообщение от B~Vladi (Сообщение 30727)
NewTextArea.onkeydown=function(){
...
}

Вобщем, как обычно:)
Если фрейм это не схавает, то можно поступить так:
Вещаем событие на body, проверяем цель события (target==NewTextArea) и если совпадает - обрабатываем.

Хм.. вставил в функцию инициализации:
var NewTextArea={
  frame:{},
  document:{},
  window:{},
  init:function(frame){
    NewTextArea.frame=frames[frame]?frames[frame]:document.getElementById(frame);//IE, Opera - frames.document, другие - ById.document

    if (!NewTextArea.frame){
      //alert("Ошибка ID");
      return -1;
    }

    //1) получить указатель
    NewTextArea.document=NewTextArea.frame.contentDocument || NewTextArea.frame.document || NewTextArea.frame.contentWindow.document;
    if (!NewTextArea.document){
      //alert("Ошибка iframe");
      return -2;
    }

    NewTextArea.window=NewTextArea.frame.contentWindow || NewTextArea.frame.window;
    if (!NewTextArea.window){
      //alert("window");
      return -2;
    }

    //2) Оформить iframe HTML документ
    var HTML = "<html><head>";
    HTML += "</head><body>";
    HTML += "</body></html>"

    NewTextArea.document.open();
    NewTextArea.document.write(HTML);
    NewTextArea.document.close();

    //3) Установить designMode
    if (NewTextArea.document.designMode){
      NewTextArea.document.designMode='on';
    }else{
      alert("Ошибка designMode");
      return -3;
    }

    NewTextArea.onkeydown=function(){
         alert('');
    }
  }
}


Не работает.. или я тупень? :))))

mcfly 23.09.2009 12:04

Надеюсь я не сильно наглею, если попрошу на моем примере попробовать вставить? АТо у меня чтот не получается :(

B~Vladi 23.09.2009 12:16

Цитата:

Сообщение от mcfly
Не работает.. или я тупень?

Или я... у фрейма (HTMLIFrameElement) может и не быть такого события, поэтому я предложил второй вариант... но у body (или window) тоже может не быть такого события... Надо смотреть, а мне лень:)

mcfly 23.09.2009 12:58

Тогда будем ждать неленивых специалистов...

Riim 23.09.2009 13:50

Мы все здесь ленивые).

mcfly 23.09.2009 13:51

Цитата:

Сообщение от Riim (Сообщение 30755)
Мы все здесь ленивые).

Ленитесь отвечать на сложные вопросы, а на легкие вопросы отвечаете для поднятия (само)оценки? :)))

Kolyaj 23.09.2009 14:37

Мы ленимся отвечать людям, которые ленятся сами что-то проверить.

Riim 23.09.2009 14:49

Я отвечаю если вопрос мне самому интересен (раз уж для себя разобрался, то почему бы и не ответить) или если ответ займет не более двух - трех минут.

Цитата:

Сообщение от mcfly
для поднятия (само)оценки

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

mcfly 23.09.2009 15:08

Цитата:

Сообщение от Kolyaj (Сообщение 30760)
Мы ленимся отвечать людям, которые ленятся сами что-то проверить.

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

B~Vladi 23.09.2009 16:02

Цитата:

Сообщение от mcfly
Я уже проделал все, на что мои знания способны.

На фрейм удалось событие повесить?! Как предполагается реагировать при вставке текста из буфера?!

mcfly 23.09.2009 16:12

Цитата:

Сообщение от B~Vladi (Сообщение 30789)
На фрейм удалось событие повесить?! Как предполагается реагировать при вставке текста из буфера?!

Не удалось, так как я не представляю как события вешать на содержимое фрейма

mcfly 23.09.2009 16:16

Тоесть, я представляю как вешаются события на простые элементы дом, но тут фрейм + в designMode :blink:

B~Vladi 23.09.2009 16:29

Цитата:

Сообщение от mcfly
Тоесть, я представляю как вешаются события на простые элементы дом, но тут фрейм + в designMode

Ну и что?! Что смущает?! Это то же DOM-элемент...

Octane 23.09.2009 17:05

В designMode обработчик события можно установить только на document и window фрейма.

mcfly 25.09.2009 00:34

Я тут поковырялся в коде и нашел для хрома, сафари и фф:

//Chrome, Safary
if(NewTextArea.frame.window.document.body.addEventListener)
  NewTextArea.frame.window.document.body.addEventListener('paste', edtPaste, true);
//FF
else if(NewTextArea.frame.contentWindow.document.addEventListener)
  NewTextArea.frame.contentWindow.document.addEventListener("paste", edtPaste, true);


Но для ИЕ и Оперы, так и не нашел.

Есть какие-нибудь у кого-нибудь идеи?

Smoke 13.11.2009 23:53

может быть вот это поможет для ИЕ
else if(NewTextArea.frame.window.document.body.attachEvent)
  NewTextArea.frame.window.document.body.attachEvent("onpaste",edtPaste);


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