TinyMCE с AJAX (панель обновления) никогда не имеет значения - PullRequest
10 голосов
/ 12 мая 2010

Я хотел использовать Rich Text Editor для текстовой области внутри панели обновления.

Я нашел этот пост: http://www.queness.com/post/212/10-jquery-and-non-jquery-javascript-rich-text-editors с помощью этого вопроса: Нужен ASP.Net/MVC Rich Text Editor

Решил использовать TinyMCE, как я использовал его ранее в ситуациях, не связанных с AJAX, и в этом списке говорится, что он совместим с AJAX. Хорошо, я делаю добро tinyMCE.init({ //settings here }); Проверьте его, и он исчезнет после обновления панели обновления. Из этого вопроса я выясняю, что он должен быть в функции page_load, чтобы он запускался даже при асинхронных обратных передачах. Хорошо, сделай это, и панель останется. Однако, при попытке передать значение из моего текстового поля, его текст всегда возвращается пустым, потому что мой валидатор формы всегда говорит: «Вы должны ввести описание», даже когда я ввожу в него текст. Это происходит при первой загрузке страницы и после выполнения асинхронных обратных передач на страницу.

Хорошо, я нахожу это http://www.dallasjclark.com/using-tinymce-with-ajax/ и Не могу опубликовать дважды из одной и той же текстовой области AJAX TinyMCE . Я пытаюсь добавить этот код в функцию загрузки моей страницы сразу после tinyMCE.init. Это нарушает все мои jquery, вызываемые также в page_load после него, и у него все еще остается та же проблема.

Я все еще довольно новичок в написании сценариев на стороне клиента, так что, может быть, мне нужно поместить код в другое место, чем page_load? Не уверен, что посты, на которые я ссылался, не очень понимали, где разместить этот код.

Мой Javascript:

<script type="text/javascript">

var redirectUrl = '<%= redirectUrl %>';

function pageLoad() {

    tinyMCE.init({
        mode: "exact",
        elements: "ctl00_mainContent_tbDescription",
        theme: "advanced",
        plugins: "table,advhr,advimage,iespell,insertdatetime,preview,searchreplace,print,contextmenu,paste,fullscreen",
        theme_advanced_buttons1_add_before: "preview,separator",
        theme_advanced_buttons1: "bold,italic,underline,separator,justifyleft,justifycenter,justifyright, justifyfull,bullist,numlist,undo,redo,link,unlink,separator,styleselect,formatselect",
        theme_advanced_buttons2: "cut,copy,paste,pastetext,pasteword,separator,removeformat,cleanup,charmap,search,replace,separator,iespell,code,fullscreen",
        theme_advanced_buttons2_add_before: "",
        theme_advanced_buttons3: "",
        theme_advanced_toolbar_location: "top",
        theme_advanced_toolbar_align: "left",
        extended_valid_elements: "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
        paste_auto_cleanup_on_paste: true,
        paste_convert_headers_to_strong: true,
        button_tile_map: true
    });

    tinyMCE.triggerSave(false, true);
    tiny_mce_editor = tinyMCE.get('ctl00_mainContent_tbDescription');
    var newData = tiny_mce_editor.getContent();
    tinyMCE.execCommand('mceRemoveControl', false, 'your_textarea_name');

    //QJqueryUI dialog stuff
}</script>

Теперь мой текущий код не имеет tinyMCE.execCommand("mceAddControl",true,'content');, который также должен быть добавлен к одному указанному вопросу. Я попытался добавить его, но, опять же, не знал, куда его поместить, и просто поместить его в page_load, похоже, не дало никакого эффекта.

Управление текстовым полем:

<asp:TextBox ID="tbDescription" runat="server" TextMode="MultiLine" 
                Width="500px" Height="175px"></asp:TextBox><br />

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

Спасибо!

Редактировать: Для дальнейшего разъяснения у меня есть проверка формы на сервере, например:

If tbDescription.Text = "" Or tbDescription.Text Is Nothing Then
        lblDescriptionError.Text = "You must enter a description."
        isError = True
    Else
        lblDescriptionError.Text = ""
    End If

И эта ошибка всегда приводит к отображению сообщения об ошибке.

Edit:

Хорошо, я впадаю в отчаяние, я потратил на это часы. Я наконец нашел то, что я считаю победителем в обмене экспертами, в котором говорится следующее (была часть о кодировании значения в xml, но я пропустил это): http://www.experts -exchange.com / Programming / Languages ​​/ C_Sharp / Q_25059848.html

Для тех, кто хочет использовать tinyMCE с AJAX.Net:

  1. Добавление обработчиков начала / конца к объекту запроса AJAX. Они удаляют элемент управления tinyMCE перед отправкой данных (начало) и воссоздают элемент управления tinyMCE (конец):

    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(function(sender, args) {
        var edID = "<%=this.ClientID%>_rte_tmce"; // the id of your textbox/textarea.
        var ed = tinyMCE.getInstanceById(edID);
      if (ed) {
        tinyMCE.execCommand('mceFocus', false, edID);
        tinyMCE.execCommand('mceRemoveControl', false, edID);
    }
        });
    
      Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function(sender, args) {
         var edID = "<%=this.ClientID%>_rte_tmce";
          var ed = tinyMCE.getInstanceById(edID);
          if (ed) {
        tinyMCE.execCommand('mceAddControl', false, edID);
          }
       });
    
  2. Когда пользователь меняет / размывает элемент управления tinyMCE, мы хотим убедиться, что текстовое поле / текстовое поле обновляется правильно:

       ed.onChange.add(function(ed, l) {
           tinyMCE.triggerSave(true, true);
     });
    

Теперь я попробовал этот код, поместив его в свой собственный тег сценария, поместив запросы начала и конца в их собственные теги сценария и поместив ed.onChange в page_load, поместив все в page_load и поместив все 3 в него. собственный скрипт тега. Во всех случаях это никогда не работало, и даже иногда нарушало jquery, который также находится в моей page_load ... (и да, я изменил приведенный выше код, чтобы соответствовать моей странице)

Может кто-нибудь заставить это работать или предложить решение?

код

Ответы [ 5 ]

3 голосов
/ 04 ноября 2011

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

Я занимаюсь разработкой приложения веб-форм ASP.NET, и на одной из страниц есть элемент управления textarea, содержащийся в UpdatePanel. tinyMCE связывается с этой текстовой областью. Текст для текстовой области поступает из связанного текстового поля в элементе управления повторителя, потому что я хочу получить текст из элемента управления ObjectDataSource, и это немного хитрый способ сделать это. На мой взгляд, элементы управления ObjectDataSource удобны и быстро выполняются.

Вот моя разметка, содержащая элемент управления ObjectDataSource, повторитель, ограниченное текстовое поле и текстовое поле (asp: TextBox установлен на многострочное). Обратите внимание, что для связанного текстового поля установлено значение «display: none»:

<asp:ObjectDataSource ID="odsDetailText" runat="server" TypeName="Data.Document" SelectMethod="GetDocumentDetailText" />
<asp:Repeater ID="repBody" runat="server" DataSourceID="odsDetailText">
    <ItemTemplate>
        <asp:TextBox ID="tbxBodyBound" runat="server" Text='<%# Eval("Body") %>' CssClass="hidden" />
    </ItemTemplate>
</asp:Repeater>
<asp:TextBox ID="tbxBody" runat="server" TextMode="MultiLine" />

У меня также есть кнопка asp: для сохранения текста в tinyMCE на SQL Server. Все эти элементы управления содержатся в UpdatePanel.

Я поместил весь свой код jQuery и JavaScript в отдельный файл. Я включаю соответствующие биты ниже. Как обзор:

  • Я инициализирую tinyMCE в событии JavaScript pageLoad. Обратите внимание, что это событие запускается для полной и частичной (асинхронной) обратной передачи, поэтому tinyMCE всегда отображается и не исчезает между полной или частичной обратной передачей.

  • Также в событии pageLoad, если постбэк является асинхронным, я начинаю прослушивать событие BeginRequest, вызванное ASP.NET PageRequestManager. Я прекращаю прослушивать событие BeginRequest в событии JavaScript pageUnload. Это предотвращает добавление все большего числа слушателей при каждом срабатывании pageLoad.

  • Когда срабатывает обработчик события BeginRequest (когда нажата кнопка «Сохранить» на моей странице), я получаю HTML-содержимое текстового редактора tinyMCE и сохраняю его в файле cookie. Для этого я использую плагин cookie jQuery: https://github.com/carhartl/jquery-cookie. Для безопасности HTML-код зашифрован в cookie.

  • Теперь в коде сервера, который выполняется при нажатии кнопки «Сохранить», текст файла cookie (в кодировке HTML) извлекается и сохраняется на сервере SQL. Файл cookie теперь удален.

  • ASP.NET связывает сохраненные данные со скрытым textobx через элемент управления ObjectDataSource, значение элемента управления textarea устанавливается на скрытые текстовые поля, а часть страницы в UpdatePanel отображается обратно в браузере. 1032 *

  • tinyMCE теперь отображает этот текст из текстовой области, но он закодирован в формате HTML и не предназначен для чтения человеком.

  • Итак, в событии JavaScript pageLoad я форматирую текст tinyMCE, расшифровывая HTML.

  • Работа выполнена!

Вот соответствующие части моего файла сценария:

// #########################################################
// Events
// #########################################################
// ---------------------------------------------------------
// Check for full and partial postbacks
// ---------------------------------------------------------
function pageLoad(sender, args) {

    // Register event handler for async postback beginning
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    if (!prm.get_isInAsyncPostBack()) {
        prm.add_beginRequest(onBeginRequest);
    };

    // Configure HTML editor
    HTMLEditorConfig();

    // Format HTML editor text
    HTMLEditorFormat();
};

// ---------------------------------------------------------
// When page unloads after full or partial postback
// ---------------------------------------------------------
function pageUnload(sender, args) {

    // Deregister event handler for async postback beginning
    Sys.WebForms.PageRequestManager.getInstance().remove_beginRequest(onBeginRequest);
};

// ---------------------------------------------------------
// Event handler for async postback beginning
// ---------------------------------------------------------
function onBeginRequest() {

    // Check whether to save text editor text
    HTMLEditorSave();
};

// #########################################################
// Functions
// #########################################################
// ---------------------------------------------------------
// Configure HTML text editor. tinyMCE converts standard textarea controls
// ---------------------------------------------------------
function HTMLEditorConfig() {

    // Determine edit mode
    var editMode = $('input:hidden[id*=hfEditMode]').val().toLowerCase();

    // If not in edit mode, prevent edits
    var editorReadOnly = null;
    var editorHeight = null;
    if (editMode == 'true') {
        editorReadOnly = '';
        editorHeight = '332';
    } else {
        editorReadOnly = 'true';
        editorHeight = '342';
    };

    // Initialise HTML text editor
    tinyMCE.init({
        mode: "textareas",
        plugins: "advhr,insertdatetime,print,preview,fullscreen",
        width: "488",
        height: editorHeight,

        // Theme options
        theme: "advanced",
        theme_advanced_buttons1: "newdocument,|,print,preview,|,cut,copy,paste,|,undo,redo,removeformat,|,bold,italic,underline,strikethrough,sub,sup,|,forecolor,backcolor",
        theme_advanced_buttons2: "justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,|,fontselect,fontsizeselect",
        theme_advanced_buttons3: "insertdate,inserttime,|,advhr,|,charmap,|,fullscreen",
        theme_advanced_toolbar_location: "top",
        theme_advanced_toolbar_align: "left",
        theme_advanced_statusbar_location: "none",
        theme_advanced_resizing: false,

        // Skin options
        skin: "o2k7",
        skin_variant: "silver",

        // Custom css
        content_css: "../../Script/tiny_mce/custom.css",

        // Allow edits?
        readonly: editorReadOnly
    });
};

// ---------------------------------------------------------
// Format HTML editor text by ensuring its HTML is decoded
// ---------------------------------------------------------
function HTMLEditorFormat() {

    // Check bound textbox containing HTML for text editor
    var bodyText = $('input:text[id*=tbxBody]').val();

    // If HTML exists, decode it
    if (bodyText !== null) {
        tinyMCE.activeEditor.setContent(decodeURIComponent(bodyText));
    };
};

// ---------------------------------------------------------
// Save HTML text editor text to cookie for server-side processing.
// Can't save to hidden field or asp control as this function fires after viewstate is captured (I think).
// Extra content in viewstate would slow down page load anyway.
// ---------------------------------------------------------
function HTMLEditorSave() {

    // Determine edit mode
    var editMode = $('input:hidden[id*=hfEditMode]').val().toLowerCase();

    // If in edit mode, create cookie with encoded text editor HTML. Server code will save this to database.
    if (editMode == 'true') {
        var textToSave = tinyMCE.activeEditor.getContent();
        $.cookie('HTMLEditorText', textToSave);
    }
};

Вот часть кода сервера, которая срабатывает при нажатии кнопки Сохранить:

Private Sub Save()

    'Retrieve tinyMCE text from cookie
    Dim cookieName As String = "tinyMCEText"
    Dim cookies As HttpCookieCollection = Request.Cookies
    Dim text As String = cookies(cookieName).Value

    'Save text to database...

    'Delete cookie
    cookies.Remove(cookieName)

    'Databind text for tinyMCE
    repeaterTinyMCE.DataBind()
    Dim encodedText As String = DirectCast(repeaterTinyMCE.Controls(0).Controls(1), TextBox).Text
    textboxTinyMCE.Text = encodedText
End Sub

Надеюсь, это кому-нибудь поможет.

2 голосов
/ 13 мая 2010

Я думаю, что вы хотите посмотреть на это сообщение: Как заставить TinyMCE работать внутри UpdatePanel?

Обязательно зарегистрируйте функцию init с scriptmanager

ScriptManager.RegisterStartupScript(this.Page, 
         this.Page.GetType(), mce.ClientID, "pageLoad();", true);
1 голос
/ 17 августа 2010

Вы должны активировать функцию сохранения при отправке назад, используйте Page.RegisterOnSubmitStatement, чтобы зарегистрировать скрипт tinyMCE.triggerSave();

Я заметил, что функция tinyMCE init может вызываться только для выбора всех текстовых полей или текстовых полей определенного класса. exact не работает.

0 голосов
/ 26 мая 2010

Одна вещь, с которой я столкнулся, когда помещал TinyMCE в панель обновлений, заключалась в том, что мне пришлось делать всевозможные трюки, чтобы все работало правильно. Имейте в виду, как работает панель обновления, когда вы хотите обновить ее, она полностью заменяет DOM внутри нее, включая TinyMCE.

Обходной путь, который я использовал, заключался в том, чтобы удалить TinyMCE с панели обновлений и обернуть все, что нужно для динамического обновления на панели обновлений. Затем я добавил бы данные в TinyMCE через API javascript, который он предоставляет, если мне нужно, чтобы содержимое TinyMCE было динамичным.

0 голосов
/ 26 мая 2010

Ну, у меня было два способа заставить это работать, но это не помогло решить проблему, просто избегайте ее.

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

...