ASP.NET-es képfeltöltő CLEditorhoz
Nagyon sok JavaScriptes WYSIWYG editor létezik, nekem az egyik kedvencem a CLEditor. Nem tud sokat, nem is tökéletes, de kicsi, egyszerű, pluginekkel bővíthető és jQuery alapú. Az egész editor 4 fájlból áll és mindössze 9kb, amiért ezt kapjuk:
Nem is beszélve arról, hogy gyakorlatilag ingyenesen használható a MIT és a GPLv2 licencek értelmében. Egy próbát mindenképp megér, ami a fájlok bemásolása után mindössze ennyi:
<head runat="server"> <link href="Scripts/CLEditor/jquery.cleditor.css" rel="stylesheet" type="text/css" /> <script src="Scripts/jquery-1.4.4.min.js" type="text/javascript"></script> <script src="Scripts/CLEditor/jquery.cleditor.js" type="text/javascript"></script> <script type="text/javascript"> $(function () { $('#txtContent').cleditor(); }); </script> </head> <body> <form id="form1" runat="server"> <div> <asp:TextBox ID="txtContent" runat="server" ClientIDMode="Static" TextMode="MultiLine" /> </div> </form> </body>
Mint sok más editor, sajnos alapból ez sem tud képfeltöltést, csak képbeszúrást, ami különösen nem is meglepő, hiszen a fájlfeltöltéshez szerver oldali komponens is kell. PHP-s megoldást találtam, de nekem természetesen ASP.NET-es kellett, hát csináltam egyet.
A pluginezés szerencsére nagyon egyszerű, gyakorlatilag egy új gombot kell regisztrálni:
$.cleditor.buttons.imageUpload = {
name: "imageUpload",
image: "imageUpload.png",
title: "Upload and insert image",
command: "inserthtml",
buttonClick: onImageUploadButtonClick
};
Majd ezt a gombot beszúrni az eszköztárra, például a beépített képbeszúró gomb (“image”) elé:
$.cleditor.defaultOptions.controls = $.cleditor.defaultOptions.controls.replace("image", "imageUpload image");
Máris van egy gombunk, és ha a felhasználó rákattint, meghívódik az onImageUploadButtonClick függvényünk. Itt egy jQueryUI-os dialog ablakot szeretnénk feldobni, amiben egy iframe jeleníti meg az ASP.NET-es feltöltő oldalt. Ezt így alapozhatjuk meg a markupban:
<div id="dialog" style="display: none;"> <iframe src="ImageUploadPopup.aspx" frameborder="0"></iframe> </div>
Ha ez megvan, akkor máris írhatjuk a JavaScript kódot a popup megjelenítésére:
function onImageUploadButtonClick(e, data) { // Open a new popup dialog. $("#dialog").dialog({ autoOpen: true, modal: true, width: '500', position: 'auto', title: 'Insert image', buttons: [ { text: "Insert", click: function () { $(this).dialog('close'); onImageUploadPopupClose(data); } }, { text: "Cancel", click: function () { $(this).dialog('close'); } } ] }); // Ez kell, hogy az IE az editorba szúrja be a képet, // ne kedve szerint valami meglepő helyre az oldalon. data.editor.focus(); // A false azt jelzi, hogy a gomb funkcióját teljes egészében mi // valósítjuk meg, ne a gomb deklarációnál megadott command hajtódjon végre. return false; }
A végén lévő két sortól eltekintve ebben semmi extra nincs, klasszikus jQueryUI dialog. A felugró ablakba az ImageUploadPopup.aspx fog betöltődni, ami a példa kedvéért igen egyszerű:
<asp:FileUpload runat="server" ID="fupImage" /> <asp:Button ID="btnUpload" runat="server" onclick="btnUpload_Click" Text="Upload" /> <asp:Label ID="lblResult" runat="server" /> <asp:HiddenField ID="hfSelectedImageUrl" runat="server" ClientIDMode="Static" />
A fájlt az Upload gomb megnyomására töltjük fel, majd a Labelben tájékoztatjuk a felhasználót az eredményről. A rejtett mezőt arra használjuk, hogy beleírjuk azt az URL-t, amit majd az editorba be kell szúrni. A gomb eseménykezelője:
protected void btnUpload_Click( object sender, EventArgs e ) { // Fájl mentése a diszkre. // VIGYÁZAT: demó kód, input validálás hiányzik! string folder = this.Server.MapPath( "~/Upload" ); string target = Path.Combine( folder, this.fupImage.FileName ); this.fupImage.SaveAs( target ); // Felhasználó tájékoztatása. this.lblResult.Text = String.Format( CultureInfo.InvarianCulture, "{0} feltöltve!", this.fupImage.FileName ); // Beszúrandó URL mentése a rejtett mezőbe. this.hfSelectedImageUrl.Value = "Upload/" + this.fupImage.FileName; }
Amikor a felhasználó az Insert gombra kattintva bezárja a dialógusablakot, akkor meg fog hívódni az onImageUploadPopupClose függvényünk. Itt kiolvassuk a rejtett mező tartalmát, gyártunk belőle egy img elemet és megkérjük az editort, hogy szúrja be a szövegbe:
function onImageUploadPopupClose(data) { var strSelectedImageUrl = $("#dialog").find("iframe").contents().find("#hfSelectedImageUrl").val(); var editor = data.editor; var html = "<img src='" + strSelectedImageUrl + "' />"; editor.execCommand(data.command, html, null, data.button); editor.hidePopups(); editor.focus(); }
Leírni bonyolultabb, mint megcsinálni, de még egyszerűbb a teljes forráskódot letölteni innen.

MSDN Kompetencia Központ
Üdv!
Arra vajon van valami megoldás, hogy mapped url-ekkel is működjön a CL editor?
Ha közvetlenül navigálok a http://localhost:50862/Admin/PageEdit.aspx-re, akkor betöltődik a szerkeszteni kívánt tartalom, majd egy button click eseményben elérve a CLeditor tartalmát elmentem adatbázisba.
Ha ugyezt mondjuk a http://localhost:50862/admin-pageedit URL-en keresztül érem el – akár mapped URL-ként, akár a routing engine-t használva – akkor local-ban IIS Express alatt látszólag nem történik semmi, az éles szerveren IIS alatt pedig visszadob a customErrors-ban lévő defaultRedirect-re, valahogy így: http://localhost:50862/?aspxerrorpath=/Admin/PageEdit.aspx
Az is felmerült már benne, hogy nem is a CLEditorral van a baj, hanem egyszerűen a buttonclick esemény környékén hagyok ki valami fontosat.
Szerintem itt nem a CLEditorral lesz a gond, mert az csak nyers kliens oldali JavaScript. Érdemes lenne megnézni Fiddlerrel, hogy mi megy át a hálózaton, mi kerül a HTML-be (form tag action attribútum), hova megy a postback stb.