<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kruse-Net.dk &#187; javascript</title>
	<atom:link href="http://www.kruse-net.dk/kategorier/tech/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kruse-net.dk</link>
	<description>Det man blogger er man selv...</description>
	<lastBuildDate>Tue, 22 Nov 2011 15:18:43 +0000</lastBuildDate>
	<language>da</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Include/import i Javascript</title>
		<link>http://www.kruse-net.dk/2006/03/20/includeimport-i-javascript/</link>
		<comments>http://www.kruse-net.dk/2006/03/20/includeimport-i-javascript/#comments</comments>
		<pubDate>Mon, 20 Mar 2006 19:43:40 +0000</pubDate>
		<dc:creator>Jakob Kruse</dc:creator>
				<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.kruse-net.dk/2006/03/20/includeimport-i-javascript/</guid>
		<description><![CDATA[Med Web 2.0 og de deraf følgende Javascript biblioteker af stigende størrelse er der specielt én mangel i Javascript der så småt begynder at blive kritisk: mangelen på en &#8220;include&#8221; eller &#8220;import&#8221; erklæring, eller med andre ord at man ikke umiddelbart i én script fil kan angive at en anden skal indlæses. Min forrige artikel, [...]]]></description>
			<content:encoded><![CDATA[<p><!-- First we load the Script library -->
<script type="text/javascript" src="/javascript/lib/Script.js"></script></p>

<p><!-- Then map all aliases to script file uri's -->
<script type="text/javascript">
<!--
  Script.addAlias("String extensions", "/javascript/ext/StringX.js");
// -->
</script></p>

<p>Med Web 2.0 og de deraf følgende Javascript biblioteker af stigende størrelse er der specielt én mangel i Javascript der så småt begynder at blive kritisk: mangelen på en &#8220;include&#8221; eller &#8220;import&#8221; erklæring, eller med andre ord at man ikke umiddelbart i én script fil kan angive at en anden skal indlæses. Min forrige artikel, &#8220;Leg med AJAX&#8221;, illustrerer det kun alt for tydeligt. Der skal inkluderes ikke mindre end 8 forskellige biblioteker for at få stillet funktionaliteten i det sidste til rådighed. Den stakkels udvikler der skal bruge Google biblioteket skal selv holde styr på at få de andre 7 inkluderet i den rette rækkefølge. Ekstrapoleres eksemplet til en hel Web 2.0 applikation kan det være over 100 script filer der på den måde skal holdes styr på. Noget må gøres!</p>

<p>Løsningen er nærliggende. AJAX giver netop mulighed for ikke blot at hente XML, men også Javascript og alt muligt andet. Så de samme teknologier som anvendes til at gøre en Web 2.0 side levende kan anvendes til at forenkle den. Løsningen findes i flere forskellige varianter. De fleste inkluderer på en eller anden måde <code>eval()</code> funktionen, hvilket jeg har meget svært ved at finde elegant &#8211; den har aldrig samme effekt som at loade filen på den &#8220;sædvanlige&#8221; måde, med et script tag. Den løsning jeg foreslår her er lidt anderledes, omend uhyre enkel: den efterspurgte Javascript kode hentes som tekst og indsættes i kroppen af et script tag, der derefter indsættes på siden. Browserens umiddelbare reaktion er at fortolke hele indholdet af script tag&#8217;et.</p>

<p>Nedenstående to knapper illustrerer teknikken. Klik på den første og du får en fejl (eller ingenting, hvis din browser ikke er sat op til at vise Javascript fejl). Klik på den anden medfører indlæsning af et script, hvorefter klik på første knap igen har et mere positivt resultat.</p>

<p><input type="button" value="en_funktion_i_mit_library()" onclick="en_funktion_i_mit_library()" />
<input type="button" value="Script.require('/javascript/mit_library.js')" onclick="Script.require('/javascript/mit_library.js')" /></p>

<p>Script objektet der stiller løsningen til rådighed findes i filen 
<a  href="/javascript/lib/Script.js">Script.js</a>. Det er ganske få linier der er tale om, så overhead&#8217;et er lille. Script objektet stiller udover funktionen <code>require()</code> også en funktion <code>addAlias()</code> til rådighed. Tanken er at en script fil der gør brug af <code>Script.require()</code> ikke nødvendigvis skal rettes blot fordi der flyttes rundt på de andre script-filer. Ved at referere til symbolske navne i stedet for absolutte stier er dette enkelt at håndtere. I praksis tænkes biblioteket anvendt på følgende måde på en given side:</p>

<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">&lt;!-- Først loader vi Script biblioteket --&gt;
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">script </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text/javascript</span><span class="hl-quotes">&quot; </span><span class="hl-var">src</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Script.js</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;&lt;/</span><span class="hl-reserved">script</span><span class="hl-brackets">&gt;

</span><span class="hl-comment">&lt;!-- Derefter sætter vi alle nødvendige alias'er op (bør placeres i en ekstern script fil) --&gt;
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">script </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text/javascript</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-default">
  Script.addAlias(&quot;Prototype 1.4&quot;, &quot;/javascript/lib/prototype.js&quot;);
  Script.addAlias(&quot;Prototype 1.5&quot;, &quot;/javascript/lib/prototype-1.5.0_pre0.js&quot;);
  Script.addAlias(&quot;String extensions&quot;, &quot;/javascript/ext/StringX.js&quot;);
  // ...
</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">script</span><span class="hl-brackets">&gt;

</span><span class="hl-comment">&lt;!-- Så er vi klar! Nu kan vi inkludere script filer der indeholder noget svarende til: --&gt;
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">script </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text/javascript</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-default">
  Script.require(&quot;String extensions&quot;);
  
  alert(&quot;foobar&quot;.right(3)); // right funktionen defineres i String extensions
</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">script</span><span class="hl-brackets">&gt;</span></pre></div></div>

<p>Der hører et par bemærkninger til løsningen her til sidst. Eftersom XmlHttpRequest anvendes til at hente de ønskede scripts ligger løsningen under for cross domain problematikken &#8211; det er kun muligt at bede om scripts fra samme server som siden kommer fra. Funktionen `require()` har en ekstra parameter &#8220;async&#8221; man kan sætte til &#8220;true&#8221; for at omgå dette problem. Resultatet er at der blot indsættes et script tag med en src attribut. Det har samme virkning, men som async parameteren angiver hentes scriptet asynkront, dvs. mens det eksekverende script kører videre. Alt hvad der loades på denne måde vil således først være tilgængeligt når den aktuelle script blok forlades (alle de browsere jeg har testet venter med at starte eksekveringen af næste script blok til de ønskede data er hentet). I nogle tilfælde er det brugbart.</p>

<div class="note">
<p><strong>Opdatering:</strong> Det viser sig at når scripts hentes synkront (via XmlHttpRequest) i Internet Explorer så kan der meget let opstå encoding problemer. Hvis web serveren afsender script filen uden angivelse af encoding (hvilket fortolkes som UTF-8), og filen f.eks. indeholder ikke-US-ASCII tegn kodet i ISO-LATIN1 så går det galt. Jeg tror dette er forklaringen på kommentar nummer 2 nedenfor. Problemet kan, hvor jeg har testet, løses ved at sikre at filen der hentes er kodet i UTF-8.</p>

<p>Bemærk at samme fil hentet &#8220;på normal vis&#8221; (ved et script tag) fortolkes korrekt af Internet Explorer.</p>
</div>

<div class="note">
<p><strong>Opdatering:</strong> Internet Explorer demonstrerer også problemer hvis ét script, der er hentet asynkront, beder om at hente et andet script synkront. Så af hensyn til Internet Explorer bør man hente alle scripts synkront.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.kruse-net.dk/2006/03/20/includeimport-i-javascript/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Leg med AJAX</title>
		<link>http://www.kruse-net.dk/2006/03/02/leg-med-ajax/</link>
		<comments>http://www.kruse-net.dk/2006/03/02/leg-med-ajax/#comments</comments>
		<pubDate>Thu, 02 Mar 2006 21:09:51 +0000</pubDate>
		<dc:creator>Jakob Kruse</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.kruse-net.dk/2006/03/01/leg-med-ajax/</guid>
		<description><![CDATA[Opdatering: Eksemplet nedenfor har stadig en vis relevans kode-mæssigt, men da Google har droppet deres SOAP API fungerer det ikke længere. Dagens menu står på kald af SOAP-baserede web services via AJAX. Og hvis ikke du for nylig har forsynet dig med en kop kaffe, så var det måske en god idé at gøre det [...]]]></description>
			<content:encoded><![CDATA[<p><!-- Prototype -->
<script type="text/javascript" src="/javascript/lib/prototype-1.5.0_pre0.js"></script>
<!-- Document extensions -->
<script type="text/javascript" src="/javascript/ext/DocumentX.js"></script>
<!-- String extensions -->
<script type="text/javascript" src="/javascript/ext/StringX.js"></script>
<!-- AJAX Extended -->
<script type="text/javascript" src="/javascript/lib/xmlhttp.js"></script>
<!-- Modify Prototype for use with AJAX Extended -->
<script type="text/javascript" src="/javascript/lib/prototype-xmlhttp.js"></script>
<!-- IBM WS-AJAX -->
<script type="text/javascript" src="/javascript/lib/ws.js"></script>
<!-- Extensions of IBM WS-AJAX -->
<script type="text/javascript" src="/javascript/ext/ws-x.js"></script>
<!-- Behaviour -->
<script type="text/javascript" src="/javascript/lib/behaviour-1.1-p1.js"></script>
<!-- Google API interface -->
<script type="text/javascript" src="/javascript/Google.js"></script></p>

<p><strong>Opdatering:</strong> Eksemplet nedenfor har stadig en vis relevans kode-mæssigt, men da Google har droppet deres SOAP API fungerer det ikke længere.</p>

<p>Dagens menu står på kald af SOAP-baserede web services via AJAX. Og hvis ikke du for nylig har forsynet dig med en kop kaffe, så var det måske en god idé at gøre det før du læser meget videre. For det er en hel del komponenter jeg hermed bringer i spil på samme tid. For de utålmodige starter jeg med resultatet &#8212; indlejrede Google søgninger:</p>

<p><input type="text" id="search_string" />
<input type="button" value="Søg" id="search_button" />
<img src="/graphics/spinner-small.gif" alt="spinner"  id="searchingGoogle" style="display: none"/></p>

<div id="result_section" style="display: none">10 første resultater (af <span id="estimated_count">?</span>):<br /><ul id="results"><li /></ul></div>

<p>Bemærk at Google kun tillader 1000 forespørgsler pr. dag pr. nøgle, så hvis der ikke kommer noget svar kan det være derfor.</p>

<p><span id="more-46"></span></p>

<p><strong>Det var sjovt, vis mig koden!</strong></p>

<p>Ovenstående er frembragt af følgende:
<div>::HLIGHT<em>BLOCK</em>7::</div></p>

<p><strong>Okay, men hvor er <em>koden</em>?</strong></p>

<p>Den ligger selvfølgelig i striben af inkluderede javascript filer. Lad os tage dem fra en ende af.</p>

<ol>
<li>
<a  href="/javascript/lib/prototype-1.5.0_pre0.js">prototype-1.5.0_pre0.js</a> &#8211; Sam Stephensons 
<a  href="http://prototype.conio.net/" onclick="javascript:pageTracker._trackPageview('/external/prototype.conio.net/');" >Prototype</a> bibliotek er vel efterhånden noget af det nærmeste man kommer til en standard for AJAX kommunikation, og i øvrigt et rigtigt pænt generelt Javascript bibliotek. Jeg bruger en pre-release af version 1.5.0 her, frisk fra Subversion repositoriet. Jeg har selv fundet stor hjælp i denne 
<a  href="http://www.sergiopereira.com/articles/prototype.js.html" onclick="javascript:pageTracker._trackPageview('/external/www.sergiopereira.com/articles/prototype.js.html');" >dokumentation til Prototype</a>, som dog kun dækker funktionalitet i 1.4. Der er dog kun et enkelt sted jeg bruger en funktion fra 1.5, og det tilmed en meget lille en, så tingene ville ret let kunne omskrives til at køre på 1.4.0 (det er testet).</li>
<li>
<a  href="/javascript/ext/DocumentX.js">DocumentX.js</a> &#8211; definerer <code>xml</code> og <code>loadXML()</code> på Document klassen, ifald den findes. Dermed kan xml strenge ind- og udlæses i Mozilla på samme måde som i Internet Explorer.</li>
<li>
<a  href="/javascript/ext/StringX.js">StringX.js</a> &#8211; definerer (bl.a.) en metode <code>fix_broken_utf8()</code> på String klassen, der bruges til at rette op på en encoding fejl i Firefox.</li>
<li>
<a  href="/javascript/lib/xmlhttp.js">xmlhttp.js</a> &#8211; 
<a  href="http://ajaxextended.com/" onclick="javascript:pageTracker._trackPageview('/external/ajaxextended.com/');" >AJAX Extended</a> er et smart lille bibliotek af Alex Serebryakov, der skifter brugen af XMLHttpRequest ud med dynamiske script tags, hvormed bl.a. cross-domain problemer undgås. Kræver dog en server-side proxy. Jeg bruger version 0.9 her, men har forbedret lidt på den, så tag min udgave. Alle ændringer er tydeligt markeret.</li>
<li>
<a  href="/javascript/lib/prototype-xmlhttp.js">prototype-xmlhttp.js</a> &#8211; justerer Prototype til at anvende AJAX Extended i stedet for XMLHttpRequest på kun tre linier!</li>
<li>
<a  href="/javascript/lib/ws.js">ws.js</a> &#8211; IBM&#8217;s James Snell har skrevet 
<a  href="http://www-128.ibm.com/developerworks/webservices/library/ws-wsajax/" onclick="javascript:pageTracker._trackPageview('/external/www-128.ibm.com/developerworks/webservices/library/ws-wsajax/');" >WS-AJAX</a> der er &#8220;a cross-platform, JavaScript-based SOAP Web services client based on the Asynchronous JavaScript and XML (Ajax) design pattern for Web applications&#8221;. WS-AJAX tager sig af SOAP og message parsing og benytter Prototype (og dermed i mit tilfælde AJAX Extended) til at kommunikere med serveren. Versionen der er tilgængelig på IBM&#8217;s side lider af den brist at den kun kan snakke med en web service der ligger på den server scriptet anvendes fra. Et problem jeg har løst ved at anvende AJAX Extended. Desuden bruger jeg en nyere version af Prototype end den James Snell bruger, og der er af den årsag indført nogle rettelser i min udgave af ws.js. Min udgave er baseret på version 0.1.</li>
<li>
<a  href="/javascript/ext/ws-x.js">ws-x.js</a> &#8211; retter et problem i <code>XML.getElementsByQName()</code>, og tilføjer en enkelt ofte anvendt metode <code>get_first_child()</code> til WS-AJAX.</li>
<li>
<a  href="/javascript/Google.js">Google.js</a> &#8211; en 
<a  href="http://www.google.com/apis/" onclick="javascript:pageTracker._trackPageview('/external/www.google.com/apis/');" >Google API</a> klient, og klassen der binder det hele sammen.</li>
</ol>

<p><strong>Hvordan hænger det sammen?</strong></p>

<p>Når der klikkes på søge-knappen ovenfor kaldes <code>Google.search()</code> metoden i Google.js, her set i uddrag:
<div>::HLIGHT<em>BLOCK</em>8::</div></p>

<p>Metoden opretter et WS-AJAX <code>Call</code> objekt, udfylder det, og beder om at få udført en SOAP RPC forespørgsel til Google. WS-AJAX bygger en SOAP kuvert med parametrene i og beder derefter Prototype om at levere et objekt der kan transportere kuverten til modtageren. Normalt ville Prototype levere et XMLHttpRequest objekt (det vil den hvis <code>prototype-xmlhttp.js</code> filen fjernes), men her leveres i stedet XMLHTTP objektet fra AJAX Extended. WS-AJAX beder om at få sendt kuverten, så AJAX Extended sender den videre til server-side proxy scriptet (via en eller flere ganske komplicerede javascript uri&#8217;er), som kommunikerer med Google og sender svaret tilbage. WS-AJAX parser svaret (et XML dokument) til et SOAP objekt, som gives som parameter til funktionen der erklæres nederst i ovenstående uddrag. Funktionen tager sig derefter af at placere data de ønskede steder på siden.</p>

<p>Pyyh&#8230; Det var en lang omgang. Men eftersom det eneste der skal ændres for at snakke med en anden web service er det der ligger i Google.js (ca. 60 linier kode), er det faktisk ikke så kompliceret.</p>

<p><strong>Jeg vil se mere!</strong></p>

<p>Det tænkte jeg nok. Der er en detalje ved html koden ovenfor som ikke er behagelig &#8212; den indeholder &#8220;funktionalitet&#8221; i form af inline script kode. Den slags hører ikke hjemme i html. Heldigvis er det til at råde bod på. Ind træder 
<a  href="http://bennolan.com/behaviour/" onclick="javascript:pageTracker._trackPageview('/external/bennolan.com/behaviour/');" >Behaviour</a> af Ben Nolan. &#8220;Behaviors&#8221; har længe været kendt i Internet Explorer: I CSS stylesheetet kan man via en særlig <code>behavior:</code> erklæring tilknytte funktionalitet i form af script kode til elementer, på samme måde som der tilknyttes layout. Både Netscape og Microsoft har forsøgt at &#8220;sælge&#8221; denne idé til W3C, først hver for sig &#8212; hhv. 
<a  href="http://www.w3.org/TR/NOTE-AS" onclick="javascript:pageTracker._trackPageview('/external/www.w3.org/TR/NOTE-AS');" >Action Sheets</a> og 
<a  href="http://www.w3.org/TR/NOTE-HTMLComponents" onclick="javascript:pageTracker._trackPageview('/external/www.w3.org/TR/NOTE-HTMLComponents');" >HTML Components</a>, begge i 1998 &#8212; og siden sammen i 1999 under titlen &#8220;
<a  href="http://www.w3.org/TR/becss" onclick="javascript:pageTracker._trackPageview('/external/www.w3.org/TR/becss');" >Behavioral Extensions to CSS</a>&#8220;. Men det er aldrig blevet til mere end et Working Draft.</p>

<p>I mangel af en egentlig standard er det heldigvis muligt at implementere konceptet i Javascript, som Ben Nolan har gjort. Med Behaviour kan vi skrive Google eksemplet om som følger:</p>

<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-brackets">&lt;</span><span class="hl-reserved">input </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text</span><span class="hl-quotes">&quot; </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">search_string</span><span class="hl-quotes">&quot; </span><span class="hl-brackets">/&gt;
&lt;</span><span class="hl-reserved">input </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">button</span><span class="hl-quotes">&quot; </span><span class="hl-var">value</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Søg</span><span class="hl-quotes">&quot; </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">search_button</span><span class="hl-quotes">&quot; </span><span class="hl-brackets">/&gt;
&lt;</span><span class="hl-reserved">img </span><span class="hl-var">src</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">/graphics/spinner-small.gif</span><span class="hl-quotes">&quot; </span><span class="hl-var">alt</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">spinner</span><span class="hl-quotes">&quot;  </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">searchingGoogle</span><span class="hl-quotes">&quot; </span><span class="hl-var">style</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">display: none</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">/&gt;

&lt;</span><span class="hl-reserved">p </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">result_section</span><span class="hl-quotes">&quot; </span><span class="hl-var">style</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">display: none</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-default">10 første resultater (af </span><span class="hl-brackets">&lt;</span><span class="hl-reserved">span </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">estimated_count</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-default">?</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">span</span><span class="hl-brackets">&gt;</span><span class="hl-default">):</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">br </span><span class="hl-brackets">/&gt;&lt;</span><span class="hl-reserved">ul </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">results</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;&lt;/</span><span class="hl-reserved">ul</span><span class="hl-brackets">&gt;&lt;/</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span></pre></div></div>

<p>Funktionaliteten erklæres i en Javascript fil (her placeret i Google.js for at holde det enkelt):</p>

<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Google</span><span class="hl-default">.</span><span class="hl-identifier">behaviours</span><span class="hl-default"> = </span><span class="hl-brackets">{
  </span><span class="hl-quotes">'</span><span class="hl-string">#search_string</span><span class="hl-quotes">'</span><span class="hl-code"> : </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">element</span><span class="hl-brackets">) {
    </span><span class="hl-identifier">Behaviour</span><span class="hl-code">.</span><span class="hl-identifier">addEventObserver</span><span class="hl-brackets">(</span><span class="hl-identifier">element</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">keydown</span><span class="hl-quotes">'</span><span class="hl-code">,
      </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-brackets">) {
        </span><span class="hl-reserved">if </span><span class="hl-brackets">(</span><span class="hl-code">!</span><span class="hl-identifier">e</span><span class="hl-brackets">) </span><span class="hl-reserved">var </span><span class="hl-identifier">e</span><span class="hl-code"> = </span><span class="hl-builtin">window</span><span class="hl-code">.</span><span class="hl-identifier">event</span><span class="hl-code">;
        </span><span class="hl-reserved">if </span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-code">.</span><span class="hl-identifier">keyCode</span><span class="hl-code"> == </span><span class="hl-identifier">Event</span><span class="hl-code">.</span><span class="hl-identifier">KEY_RETURN</span><span class="hl-brackets">) {</span><span class="hl-code">
          $</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">search_button</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">click</span><span class="hl-brackets">()</span><span class="hl-code">;
        </span><span class="hl-brackets">}
      }</span><span class="hl-code">, </span><span class="hl-reserved">false
    </span><span class="hl-brackets">)</span><span class="hl-code">;
  </span><span class="hl-brackets">}</span><span class="hl-code">,
  
  </span><span class="hl-quotes">'</span><span class="hl-string">#search_button</span><span class="hl-quotes">'</span><span class="hl-code"> : </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">element</span><span class="hl-brackets">) {
    </span><span class="hl-identifier">Behaviour</span><span class="hl-code">.</span><span class="hl-identifier">addEventObserver</span><span class="hl-brackets">(</span><span class="hl-identifier">element</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">click</span><span class="hl-quotes">'</span><span class="hl-code">,
      </span><span class="hl-reserved">function</span><span class="hl-brackets">() {
        </span><span class="hl-identifier">Google</span><span class="hl-code">.</span><span class="hl-identifier">search</span><span class="hl-brackets">(</span><span class="hl-code">$</span><span class="hl-identifier">F</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">search_string</span><span class="hl-quotes">'</span><span class="hl-brackets">))</span><span class="hl-code">;
      </span><span class="hl-brackets">}</span><span class="hl-code">, </span><span class="hl-reserved">false
    </span><span class="hl-brackets">)</span><span class="hl-code">;
  </span><span class="hl-brackets">}
}</span><span class="hl-default">;

</span><span class="hl-identifier">Behaviour</span><span class="hl-default">.</span><span class="hl-identifier">register</span><span class="hl-brackets">(</span><span class="hl-identifier">Google</span><span class="hl-code">.</span><span class="hl-identifier">behaviours</span><span class="hl-brackets">)</span><span class="hl-default">;</span></pre></div></div>

<p>Bemærk at Bens version af Behaviour, omend en rigtigt god start, lider af en række fejl og mangler. Mange af disse har venlige personer rådet bod på, men rettelserne er desværre ikke blevet tilføjet den officielle udgave. Du bør derfor anvende 
<a  href="/javascript/lib/behaviour-1.1-p1.js">min version af behaviour.js</a> indtil Ben får frigivet noget der er bedre. Den kræver i øjeblikket Prototype 1.5, men ville forholdsvis let kunne rettes til at køre uden.</p>

<p>Ovenstående eksempel er ret simpelt, men man kan også anvende mere komplicerede CSS selector udtryk indeholdende både element-navne, klasser, ét id samt alle CSS2 og CSS3 attribut selectors. F.eks. &#8220;#mydiv table tr.even a[href*=w3.org]&#8220;.</p>

<p>God fornøjelse!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kruse-net.dk/2006/03/02/leg-med-ajax/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Konvertering af Thai tekst</title>
		<link>http://www.kruse-net.dk/2006/02/23/konvertering-af-thai-tekst/</link>
		<comments>http://www.kruse-net.dk/2006/02/23/konvertering-af-thai-tekst/#comments</comments>
		<pubDate>Thu, 23 Feb 2006 20:25:51 +0000</pubDate>
		<dc:creator>Jakob Kruse</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Thai]]></category>

		<guid isPermaLink="false">http://www.kruse-net.dk/2006/02/23/konvertering-af-thai-tekst/</guid>
		<description><![CDATA[Før Unicode kom til, anvendte computere i Thailand et 8-bit tegnsæt ved navn TIS-620. Det indeholder de almindelige engelske tegn på samme pladser som i ASCII tabellen, samt de thailandske tegn på de pladser hvor vi f.eks. har placeret æøå og diverse tegn med accenter på. Hvis en fil kodet i TIS-620 flyttes til en [...]]]></description>
			<content:encoded><![CDATA[<p>Før Unicode kom til, anvendte computere i Thailand et 8-bit tegnsæt ved navn 
<a  href="http://www.langbox.com/codeset/tis620.html" onclick="javascript:pageTracker._trackPageview('/external/www.langbox.com/codeset/tis620.html');" >TIS-620</a>. Det indeholder de almindelige engelske tegn på samme pladser som i ASCII tabellen, samt de thailandske tegn på de pladser hvor vi f.eks. har placeret æøå og diverse tegn med accenter på. Hvis en fil kodet i TIS-620 flyttes til en dansk (eller engelsk) computer og læses der, vil den indeholde tekst der ser ud som det her: &#8220;ÍÂÒ¡ÃÙéÇèÒ&#8221;. Når man som jeg har det ene ben i Thailand er det noget man ser ret ofte. Men det er heldigvis til at råde bod på. Personligt får jeg ikke meget ud af at konvertere volapyk&#8217;en til thai, men så kan min kære hustru da i det mindste læse det.</p>

<p>Først resultatet af mine anstrengelser. Prøv at kopiere den underlige tekst ovenfor ind i feltet til venstre her nedenfor, og forlad så feltet (f.eks. ved at trykke på tabulator-tasten eller klikke på feltet til højre). Dit operativsystem og din browser, samt de installerede skrifttyper, skal understøtte Unicode for at det lykkes.</p>

<script type="text/javascript" src="/javascript/Tis2Unicode.js"></script>

<p><input type="text" size="40" onblur="document.getElementById('tis2unicode_output').value = tis2unicode(this.value);" style="font-size: large" />
<input type="text" size="40" id="tis2unicode_output" style="font-size: large" /></p>

<p>Virkede det? Smart ikke?</p>

<p>Konverteringen foretages i javascript, og koden ser således ud:</p>

<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">function </span><span class="hl-identifier">tis2unicode</span><span class="hl-brackets">(</span><span class="hl-identifier">tis</span><span class="hl-brackets">) {
  </span><span class="hl-reserved">var </span><span class="hl-identifier">unicode</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;&quot;</span><span class="hl-code">;
  </span><span class="hl-reserved">for </span><span class="hl-brackets">(</span><span class="hl-identifier">i</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code">; </span><span class="hl-identifier">i</span><span class="hl-code"> &lt; </span><span class="hl-identifier">tis</span><span class="hl-code">.</span><span class="hl-identifier">length</span><span class="hl-code">; </span><span class="hl-identifier">i</span><span class="hl-code">++</span><span class="hl-brackets">) {
    </span><span class="hl-reserved">var </span><span class="hl-identifier">val</span><span class="hl-code"> = </span><span class="hl-identifier">tis</span><span class="hl-code">.</span><span class="hl-identifier">charCodeAt</span><span class="hl-brackets">(</span><span class="hl-identifier">i</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-reserved">if </span><span class="hl-brackets">(</span><span class="hl-identifier">val</span><span class="hl-code"> &lt; </span><span class="hl-number">0</span><span class="hl-identifier">x80</span><span class="hl-brackets">) {
      </span><span class="hl-identifier">unicode</span><span class="hl-code"> += </span><span class="hl-identifier">tis</span><span class="hl-code">.</span><span class="hl-identifier">charAt</span><span class="hl-brackets">(</span><span class="hl-identifier">i</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-brackets">} </span><span class="hl-reserved">else if </span><span class="hl-brackets">((</span><span class="hl-number">0</span><span class="hl-identifier">xA1</span><span class="hl-code"> &lt;= </span><span class="hl-identifier">val</span><span class="hl-code"> &amp;&amp; </span><span class="hl-identifier">val</span><span class="hl-code"> &lt;= </span><span class="hl-number">0</span><span class="hl-identifier">xDA</span><span class="hl-brackets">)</span><span class="hl-code"> || </span><span class="hl-brackets">(</span><span class="hl-number">0</span><span class="hl-identifier">xDF</span><span class="hl-code"> &lt;= </span><span class="hl-identifier">val</span><span class="hl-code"> &amp;&amp; </span><span class="hl-identifier">val</span><span class="hl-code"> &lt;= </span><span class="hl-number">0</span><span class="hl-identifier">xFB</span><span class="hl-brackets">)) {
      </span><span class="hl-identifier">unicode</span><span class="hl-code"> += </span><span class="hl-builtin">String</span><span class="hl-code">.</span><span class="hl-identifier">fromCharCode</span><span class="hl-brackets">(</span><span class="hl-number">0</span><span class="hl-identifier">x0E00</span><span class="hl-code"> + </span><span class="hl-identifier">val</span><span class="hl-code"> - </span><span class="hl-number">0</span><span class="hl-identifier">xA0</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-brackets">}
  }
  </span><span class="hl-reserved">return </span><span class="hl-identifier">unicode</span><span class="hl-code">;
</span><span class="hl-brackets">}</span></pre></div></div>

<p>Du kan downloade koden 
<a  href="/javascript/Tis2Unicode.js">her</a>. Den er baseret på et 
<a  href="http://www.fedu.uec.ac.jp/ZzzThai/service/tis2utf8.html" onclick="javascript:pageTracker._trackPageview('/external/www.fedu.uec.ac.jp/ZzzThai/service/tis2utf8.html');" >perl script</a> fra 
<a  href="http://www.fedu.uec.ac.jp/ZzzThai/" onclick="javascript:pageTracker._trackPageview('/external/www.fedu.uec.ac.jp/ZzzThai/');" >ZzzTh@i</a> projektet. Et glimrende eksempel på forekomst af forkert fortolket TIS-620 tekst kan findes på 
<a  href="http://www.nectec.or.th/it-standards/std620/std620.htm" onclick="javascript:pageTracker._trackPageview('/external/www.nectec.or.th/it-standards/std620/std620.htm');" >siden om TIS-620</a> formatet. De fleste browsere i denne del af verden vil fortolke siden i ISO-8859-1 (fordi der ikke er specificeret en encoding på siden). I nogle browsere kan man manuelt vælge TIS-620 under &#8220;Encoding&#8221;, hvorefter siden fortolkes korrekt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kruse-net.dk/2006/02/23/konvertering-af-thai-tekst/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Indtastning af datoer</title>
		<link>http://www.kruse-net.dk/2006/01/06/indtastning-af-datoer/</link>
		<comments>http://www.kruse-net.dk/2006/01/06/indtastning-af-datoer/#comments</comments>
		<pubDate>Fri, 06 Jan 2006 15:31:02 +0000</pubDate>
		<dc:creator>Jakob Kruse</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Set i verden]]></category>

		<guid isPermaLink="false">http://www.kruse-net.dk/2006/01/06/indtastning-af-datoer/</guid>
		<description><![CDATA[En af de ting der ofte er problematisk i web applikationer er indtastning af datoer. Nogle applikationer tvinger brugeren til at gå gennem en kalender (der ofte skal snakke med serveren for at skifte måned), for at være sikker på at datoen bliver indtastet i et gyldigt format. Det er langsomt, og det tvinger ofte [...]]]></description>
			<content:encoded><![CDATA[<p>En af de ting der ofte er problematisk i web applikationer er indtastning af datoer. Nogle applikationer tvinger brugeren til at gå gennem en kalender (der ofte skal snakke med serveren for at skifte måned), for at være sikker på at datoen bliver indtastet i et gyldigt format. Det er langsomt, og det tvinger ofte brugeren til at bruge musen, selvom mange hellere vil taste datoen direkte. Andre applikationer giver kun mulighed for direkte indtastning, og tvinger dermed brugeren til overholde et specifikt format, som endda nogle gange slet ikke er nævnt.</p>

<p>Men hvorfor skal det være så besværligt? Her præsenteres et almindeligt input felt beregnet til dato-indtastning. Bag feltet ligger lidt logik der sørger for at en stribe forskellige formater håndteres helt automatisk. Idéen er ikke min egen, men stammer fra Simon Willisons artikel 
<a  href="http://simon.incutio.com/archive/2003/10/06/betterDateInput" onclick="javascript:pageTracker._trackPageview('/external/simon.incutio.com/archive/2003/10/06/betterDateInput');" >A better way of entering dates</a>. Her tilrettet til brug i danske applikationer og udvidet lidt. Prøv selv!</p>

<script type="text/javascript" src="/javascript/ArrayX.js"></script>

<p><script type="text/javascript" src="/javascript/StringX.js"></script>
<script type="text/javascript" src="/javascript/DateBox.js"></script></p>

<p>Indtast en dato (valgfrit format):
<input type="text" id="datebox" value="" /></p>

<script type="text/javascript"><!--
  DateBox.register(document.getElementById('datebox'));
  // -->
</script>

<p>Bemærk, af praktiske årsager fortolkes indtastningen først når feltet forlades. Her er et par eksempler på gyldige indtastninger:</p>

<ul>
<li>i dag/i morgen/i går, evt. sammentrukket og/eller forkortet</li>
<li>6</li>
<li><span>6. jan</span></li>
<li><span>6. jan 2005</span></li>
<li>jan 6</li>
<li>næste fredag</li>
<li>sidste onsdag</li>
<li>06/01/2005</li>
<li>06/01/05</li>
<li>06/01</li>
<li>6/1</li>
<li>2005-01-06</li>
<li>05-01-06</li>
<li>01-06</li>
<li>1-6</li>
<li>pil op/pil ned retter til næste/foregående dag</li>
</ul>

<p>Skulle flere formater ønskes kan de let tilføjes. Ovenstående eksempel er genereret med følgende kode:</p>

<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-brackets">&lt;</span><span class="hl-reserved">script </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text/javascript</span><span class="hl-quotes">&quot; </span><span class="hl-var">src</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">/javascript/ArrayX.js</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;&lt;/</span><span class="hl-reserved">script</span><span class="hl-brackets">&gt;
&lt;</span><span class="hl-reserved">script </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text/javascript</span><span class="hl-quotes">&quot; </span><span class="hl-var">src</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">/javascript/StringX.js</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;&lt;/</span><span class="hl-reserved">script</span><span class="hl-brackets">&gt;
&lt;</span><span class="hl-reserved">script </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text/javascript</span><span class="hl-quotes">&quot; </span><span class="hl-var">src</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">/javascript/DateBox.js</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;&lt;/</span><span class="hl-reserved">script</span><span class="hl-brackets">&gt;</span><span class="hl-default">

Indtast en dato (valgfrit format):
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">input </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text</span><span class="hl-quotes">&quot; </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">datebox</span><span class="hl-quotes">&quot; </span><span class="hl-var">value</span><span class="hl-code">=</span><span class="hl-quotes">&quot;&quot; </span><span class="hl-brackets">/&gt;

&lt;</span><span class="hl-reserved">script </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">text/javascript</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-default">
  DateBox.register(document.getElementById('datebox'));
</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">script</span><span class="hl-brackets">&gt;</span></pre></div></div>

<p>Der er desuden krydret med følgende CSS:</p>

<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">.DateBoxControlErrorMsg
</span><span class="hl-brackets">{
  </span><span class="hl-reserved">color: </span><span class="hl-var">Red</span><span class="hl-reserved"></span><span class="hl-code">;
</span><span class="hl-brackets">}

</span><span class="hl-identifier">.DateBoxControlMsg</span><span class="hl-special">:before</span><span class="hl-default">, </span><span class="hl-identifier">.DateBoxControlErrorMsg</span><span class="hl-special">:before
</span><span class="hl-brackets">{
  </span><span class="hl-reserved">content:</span><span class="hl-code"> &quot; (&quot;</span><span class="hl-reserved"></span><span class="hl-code">;
</span><span class="hl-brackets">}

</span><span class="hl-identifier">.DateBoxControlMsg</span><span class="hl-special">:after</span><span class="hl-default">, </span><span class="hl-identifier">.DateBoxControlErrorMsg</span><span class="hl-special">:after
</span><span class="hl-brackets">{
  </span><span class="hl-reserved">content:</span><span class="hl-code"> &quot;)&quot;</span><span class="hl-reserved"></span><span class="hl-code">;
</span><span class="hl-brackets">}</span></pre></div></div>

<p>De to sidste regler har ingen effekt i Internet Explorer op til version 6.</p>

<p>Download: 
<a  href="/javascript/ArrayX.js">ArrayX.js</a>, 
<a  href="/javascript/StringX.js">StringX.js</a>, 
<a  href="/javascript/DateBox.js">DateBox.js</a>.</p>

<div class="note">
<p><strong>Opdatering:</strong> Som beskrevet i 
<a  href="/2006/06/22/scroll-hjul-events/">en nyere artikel</a> har jeg også udvidet DateBox til at håndtere op/nedtælling af datoen ved rul med hjulet på musen.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.kruse-net.dk/2006/01/06/indtastning-af-datoer/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>JavaScript Logging</title>
		<link>http://www.kruse-net.dk/2005/10/20/javascript-logging/</link>
		<comments>http://www.kruse-net.dk/2005/10/20/javascript-logging/#comments</comments>
		<pubDate>Thu, 20 Oct 2005 18:34:06 +0000</pubDate>
		<dc:creator>Jakob Kruse</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Set i verden]]></category>

		<guid isPermaLink="false">http://www.kruse-net.dk/2005/10/20/javascript-logging/</guid>
		<description><![CDATA[Enhver der helt eller delvist lever af at udvikle web sider eller applikationer har på et eller andet tidspunkt ønsket sig et mere avanceret værktøj til rådighed end alert(). Måske JavaScript Logging er løsningen? Det er da et forsøg værd!]]></description>
			<content:encoded><![CDATA[<p>Enhver der helt eller delvist lever af at udvikle web sider eller applikationer har på et eller andet tidspunkt ønsket sig et mere avanceret værktøj til rådighed end <code>alert()</code>. Måske 
<a  href="http://www.alistapart.com/articles/jslogging#fvlogger" onclick="javascript:pageTracker._trackPageview('/external/www.alistapart.com/articles/jslogging?fvlogger');" >JavaScript Logging</a> er løsningen? Det er da et forsøg værd!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kruse-net.dk/2005/10/20/javascript-logging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

