Redigera vilken sajt som helst i webbläsaren

Ok det här är coolt faktiskt. Paul Buchheit, skaparen bakom bland annat Gmail och Friendfeed, postade just på den senare sajten en kod för att kunna redigera text direkt i webbläsaren. Den gör body till en contenteditable helt enkelt.

Jag har fått det att fungear på Safari, Firefox och Chrome, mac versioner. Och jag hör folk som säger det funkar på IE och PC versioner också.

Lägg till följande som ett bokmärke, akivera och börja skriv direkt på skärmen.

javascript:document.body.contentEditable=(document.body.contentEditable!='true');void%200

Eller klicka på denna länk för att testa på vår sajt.

By Jesper Lind

Mozilla Labs Bespin - kodredigering i molnet

Bespin

Detta är något nytt och väldigt spännande. Mozilla Labs har precis släppt en prototyp av en kodeditor som de kallar Bespin.

Har precis sett introduktionsfilmen som du hittar i releaselänken ovan och testkört själva editorn.

Man använder sig av HTML5-taggen Canvas för att rita upp scrollbars, de grafiska elementen samt även själva texten om jag förstått det hela rätt. Det gör att man kan finna funktioner som inte funnits på nät-applikationer innan. T ex kan de mäta längden på textsträngar och få texten att anpassa sig efter de omliggande panelerna och hur mycket utrymme som finns tillgängligt.

Prestandan på textediteringen blir med hjälp av Canvas-rendereringen väldigt god. I videon visas exempel på hur man redigerar en fil på över 30000 rader och det fortfarande går väldigt snabbt att skriva. Något vi inte sett på webben innan.

Även fast det är en tidig protoyp ser det mycket lovande ut och jag tror detta kan utvecklas till något riktigt häftigt. Senast för nån timme sen satt jag och försökte editera kod i en TinyMCE-editor som jag har konfigurerat själv och det är verkligen en stor möda. Det behövs något bättre på webben och Bespin kan vara svaret.

Målet med projektet är att skapa en produkt som kan mäta sig med med traditionella kodredigerare som körs i skrivbordsmiljö. Än är det nog läng väg kvar innan jag ska byta ut Visual Studio mot ett webbaserat alternativ, men kanske blir det tillräckligt bra i framtiden för att man ska göra viss del av sitt kodande ute i molnet. Möjligheten till att kollaborera många andra användare samtidigt i samma filer är minst sagt intressant.

I det första utförandet stöjder Bespin syntax highlighting för Javascript, HTML och CSS, men fler språk kommer att läggas till i senare versioner.

Man kan programmerar egna kommandon och på så sätt utöka editorn med egen funktionallitet. Det kommer även finnas en modell för att kunna dela dessa påbyggnader med andra användare.

By Jesper Lind

Syntaxmarkering i blogginlägg med Javascript

Har precis fixat så att kodexempel i denna blogg får syntaxen framhävd med färger så den förhoppningsvis ska bli mer lättläst. Det engelska uttrycket är ju "syntax higlighting" men jag hade lite svårt att hitta en svensk motsvarighet först. Kristoffer på Bloggy hjälpte mig och tipsade om "syntaxmarkering", som fick blir titel på detta inlägg.

När jag sökte efter en metod att få till detta hittade jag några olika alternativ, i en tråd på Stack Overflow går man igenom några av dem.

Vissa tycker att det är en bra ide att märka upp koden med html och css i förhand, och spara den färdigformatterad i databasen. Detta kan man bland annat göra med ett plugin till Visual Studio som heter CopySourceASHtml. Jag dock att jag inte ville ha in detta i databasen utan att koden skulel sparas helt utan extra HTML och CSS. För om man vill ändra på det i efterhand så är det ju omständigt att behöva ändra alla gamla exempel.

Istället beslutade jag mig för att använda Javascript och att formatteringen ska ske i besökarens webbläsare. Uppritningen blir ju något långsammare, men de andra fördelarena var tillräckligt stora för att jag skulle gå på detta spåret.

Ett sådant javascript är google-code-prettify men eftersom det inte verkar ha stöd för C# så var det inget alternativ för denna blogg som har större delen av kodexemplen på det programmeringsspråket.

Istället valde jag samma som Scott Hanselman och bloggplattformen Wordpress använder sig av. Det heter SyntaxHighlighter och är utvecklat av Alex Gorbatchev.

Ett litet problem är dock att koden ska märkas upp på följande sätt och name inte är godkänt attribut på <pre>-taggen enligt XHTML-standarderna.

<pre name="code" class="javascript">
// the code
</pre>

Lars Corneliussen har dock fixat ett jQuery-plugin beautyOfCode som ändrar beteendet i SyntaxHighlighter så man istället kan använda följande struktur:

<pre class="code">
<code class="javascript">
// the code
</code>
</pre>

Det senare alternativet är alltså godkänd XHTML och det är detta som jag använder här. Läs gärna om hur jag fixade så att TinyMCE-editorn kan skapa denna kod med hjälp av ett plugin.

Än så länge har jag bara gjort om kodexemplena på förstasidan i bloggen till att använda syntaxmarkeringen. Ska fundera lite på hur jag ska ändra alla gamla exempel som fortfarande bara visas med en grå ruta.

By Jesper Lind

Plugin till TinyMCE för att klistra in källkod

När jag postade mitt förra inlägg så märkte jag att källkoden kunde formateras bättre. HTML-editorn TinyMCE som vi använder till att redigera inläggen stoppar som default in <br /> på alla radbryt och omger stycken med paragrafer. Bra när man skriver brödtext, men onödigt när man vill posta källkod. Jag ville hellre att kodexemplena skulle vara förformatterade utan någon extra HTML-uppmärkning.

Eftersom jag har tagit bort breaks i det förra inlägget kommer här en bild på hur det såg ut innan.

Samtidigt ville jag prova med att fixa syntax-formattering där nyckelorden får färger för bättre läsbarhet. Ska skriva mer om hur jag gjorde själva syntax-uppmärkningen i ett senare blogginlägg, men kan nämna att jag gjort detta med javascript hos besökaren. Uppdatering: Nu har jag skrivit klart bloggposten om javascript-biblioteket syntaxhl som jag avänder till att visa formatteringen i själva blogginläggen.

Nu till TinyMCE-pluggen som märker upp kodstyckena i databasen. Det heter syntaxhl finns att ladda hem på GitHub och går att läsa mer om hos skaparen Richard Grundy. Vid redigering ser det ut så här:

http://codeodyssey.se/Images/Post/453/syntaxhl-plugin-for-tinymce.png

Som standard så omges koden med en textarea, något jag inte ville utan jag behövde en speciell uppmärkning för att fungera med den syntax-formatteraren jag valt. Hos Spencer Kellis hittade jag förklaring hur han hade gjort för att konfigurera TinyMCE med syntaxhl.

Först la jag syntaxhl i mappen plugin i TinyMCE. Sen modifierade jag syntax/js/dialog.js enligt följande för att få den uppmärkning jag efersträvade och inte textarea som den använder sig av som standard.

textarea_output = '<pre class="code">';
textarea_output += '<code class="' + f.syntaxhl_language.value + options + '">';
textarea_output +=  f.syntaxhl_code.value;
textarea_output += '</code></pre> ';

I databasen vill jag alltså att det ska sparas så här:

<pre class="code">
<code class="xhtml">
Testing the syntaxhl plugin for TinyMCE
</code>
</pre>

Så här ser mina inställningar nu:

<TinyMce:TextArea id="tbBody"
theme="advanced"
plugins="spellchecker,safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template,pagebreak,syntaxhl"
theme_advanced_buttons1="spellchecker,save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,fontsizeselect|,forecolor,backcolor"
theme_advanced_buttons2="cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,preview,pagebreak,syntaxhl"
theme_advanced_toolbar_location="bottom"
theme_advanced_toolbar_align="left"
theme_advanced_path_location="bottom"
theme_advanced_resizing="false"
extended_valid_elements="pre[class]"
pagebreak_separator="<!--more-->"
force_br_newlines="false"
convert_newlines_to_brs="false"
preformatted="true"
apply_source_formatting="false"
remove_linebreaks="false"
Value='<%# Bind("Body") %>'
Rows="20"
runat="server" />

Ändingar jag gjort sen min förra konfiguration är dessa:

  • Lagt till knappen för syntaxhl i plugin och i theme_advanced_button2.
  • Lagt till pre[class] i extended_valid_elements för att editorn ska godkänna attributet.
  • Satt force_br_newline och converty_newlines_to_brs till false.
  • Satt preformatted till true.

TinyMCE har många konfigurationmöjligheter så det finns säkert mer saker att tweaka för ännu bättre resultat. Kolla även Spenser Kellis visar upp hur han har gjort sina inställningar.

 

By Jesper Lind

Förhindra PostBack på ImageButton och kör JavaScript istället

Hade lite problem med att en ImageButton gjorde postback hela tiden, fast jag ville köra ett eget JavaScript. Trixet är att se till att return false; är med i slutet av JavaScript-anropet som jag läste om här.

<asp:TextBox ID="tbSearch" runat="server" />
<asp:ImageButton id="ibSearch"
OnClientClick="do_search();return false;"
ImageUrl="search-button.gif" runat="server" />
<script type="text/JavaScript">
function do_search()
{
window.location.href="search-results.aspx?s=" + document.getElementById('<%=tbSearch.ClientID %>').value;
}</script>

By Jesper Lind

Lansering av Silverlight 1.0

http://www.codeodyssey.se/upload/resource/blog/silverlight_anims.jpg

Silverlight har nu släppts i version 1.0, läs mer hos bland Microsoft representanterna Robert Folkesson och Scott Guthrie. För er som inte är insatta i tekniken så handlar det om ett plugin till webbläsare för att presentera multimedia och erbjuda interaktivitet (ungefär som Adobe's Flash-spelaren).

Man tillkännager samtidigt att man kommer samarbeta med Novell och hjälpa dem med att utveckla en Linux-baserad implementation av tekniken. På Linux kommer denna få namnet Moonlight läs mer hos Mono-utvecklaren Miguel de Icaza.

Version 1.0 av Silverlight programmeras om jag har förstått det hela rätt genom Javascript-kod och man behöver bara en texteditor för att skapa denna. Det går att ladda ner en utökning till Visual Studio för att få Intellisense på Javascript för Silverlight.

Nästa version 1.1 kommer stödja ASP.NET och finns än så länge bara i Alpha-släpp för utvecklare att testa med. På Silverlight-sajten finns alla verktyg som man behöver för att komma igång med att utveckla applikationer.

Vi ser fram emot att prova på Silverlight-utveckling och tror väldigt starkt på tekniken. IDG har också skrivit en notis om det.

By Jesper Lind

Första XSS-attacken mot vår blogg

Det här är inte speciellt dramatiskt egentligen, men lite kul med action. Någon postade för en stund sen en XSS-länk på den engelska delen av vår hemsida.

Jag visste att kommentarsfältet inte var skyddat mot HTML och har inte brytt mig om att fixa det förrän nu.

Attackvektorer

I kommentaren som postades låg följande html-tagg och det är alltså bara en test för att se ifall det gick att köra javascript genom kommentarerna på vår blogg.

<INPUT TYPE="IMAGE" src="javascript:alert('XSS');">

På ha.ckers.org's XSS (Cross Site Scripting) Cheat Sheet kan man läsa att denna vektor inte fungerar på IE7 eller FF2 men på IE6 och Opera. Där finns även fler referenser till andra vektorer.

Hur man skyddar man sig mot XSS (med .NET)

Det enklaste alternativet är att låta validateRequest vara på slaget som det är som standard. Nackdelarna är att det då inte går att posta taggar över huvudtaget och att ett error visas. Läs mer om för-/nackdelar ValidateRequest här. I vår blogg som handlar om webbutveckling vill vi ju kunna tillåta html-kod från våra besökare, så vi har detta skydd avstängt.

Istället ser vi till att använda Server.HtmlEncode på all text som kommer från besökaren (det var detta jag just la till).

En bra effekt är att det numera går att skriva htmlkod i kommentarerna och den visas som den ska. Vissa har ju märkt att det inte fungerat så bra tidigare och vi borde ha fixat det för länge sen.

Testning tillåtet

Om nån är intressarad får ni gärna försöka att posta XSS till detta inlägget. Jag antar att det är omöjligt men vem vet om det finns någon obskyr metod som inte HTMLEncode klarar av att filtera.

Har även lagt in en liten funktion som ska göra om url till länkar. Där kan jag tänka mig att det kan gå att få in någon XSS-variant. Så här ser funktionen ut ifall nån vill prova att "hacka" den.

public string ConvertUrlToHyperlink(string strInput)
{
string strPattern = @"(?<url>http://(?:[\w-]+\.)+[\w-]+(?:/[\w-./?%&~=]*[^.\s|,|\)|<|!])?)";
string strReplace = "<a href=\"${url}\" target=_blank>${url}</a>";
string strResult;
strResult = Regex.Replace(strInput, strPattern, strReplace);
strPattern = @"(?<!http://)(?<url>www\.(?:[\w-]+\.)+[\w-]+(?:/[\w-./?%&~=]*[^.\s|,|\)|<|!])?)";
strReplace = "<a href=\"http://${url}\" target=_blank>${url}</a>";
strResult = Regex.Replace(strResult, strPattern, strReplace);

return strResult;
}

By Jesper Lind

UpdatePanel - TinyMCE demo med nedladdningsbar zip-fil

TinyMCE är en skön HTML-Editor som har blivit väldigt populär. Den är oftast väldigt enkel att använda och har många konfigureringsmöjligheter.

Men att använda den tillsammans med Ajax och partial update är verkligen ingen lätt match. Jag lyckades tidigare i år, efter stor möda, men det var nog mest tur.

Skrev om det i bloggen, men den postningen blev inte så fullständig eller bra. Det var mest lite egna minnesanteckningar som jag fick till där. Jocke var inne och kollade på beskrivningen men fick inte till det. Så nu tänkte jag visa precis hur man kan göra med ett uppdaterad och fullständig kod.

Problemen

Problem 1. TinyMCE gör om textboxar till en Iframe, som My Portal Project förklarar. Detta leder till att det är svårt att ta emot värden (speciellt i Firefox). Waqas_badas visar hur man kan komma runt detta genom ett javascript på submit-knappen.

Problem 2. Vid Ajax-anrop ritas inte editorn upp igen. Här kan man anropa mceAddControl-kommandot, men det gäller att resetta id-räknaren innan man gör det, här är en som kommit på hur man gör.

Kodexempel

Nu tänkte jag låta koden förklara resten. Missa inte att ladda hem zip-filen längst ner som innehåller ett färdigt project som fungerar i IE7, FF2 och Opera.

Default.aspx

<%@ Page Language="C#" ValidateRequest="false" Trace="false" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>MS Ajax UpdatePanel - TinyMCE</title>
<script type="text/javascript">
function SaveMyPreciousValues()
{
tinyMCE.triggerSave(false,true);
TextBox1 = document.getElementById('TextBox1');
alert('Check value when posting: '+ TextBox1.value)
}
</script>
</head>
<body>

<form id="form1" runat="server">
<asp:ScriptManager ID="sm" EnablePartialRendering="true" runat="server">
</asp:ScriptManager>

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<p>
<asp:Label ID="Label1" runat="server" Text="Welcome to the MS Ajax UpdatePanel - TinyMCE Demo, Enjoy!"></asp:Label>
</p>
<asp:TextBox ID="TextBox1" Rows="10" Columns="50" TextMode="MultiLine" EnableViewState="false" Text="Write something here..." runat="server"></asp:TextBox>

<p>
<asp:Button ID="Button1" runat="server" OnClick="Button1_OnClick" OnClientClick="SaveMyPreciousValues();" Text="Hit me" />
</p>
</ContentTemplate>
</asp:UpdatePanel>

</form>
</body>
</html>

Default.cs.aspx

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
LoadTinyMCE();
}

private void LoadTinyMCE()
{

//Load tinyMCE
HtmlGenericControl Include = new HtmlGenericControl("script");
Include.Attributes.Add("type", "text/javascript");
Include.Attributes.Add("src", "js/tiny_mce/tiny_mce.js");
this.Page.Header.Controls.Add(Include);


//Config MCE
HtmlGenericControl Include2 = new HtmlGenericControl("script");
Include2.Attributes.Add("type", "text/javascript");
Include2.InnerHtml = "tinyMCE.init({mode : 'textareas' ,language : 'sv',entity_encoding : 'raw'});";
this.Page.Header.Controls.Add(Include2);

}

protected void Button1_OnClick(object sender, EventArgs e)
{

//Get the contect of the TextBox
string inputText = Request.Form["TextBox1"];

//Print all Form-values when testing
/*for (int i = 0; i<Request.Form.Count;i++ )
{
string itemName = Request.Form.AllKeys[i];
string itemValue = Request.Form.GetValues(i)[0];
Label1.Text = Label1.Text + "<br />" + itemName + ":" + itemValue;
}*/

Label1.Text = "Content posted from TextBox1: " + inputText;

//Register some javascript to redraw the editor.
//Very important to reset the id-counter to "0", or else strange things will happen..
ScriptManager.RegisterClientScriptBlock(UpdatePanel1, this.GetType(), "init", "tinyMCE.idCounter=0;tinyMCE.execCommand('mceAddControl', false, 'TextBox1');", true);
}
}

zip-icon UpdatePanelTinyMCE.zip (C#)

Uppdatering: Joakim har skrivit om exemplet till VB.NET, läs mer på hans blogg.

By Jesper Lind