2009-02-13 6 views
13

J'essaye de faire quelque chose que beaucoup de gens semblent avoir pu faire mais que je suis incapable de mettre en application n'importe quelle solution. Le contrôle TinyMCE fonctionne plutôt bien dans un formulaire asp.net jusqu'à ce que vous le fermiez avec un UpdatePanel, qui se brise ensuite après la publication. J'ai essayé quelques corrections comme la méthode RegisterClientScriptBlock, mais échoue toujours, je perds toujours le contrôle tinyMCE après la publication. Ci-dessous est un projet de test complet (VS 2008) fourni avec un contrôle en dehors de UpdatePanel et un à l'intérieur, avec un bouton sur chacun pour générer une publication. Aussi dans le projet j'ai un contrôle EditorTest qui inclut le code commenté de certains appels que j'ai essayés, au cas où cela donnerait des idées à n'importe qui.Comment faire fonctionner TinyMCE dans un UpdatePanel?

CODE SAMPLE

Voici quelques sources pour des solutions sur le forum MCE:
AJAX
UpdatePanel

Répondre

-2

TinyMCE (ainsi que d'autres éditeurs WYSIWYG, FCKEditor, etc.) souffre de problèmes de validation de publication. Par défaut, toute page ASP.Net sur la publication a son contenu vérifié, et tout code HTML non codé renvoie l'erreur de validation de publication. Maintenant, beaucoup de gens, y compris sur ces forums suggèrent de désactiver la validation de publication, validaterequest = "false", mais cela vous rend vulnérable aux attaques de scripts, la meilleure chose à faire est de lier une fonction à l'événement de publication asynchrone juste avant la publication asynchrone. Cette fonction JavaScript doit coder en HTML les données TinyMCE renvoyées au serveur, cela passera ensuite la validation de publication et vous serez OK. Je pense que TinyMCE et d'autres éditeurs le font correctement sur les publications, mais pas sur les publications asynchrones, d'où le problème. En fait, si vous regardez la source de TinyMCE, vous trouverez probablement leur fonction et ajoutez simplement la liaison d'événements.

Hope this helps

+0

Cela n'a rien à voir avec mon problème où mes postbacks travaillent, il est la mise en page de tinyMCE que ne reconstruit pas. L'encodage de la balise <> corrige le problème de validationRequest et je l'ai déjà fait. L'exemple de code fourni n'inclut pas de telles erreurs. –

0

Vous devez appeler la méthode d'initialisation du TinyMCE chaque fois que le panneau de mise à jour est actualisée.

Pour cela, vous devez soit appeler cette méthode (tinyMCE.init) à partir d'une méthode RegisterStartupScript, ou pour créer une fonction javascript chargement de la page dans la section de la tête de la page comme ceci:

function pageLoad() { 
    tinyMCE.init(); 
} 

Cette La fonction sera exécutée chaque fois que le panneau de mise à jour est actualisé.

4

Ok, votre problème est double.Stefy vous a fourni une partie de la réponse, qui est que vous devez initialiser TinyMCE sur le postback en vous inscrivant script de démarrage comme ceci:

using System.Web.UI; 

namespace TinyMCEProblemDemo 
{ 
    public partial class EditorClean : UserControl 
    { 
     protected void Page_Load(object sender, System.EventArgs e) 
     {     
       ScriptManager.RegisterStartupScript(this.Page, 
        this.Page.GetType(), mce.ClientID, "callInt" + mce.ClientID + "();", true); 
     } 
    } 
} 

Le deuxième problème que vous avez est avec votre mise en œuvre d'un contrôle personnalisé. La conception de contrôles personnalisés est hors de portée de cette réponse. Google peut vous aider là-bas.

Vous avez plusieurs instances de votre contrôle sur la page qui peuvent vous causer des problèmes avec le script, car il est rendu plusieurs fois. Voici comment je l'ai modifié votre balisage pour résoudre votre problème (notez nommage dynamique de vos fonctions de script, les contrôles personnalisés doivent être autonomes et le mode: « exact » sur le tinyMCE.init):

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EditorClean.ascx.cs" 
    Inherits="TinyMCEProblemDemo.EditorClean" %> 
<script type="text/javascript" src="Editor/tiny_mce.js"></script> 

<script type="text/javascript"> 
    function myCustomCleanup<%= mce.ClientID%>(type, value) { 
     if (type == "insert_to_editor") { 
      value = value.replace(/&lt;/gi, "<"); 
      value = value.replace(/&gt;/gi, ">"); 
     } 
     return value; 
    } 
    function myCustomSaveContent<%= mce.ClientID%>(element_id, html, body) { 
     html = html.replace(/</gi, "&lt;"); 
     html = html.replace(/>/gi, "&gt;"); 
     return html; 
    } 

    function callInt<%= mce.ClientID%>() { 

     tinyMCE.init({ 
      mode: "exact", 
      elements: "<%= mce.ClientID%>", 
      theme: "advanced", 
      skin: "o2k7", 
      plugins: "inlinepopups,paste,safari", 
      theme_advanced_buttons1: "fontselect,fontsizeselect,|,forecolor,backcolor,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,blockquote,|,cut,copy,paste,pastetext,pasteword", 
      theme_advanced_buttons2: "", 
      theme_advanced_buttons3: "", 
      theme_advanced_toolbar_location: "top", 
      theme_advanced_toolbar_align: "left", 
      cleanup_callback: "myCustomCleanup<%= mce.ClientID%>", 
      save_callback: "myCustomSaveContent<%= mce.ClientID%>" 
     }); 
    } 
</script> 
<textarea runat="server" id="mce" name="editor" cols="50" rows="15">Enter your text here...</textarea> 
+0

Est-ce que ma réponse a résolu votre problème? –

+1

Vous ne pouvez pas utiliser le 'mode'" exact ", il ne fonctionne pas correctement dans un UpdatePanel. Vous pouvez utiliser 'textareas' ou' class selector' à la place. Et pour moi le 'save_callback' était assez bogué, à la place j'ai utilisé' RegisterOnSubmitStatement' pour appeler 'tinyMCE.triggerSave()'. Cela fonctionne très bien pour moi. – BrunoLM

+1

J'ai utilisé le mode exact dans UpdatePanels sans problème, les exigences de chacun et les détails d'implémentation sont différents. –

1

Je l'ai fait ce qui suit :

d'abord, j'ajouté le Javascript ce à ma page:

<script type="text/javascript"> 
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler); 

function endRequestHandler(sender,args) 
{ 
    tinyMCE.idCounter=0; 
    tinyMCE.execCommand('mceAddControl',false,'htmlContent'); 
} 

function UpdateTextArea() 
{ 
    tinyMCE.triggerSave(false,true); 
} 
</script> 

Parce que je suis la création d'un ASP.NET et à l'aide et Button ASP.NET dans ma page, je devais ajouter ce qui suit à la Charge de page:

protected void Page_Load(object sender, EventArgs e) 
{ 
    Button1.Attributes.Add("onclick", "UpdateTextArea()"); 
} 
2

La bonne façon de rendre le travail de tinyMCE dans un UpdatePanel:

1) Créer un gestionnaire pour l'OnClientClick de votre bouton « Soumettre ».

2) Exécutez tinyMCE.execCommand ("mceRemoveControl", false, '<% = txtMCE.ClientID%>'); dans le gestionnaire, de manière à supprimer l'instance tinyMCE avant la publication.

3) Dans votre publication asynchrone, utilisez ScriptManager.RegisterStartupScript pour exécuter tinyMCE.execCommand ("mceAddControl", true, '<% = txtMCE.ClientID%>');

Fondamentalement, tout ce que vous devez faire est d'utiliser la commande mceRemoveControl avant la publication asynchrone et d'enregistrer un script de démarrage pour exécuter la commande mceAddControl après la publication asynchrone. Pas trop dur.

12

Pour exécuter la init chaque fois que les UpdatePanel changements que vous devez enregistrer le script en utilisant ScriptManager:

// control is your UpdatePanel 
ScriptManager.RegisterStartupScript(control, control.GetType(), control.UniqueID, "your_tinymce_initfunc();", true); 

REMARQUE: Vous ne pouvez pas utiliser le mode exact sur votre fonction init, vous pouvez utiliser textareas ou class selector , sinon cela ne fonctionnera pas correctement.

Vous devez également utiliser

ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "", "tinyMCE.triggerSave();"); 

Sur un postback d'un UpdatePanel le contenu de l'éditeur est pas enregistré sur la zone de texte, car le comportement par défaut est seulement pour form.submit, donc quand vous quoi que ce soit soumettez économisera le texte avant les messages.

Sur le code derrière pour obtenir la valeur, vous aurez juste besoin d'accéder à la propriété TextBox.Text.

REMARQUE: Si vous utilisez le. NET GZipped vous devrez probablement le laisser tomber, je ne pouvais pas le faire fonctionner, je devais l'enlever complètement.

1

Ceci est une vieille question, mais après des heures de recherche et de déconner en cherchant la réponse, je me sens obligé de poster la solution que j'ai trouvée. Il semble que, au moins dans l'implémentation que j'utilise (plusieurs éditeurs dans un UpdatePanel), tinyMCE doit être informé que le contrôle disparaît quand UpdatePanel le soumet, sinon il refusera de le charger à nouveau.

Ainsi, en plus du code Init TinyMCE (qui ne doit exécuter lorsque l'ensemble des charges de page), vous devez le faire pour chacun de vos Carto textboxes:

ScriptManager.RegisterStartupScript(this, this.GetType(), elm1.UniqueID+"Add", 
    "tinyMCE.execCommand('mceAddControl', true,'" + elm1.ClientID + "');", true); 
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), elm1.UniqueID + "Remove", 
    "tinyMCE.execCommand('mceRemoveControl', true,'" + elm1.ClientID + "');"); 

elm1 est quel que soit le tinyMCE l'élément est. Mine est une zone de texte résidant dans un contrôle UserControl, mais vous pouvez l'appliquer à n'importe quel élément que vous souhaitez lier/dissocier votre zone de texte.

+2

J'ai aussi passé des heures à chercher. Il s'avère dans la version 4 que les commandes TinyMCE ci-dessus ont été remplacées par 'mceAddEditor' /' mceRemoveEditor' http://www.tinymce.com/forum/viewtopic.php?id=31256 –

0

i résolu ce problème appel minuscule mce après la génération de réponse de l'appel ajax

function edittemp(name) { 

xmlhttp=GetXmlHttpObject(); 
if (xmlhttp==null) 
{ 
alert ("Your browser does not support XMLHTTP!"); 
return; 
} 


var url="edit_temp.php"; 
url=url+"?id="+name; 





xmlhttp.onreadystatechange=stateChanged3; 
xmlhttp.open("GET",url,true); 
xmlhttp.send(null); 


} 
function stateChanged3() 
{ 
if (xmlhttp.readyState==4) 
{ 
spl_txt=xmlhttp.responseText.split("~~~"); 


document.getElementById("edit_message").innerHTML=spl_txt[0]; 
tinyMCE.init({ 
theme : "advanced", 
mode: "exact", 
elements : "elm1", 
theme_advanced_toolbar_location : "top", 
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator," 
+ "justifyleft,justifycenter,justifyright,justifyfull,formatselect," 
+ "bullist,numlist,outdent,indent", 
theme_advanced_buttons2 : "link,unlink,anchor,image,separator," 
+"undo,redo,cleanup,code,separator,sub,sup,charmap", 
theme_advanced_buttons3 : "", 
height:"350px", 
width:"600px" 
}); 
} 
} 

et la page caaled par appel ajax est

<?php 
$name=$_GET['id']; 
include 'connection.php'; 
$result=mysql_query("SELECT * FROM `templete` WHERE temp_name='$name' and status=1"); 

$row = mysql_fetch_array($result); 
$Content=$row['body']; 
?> 
<html> 
<head> 
<title>editing using tiny_mce</title> 
<script language="..." src="tinymce/jscripts/tiny_mce /tiny_mce.js"></script> 
</head> 
<body> 
<h2>change the template here</h2> 
<form method="post" action="save_temp.php?name=<?php echo $name;?>"> 
<textarea id="elm1" name="elm1" rows="15" cols="80"><?php echo $Content;?></textarea> 
<br /> 
<input type="submit" name="save" value="Submit" /> 
<input type="reset" name="reset" value="Reset" /> 
</form> 
</body> 
</html> 

peut être utile dans une telle situation.

0

I di ce

<script language="javascript" type="text/javascript"> 
    function pageLoad(sender, args) { 
     aplicartinyMCE();  
    } 
    function aplicartinyMCE() { 
     tinyMCE.init({ 
      mode: "specific_textareas", 
      editor_selector: "mceEditor", 
      ..... 
     }); 
    } 
</script> 

qui initialisent l'éditeur après chaque publication asynchrone, même si

Puis, en cas page_load

ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "salvarEditorMCE", "tinyMCE.triggerSave();"); 
1

Mise à jour de la réponse à cette question pour ceux qui utilisent .NET framework 4, j'ai réussi à attacher TinyMCE à un TextBox dans un panneau de mise à jour en insérant ce qui suit:

dans le balisage dans la tête < > </tête > région:

<script src="scripts/tinymce/tinymce.min.js" type="text/javascript"></script> 
<script type="text/javascript"> 

    tinyMCE.init({ 
     selector: ".tinymcetextarea", 
     mode: "textareas", 

     plugins: [ 
      "advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker", 
      "searchreplace visualblocks visualchars code fullscreen autoresize insertdatetime media nonbreaking", 
      "save table contextmenu directionality emoticons template paste textcolor", 
      "autosave codesample colorpicker image imagetools importcss layer" 
     ], 

     toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | print preview media | forecolor backcolor emoticons", 
     style_formats: [ 
      { title: 'Bold text', inline: 'b' }, 
      { title: 'Red text', inline: 'span', styles: { color: '#ff0000' } }, 
      { title: 'Red header', block: 'h1', styles: { color: '#ff0000' } }, 
      { title: 'Example 1', inline: 'span', classes: 'example1' }, 
      { title: 'Example 2', inline: 'span', classes: 'example2' }, 
      { title: 'Table styles' }, 
      { title: 'Table row 1', selector: 'tr', classes: 'tablerow1' } 
     ] 
    }); 

</script> 

Dans le balisage dans le corps < > </corps > région:

<asp:TextBox ID="tbContentHtml" CssClass="tinymcetextarea" Wrap="true" runat="server" Width="90%" TextMode="MultiLine" /> 

Et enfin dans codebehind dans l'événement Page_Load:

ScriptManager.RegisterStartupScript(this, this.GetType(), tbContentHtml.UniqueID + "Add", "tinyMCE.execCommand('mceAddEditor', true,'" + tbContentHtml.ClientID + "');", true); 
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), tbContentHtml.UniqueID + "Remove", "tinyMCE.execCommand('mceRemoveEditor', true,'" + tbContentHtml.ClientID + "');"); 
2

Cette solution ne fonctionne plus pour TinyMCE 4.2.3. Au lieu d'utiliser tinymce.mceRemoveControl(), vous devez utiliser tinymce.remove().Voici un exemple de travail complet:

La page

<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPages/Frame.master" AutoEventWireup="true" CodeFile="FullImplementation.aspx.cs" 
    Inherits="TinyMCE" ValidateRequest="false" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="cphContent" Runat="Server"> 

    <asp:ScriptManager runat="server"/> 


    <asp:UpdatePanel runat="server" id="upUpdatPanel"> 
    <ContentTemplate> 

     <asp:TextBox runat="server" id="tbHtmlEditor" TextMode="MultiLine"> 
     Default editor text 
     </asp:TextBox> 

     <asp:Dropdownlist runat="server" ID="ddlTest" AutoPostBack="true" OnSelectedIndexChanged="ddlTest_SelectedIndexChanged"> 
     <Items> 
      <asp:ListItem Text="A"></asp:ListItem> 
      <asp:ListItem Text="B"></asp:ListItem> 
     </Items> 
     </asp:Dropdownlist> 

     <asp:Button runat="server" ID="butSaveEditorContent" OnClick="butSaveEditorContent_Click" Text="Save Html Content"/>  

    </ContentTemplate> 
    </asp:UpdatePanel> 

    <script type="text/javascript"> 

     $(document).ready(function() { 
     /* initial load of editor */ 
     LoadTinyMCE(); 
     }); 

     /* wire-up an event to re-add the editor */  
     Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler_Page); 

     /* fire this event to remove the existing editor and re-initialize it*/ 
     function EndRequestHandler_Page(sender, args) { 
     //1. Remove the existing TinyMCE instance of TinyMCE 
     tinymce.remove("#<%=tbHtmlEditor.ClientID%>"); 
     //2. Re-init the TinyMCE editor 
     LoadTinyMCE(); 
     } 

     function BeforePostback() { 
     tinymce.triggerSave(); 
     } 

     function LoadTinyMCE() { 

     /* initialize the TinyMCE editor */ 
     tinymce.init({ 
      selector: "#<%=tbHtmlEditor.ClientID%>", 
      plugins: "link, autolink", 
      default_link_target: "_blank", 
      toolbar: "undo redo | bold italic | link unlink | cut copy paste | bullist numlist", 
      menubar: false, 
      statusbar: false 
     }); 
     } 

    </script> 




</asp:Content> 

Le code-behind:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

public partial class TinyMCE : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
    // we have to tell the editor to re-save the date on Submit 
    if (!ScriptManager.GetCurrent(Page).IsInAsyncPostBack) 
    { 
     ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "SaveTextBoxBeforePostBack", "SaveTextBoxBeforePostBack()"); 
    } 

    } 

    protected void butSaveEditorContent_Click(object sender, EventArgs e) 
    { 
    string htmlEncoded = WebUtility.HtmlEncode(tbHtmlEditor.Text); 

    } 

    private void SaveToDb(string htmlEncoded) 
    { 
    /// save to database column 
    } 

    protected void ddlTest_SelectedIndexChanged(object sender, EventArgs e) 
    { 

    } 
} 
+0

Ceci est certainement la solution. Il fonctionne également pour TinyMCE version 4.5.4 et fonctionne sur tous les navigateurs (testé sur Chrome version 56, IE 9, 10, 11 et Microsoft Edge 38). D'autres solutions possibles qui n'utilisent pas .remove() n'ont pas fonctionné sur les navigateurs autres que IE. En outre, vous pouvez passer le nom de classe à .remove (), ce qui est ce que je fais et fonctionne très bien. Merci @bperniciaro pour cette solution! – Jaime

+0

Excellente solution (y) –

Questions connexes