<?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>Tom&#039;s view on web development</title>
	<atom:link href="http://www.tomgreuter.nl/tech/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tomgreuter.nl/tech</link>
	<description>html5, css, javascript, editors and other bugs</description>
	<lastBuildDate>Sat, 07 Apr 2012 20:36:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>HTML5 JavaScript APIs to be used in mobile environments</title>
		<link>http://www.tomgreuter.nl/tech/2012/04/javascript-apis/</link>
		<comments>http://www.tomgreuter.nl/tech/2012/04/javascript-apis/#comments</comments>
		<pubDate>Sat, 07 Apr 2012 20:32:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[webstandaarden]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[course]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[w3c]]></category>

		<guid isPermaLink="false">http://www.tomgreuter.nl/tech/?p=147</guid>
		<description><![CDATA[At the moment I’m attending the online course Mobile Web 2: Applications at W3 Tech courses. This post is a summary of the fourth week’s subject JavaScript APIs. (Please note: this is not a thorough objective summary of the course, &#8230; <a href="http://www.tomgreuter.nl/tech/2012/04/javascript-apis/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>At the moment I’m attending the online course <a href="http://www.w3techcourses.com/course/view.php?id=10">Mobile Web 2: Applications</a> at <a href="http://www.w3techcourses.com/">W3 Tech courses</a>. This post is a summary of the fourth week’s subject <em>JavaScript APIs</em>. (Please note: this is not a thorough objective summary of the course, but just the highlights that I found important for myself to remember.)</p>
<h1>Geolocation</h1>
<p>A simple example:</p>
<pre> if (navigator.geolocation) {
          navigator.geolocation.watchPosition(
              function (pos) {
                  $("#lat").text(pos.coords.latitude);
                  $("#lng").text(pos.coords.longitude);
                  $("#alt").text(pos.coords.altitude);
                  $("#hdg").text(pos.coords.heading);
                  $("#spd").text(pos.coords.speed);
              },
              function (err) {
                  $("#status").text("ERROR: " + err.message);
              }
          )
      }</pre>
<h1><span id="more-147"></span>Device orientation</h1>
<p>The first part that needs to be understood is this cryptic <code>alpha</code>/<code>beta</code>/<code>gamma</code> system. The <code>alpha</code> component is the heading relative to North. Unfortunately it rotates in a counter-clockwise manner (which is to say that an alpha of 90 is West rather than East) so that in order to obtain a more typical heading one has to subtract <code>alpha</code> from 360 (using the West=90 example above you would then get 360 &#8211; 90 = 270°, which is the value most people would expect for a device pointing West). The <code>beta</code> component is the vertical rotation. That is to say that a device laying flat on its back with its screen pointed up will have a <code>beta</code> of 0, and if it is moved to stand vertical with the top of its screen pointing up it will read at 90. The <code>gamma</code> component is the remaining rotation axis.</p>
<h1>Touch events</h1>
<p>In order to prevent the default zooming behaviour, you can return to the meta viewport element as follows:</p>
<pre>&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/&gt;</pre>
<h1>Local Storage</h1>
<p>To persistently store data locally is the simpler alternative: Local Storage. The more complex (but more powerful) approach, IndexedDB, is a large API and at times difficult feature the details of which are still being ironed out.</p>
<p>Local Storage is a simple key-value store, in which the keys and values are strings. There is only one store per origin. This functionality is exposed through the globally available <code>localStorage</code> object.</p>
<p>If you wanted to keep a simple counter of the number of times a given user has loaded your application, you could use the following:</p>
<pre>var counter = localStorage.getItem("count") || 0;
counter++;
localStorage.setItem("count", counter);</pre>
<p>Deleting a key completely can be performed through <code>removeItem</code>, and if you wish to reset the entire store, simply call <code>localStorage.clear()</code>.</p>
<p>Local stores can also be iterated through in order to list all the content that they contain. The order is not guaranteed.</p>
<pre class="example highlight prettyprint"><span class="kwd">for</span><span class="pun">(</span><span class="kwd">var</span><span class="pln"> i </span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> localStorage</span><span class="pun">.</span><span class="pln">length</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="lit">n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pun">{</span><span class="pln">     </span><span class="kwd">var</span><span class="pln"> k </span><span class="pun">=</span><span class="pln"> localStorage</span><span class="pun">.</span><span class="pln">key</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">     console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">k </span><span class="pun">+</span><span class="str">": "</span><span class="pun">+</span><span class="pln"> localStorage</span><span class="pun">[</span><span class="pln">k</span><span class="pun">]);</span><span class="pun">}</span></pre>
<p>Note that if all you need is to store session-based data in a manner that is more powerful than cookies, you can use the sessionStorage object which works in the exact same way as localStorage but the lifetime of which is limited to a single browser session.</p>
<p>Read more: <a href="http://www.webdirections.org/blog/webstorage-persistent-client-side-data-storage/">webStorage: Persistent client side data storage</a></p>
<h1>Websockets</h1>
<p>Note that if all you need is server-push rather than a duplex conversation, then another simpler technology called Server-Sent Events can work for you.</p>
<p>Future technics</p>
<ul>
<li>System notifications</li>
<li><a href="http://davidwalsh.name/page-visibility">Page visibility</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2012/04/javascript-apis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Basics of Mobile Web Development</title>
		<link>http://www.tomgreuter.nl/tech/2012/04/basics-of-mobile-web-development/</link>
		<comments>http://www.tomgreuter.nl/tech/2012/04/basics-of-mobile-web-development/#comments</comments>
		<pubDate>Tue, 03 Apr 2012 11:00:59 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[webstandaarden]]></category>
		<category><![CDATA[course]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[summary]]></category>
		<category><![CDATA[w3c]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.tomgreuter.nl/tech/?p=129</guid>
		<description><![CDATA[At the moment I&#8217;m attending the online course Mobile Web 2: Applications at W3 Tech courses. This post is a summary of the second week&#8217;s subject Basics of Mobile Web Development. (Please note: this is not a thorough objective summary &#8230; <a href="http://www.tomgreuter.nl/tech/2012/04/basics-of-mobile-web-development/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>At the moment I&#8217;m attending the online course <a href="http://www.w3techcourses.com/course/view.php?id=10">Mobile Web 2: Applications</a> at <a href="http://www.w3techcourses.com/">W3 Tech courses</a>. This post is a summary of the second week&#8217;s subject <em>Basics of Mobile Web Development</em>. (Please note: this is not a thorough objective summary of the course, but just the highlights that I found important for myself to remember.)</p>
<ol>
<li>The way to address scaling issues on a mobile device is to use the meta viewport element.
<pre>&lt;meta name="viewport" content="width=device-width"/&gt;</pre>
<p>More info: <a href="http://dev.opera.com/articles/view/an-introduction-to-meta-viewport-and-viewport/">An introduction to meta viewport and @viewport</a> (dev.opera).</li>
<li><a href="http://www.w3.org/TR/css3-mediaqueries/">CSS Media Queries</a> is a way of applying specific CSS styles depending on a number of properties of the target device. Typical properties include whether it is rendered on <code>screen</code> or in <code>print</code>, the <code>orientation</code> of the device, its <code>resolution</code> or <code>color</code>depth, and many other such aspects (called “media features”). Examples:
<pre class="example highlight prettyprint"><span class="lit">@media</span><span class="pln"> screen </span><span class="kwd">and</span><span class="pun">(</span><span class="pln">max</span><span class="pun">-</span><span class="pln">width</span><span class="pun">:</span><span class="lit">959px</span><span class="pun">)</span><span class="pun">{</span><span class="pln">     </span><span class="com">/* CSS rules to apply specifically when the above is true */</span><span class="pun">}</span></pre>
<pre class="example highlight prettyprint"><span class="tag">&lt;link</span><span class="atn">rel</span><span class="pun">=</span><span class="atv">'stylesheet'</span><span class="atn">href</span><span class="pun">=</span><span class="atv">'style.css'</span><span class="atn">type</span><span class="pun">=</span><span class="atv">'text/css'</span><span class="atn">media</span><span class="pun">=</span><span class="atv">'all and (min-width: 960px)'</span><span class="tag">/&gt;</span></pre>
</li>
<li><span class="tag">When writing web sites that target both mobile and desktop, it is usually a better idea to write the core style sheet in a manner that works for mobile devices, and then use media queries to render the same page on larger screens, &#8220;mobile first&#8221;. This concept can be taken further by starting to design for the &#8220;dumbest&#8221; phone.<br />
</span></li>
<li><span class="tag"><span class="tag"><span class="tag"><span class="tag">How to test for native JSON:<br />
</span></span></span></span></p>
<pre>if ("JSON" in window) {
    // code that depends on native JSON being available
}</pre>
<p><span class="tag"><span class="tag"><span class="tag">Or, with a polyfill:<br />
</span></span></span></p>
<pre>&lt;script&gt;"JSON" in window || document.write('&lt;script src="json2.js"&gt;&lt;\/script&gt;')&lt;/script&gt;</pre>
<p><span class="tag"><span class="tag"><span class="tag"><br />
</span></span></span></li>
<li>In a mobile context, use opacity sparingly.</li>
<li><span class="tag"><span class="tag"><span class="tag"><a href="http://www.xuijs.com/">Xui</a> has the advantage over <a href="http://zeptojs.com/">Zepto</a> that it&#8217;s fully portable to all known browsers, while Zepto tends to be Webkit focused.<br />
</span></span></span></li>
</ol>
<p>Mentioned resources:</p>
<ul>
<li><a href="https://raw.github.com/douglascrockford/JSON-js/master/json_parse.js">JSON parser</a> (to prevend use of vulnerable eval)</li>
<li><a href="http://modernizr.com/download/">Modernizr Download Builder</a></li>
<li><a href="http://caniuse.com/">Can I use</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2012/04/basics-of-mobile-web-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>To GZIP or not to GZIP</title>
		<link>http://www.tomgreuter.nl/tech/2012/03/to-gzip-or-not-to-gzip/</link>
		<comments>http://www.tomgreuter.nl/tech/2012/03/to-gzip-or-not-to-gzip/#comments</comments>
		<pubDate>Sat, 31 Mar 2012 20:10:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[browsers]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[optimization]]></category>

		<guid isPermaLink="false">http://www.tomgreuter.nl/tech/?p=134</guid>
		<description><![CDATA[When the question to GZIP or not to GZIP is raised I&#8217;m sometimes asked if the cost (in time and battery usage) of decompressing data on the client is balanced against the gains in transport efficiency. &#8220;Yes, I assume it &#8230; <a href="http://www.tomgreuter.nl/tech/2012/03/to-gzip-or-not-to-gzip/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When the question <em>to GZIP or not to GZIP</em> is raised I&#8217;m sometimes asked if the cost (in time and battery usage) of decompressing data on the client is balanced against the gains in transport efficiency. &#8220;Yes, I assume it is, otherwise why would Yahoo <a href="http://developer.yahoo.com/performance/rules.html#gzip">propagate</a> it?&#8221;, was mostly my answer.</p>
<p>I was pleased to see that the W3C gives a more thorough answer to this question in it&#8217;s section on <a href="http://www.w3.org/TR/mwabp/#bp-conserve">Mobile Web Application Best Practices</a>:</p>
<p>Web servers should be configured to serve appropriately compressed responses. <em>However:</em></p>
<ul>
<li>Most image formats (especially JPEGs) do not benefit from compression, but SVG does;</li>
<li>Most other media formats (e.g. audio, video) do not benefit from compression;</li>
<li>Very small files (e.g. &lt;1k) generally do not benefit from compression.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2012/03/to-gzip-or-not-to-gzip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Geharnast JavaScript</title>
		<link>http://www.tomgreuter.nl/tech/2011/12/geharnast-javascript/</link>
		<comments>http://www.tomgreuter.nl/tech/2011/12/geharnast-javascript/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 20:41:17 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://tomgreuter.nl/tech/?p=92</guid>
		<description><![CDATA[Dit artikel is eerder geplaatst in de adventskalender 2011 van Fronteers. De discussie speelt zich daar af. Het belang van JavaScript op internet Het belang van JavaScript op het web is de laatste jaren enorm toegenomen. Ten eerste heeft JavaScript &#8230; <a href="http://www.tomgreuter.nl/tech/2011/12/geharnast-javascript/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>Dit artikel is eerder <a href="http://fronteers.nl/blog/2011/12/geharnast-javascript">geplaatst</a> in de <a href="http://fronteers.nl/blog/categorieen/adventskalender">adventskalender</a> 2011 van Fronteers. De discussie speelt zich <a href="http://fronteers.nl/blog/2011/12/geharnast-javascript#reactie-1971">daar</a> af.</em></p>
<h2>Het belang van JavaScript op internet</h2>
<p>Het belang van JavaScript op het web is de laatste jaren enorm toegenomen. Ten eerste heeft JavaScript deels de animatierol van Flash overgenomen, ten tweede is het web applicatiever geworden, waardoor JavaScript (bijvoorbeeld in ajax-communicatie) een grote vlucht genomen heeft. De rol JavaScript wordt groter en tegelijkertijd neemt de professionalisering toe. Het is opvallend te zien dat veel best practices uit de back-end-wereld gemeengoed aan het worden zijn bij JavaScript-development. Testen is zo&#8217;n belangrijk onderdeel.</p>
<p><span id="more-92"></span></p>
<h2>Testen</h2>
<p>Het testen van JavaScript kan op meerdere niveaus gedaan worden:</p>
<ol>
<li>Lint testen. Het testen op correcte syntax door tools als <a href="http://www.jshint.com/">JsHint</a>, <a href="http://www.jslint.com/">JsLint</a> of <a href="http://code.google.com/intl/nl/closure/utilities/">Closure Linter</a>. Dit kan deels door je editor gedaan worden.</li>
<li>Functioneel testen. Het testen van bijvoorbeeld klikscenario&#8217;s in je website of app met een tool als <a href="http://seleniumhq.org/">Selenium</a>.</li>
<li>Unittesten. Daar gaan we in dit artikel dieper op in.</li>
<li>Last but not least: handmatig testen. Idealiter stel je hiervoor schriftelijke testscripts op, zodat je gestructureerd dezelfde scenario&#8217;s kunt testen bij opeenvolgende software releases.</li>
</ol>
<p>De eerste drie soorten testtools kunnen geautomatiseerd worden, zodat je continu op de hoogte gebracht kunt worden van de staat van je applicatie.</p>
<h2>Unittesten</h2>
<p>Wikipedia zegt over <a href="http://nl.wikipedia.org/wiki/Unittesten">unittesten</a>: &#8220;Unittesten is een methode om softwaremodulen of stukjes broncode (<em>units</em>) afzonderlijk te testen. Bij unittesten zal voor iedere unit een of meerdere tests ontwikkeld worden. Hierbij worden dan verschillende testcases doorlopen. In het ideale geval zijn alle testcases onafhankelijk van andere tests.&#8221; Verschillende units samen worden getest in een integratietest.</p>
<p>Voor JavaScript zijn er diverse unittest frameworks beschikbaar. Enkele bekende zijn:</p>
<ul>
<li><a href="http://docs.jquery.com/QUnit">QUnit</a></li>
<li><a href="http://developer.yahoo.com/yui/yuitest/">YUI Test</a></li>
<li><a href="http://code.google.com/p/js-test-driver/">Js Test Driver</a></li>
<li><a href="http://pivotal.github.com/jasmine/">Jasmine</a> (voortgekomen uit JsUnit)</li>
</ul>
<p>In dit artikel kijken we verder naar unittesten met Jasmine. Jasmine kan onafhankelijk van een JavaScript-library gebruikt worden en heeft ook geen DOM nodig om zijn testen uit te voeren. Verder is Jasmine goed te automatiseren. In syntax en mogelijkheden verschilt Jasmine niet veel van andere unittesting tools.</p>
<h2>TDD &#8211; Assume your code will fail</h2>
<p>Eén stap verder nog dan systematisch testen is het testen als uitgangspunt te nemen in je software-ontwikkelproces: &#8220;Test-Driven Development&#8221; (TDD). Test-Driven Development is een ontwikkelmethode voor software waarbij eerst tests worden geschreven en daarna pas de code. De testcases worden beschreven vanuit het oogpunt van de gebruiker. Hoewel TDD (een methodiek) en Jasmine (een tool) niet per definitie een combinatie vormen, werpen we hier een korte, inleidende blik op TDD met Jasmine.</p>
<h2>Jasmine installeren</h2>
<ol>
<li>De voorbeeldcode bij dit artikel is te downloaden vanaf <a href="https://github.com/ludder/Fronteers-Jasmine-Example">github</a>.</li>
<li>Op het hoogste niveau zie je de directory&#8217;s &#8220;lib&#8221;, &#8220;spec&#8221; en &#8220;src&#8221;. &#8220;lib&#8221; bevat de core-bestanden van Jasmine, in &#8220;src&#8221; komen de JavaScriptbestanden van je project en in &#8220;spec&#8221; zitten de bestanden die de sourcecode gaan testen.</li>
<li>Open SpecRunner.html in je favoriete browser. Er worden direct enkele testen uitgevoerd. En met succes, want de SpecRunner kleurt groen.</li>
</ol>
<h2>Een eerste Jasmine unit test maken</h2>
<p>Jasmine is opgebouwd uit suites, specs en expectations. Eén JavaScript-project bestaat normaal gesproken uit meerdere Jasmine <em>testsuites</em>. Eén testsuite, die vaak een component of een class omvat, kan op zijn beurt een geneste suite of meerdere <em>specs</em> bevatten. Een spec test gerelateerde functionaliteit. In een spec kunnen één of meerdere test cases (<em>expectations</em>) gedefinieerd zijn. Met de standaard <a href="https://github.com/pivotal/jasmine/wiki/Matchers"><em>matchers</em></a> van Jasmine (functies zoals toEqual(), toBe(), toMatch(), toBeUndefined() etc.) kun je verschillende scenario&#8217;s testen.</p>
<p>Hoe schrijf je een spec? Belangrijke leidraden voor TDD zijn:</p>
<ol>
<li>Schrijf eerst je test (dus niet eerst je functionele code)</li>
<li>Zie de test falen</li>
<li>Schrijf nu de code om de test te laten slagen, op de snelst mogelijke manier, dus niet rekening houdend met eventuele aanpassingen in de code</li>
<li>Refactor (verbeter de code zonder de functionaliteit te wijzigen)</li>
<li>Herhaal deze stappen</li>
</ol>
<h2>Voorbeeld</h2>
<p>Stel dat je de Fronteers webshop beheert. Een product kan een variabele prijs hebben: De gewone bezoeker betaalt de volle mik, vaste klanten krijgen 20% korting, en Fronteersleden toucheren maar liefst 50%. Als je hier een functie voor wilt schrijven zou je dat volgens TDD met Jasmine als volgt kunnen aanpakken:</p>
<ol>
<li>Maak een suite aan (/spec/FronteersShopSpec.js) die het component FronteersShop en de nog te schrijven functie calcDiscount() gaat testen:
<pre lang="javascript">describe("FronteersShop", function() {

  var fs;
  var CLIENTTYPE_MEMBER    = 'member',
      CLIENTTYPE_FRONTEERS = 'fronteers',
      CLIENTTYPE_NONMEMBER = 'other';

  // Is executed before each spec:
  beforeEach(function() {
    fs = new FronteersShop();
  });

});</pre>
</li>
<li>De bijbehorende JavaScriptcode (/src/FronteersShop.js) ziet er dan nog als volgt uit:
<pre lang="php">function FronteersShop() {
  // a lot TODO
}</pre>
</li>
<li>Unittesten worden doorgaans opgeschreven in begrijpelijke taal, zie achtereenvolgens de beschrijving van een suite, een spec en een expectation:
<ul>
<li>describe &#8220;when the discount price is calculated&#8221;</li>
<li>it &#8220;should correctly validate function input&#8221;</li>
<li>expect(fs.calcDiscount(null)).toBeUndefined();</li>
</ul>
<p>Dit maakt enerzijds de Jasmine-code self-documenting en geeft anderszijds duidelijk aan waar in de testen fouten optreden.</li>
<li>De functie calcDiscount() willen we twee input-parameters geven</li>
<ul>
<li>price {Number} &#8211; de prijs van het product</li>
<li>customerType {String} &#8211; het soort klant: &#8216;member&#8217;, &#8216;fronteers&#8217; of &#8216;other&#8217;.</li>
</ul>
<li>In de eerste stap van onze functie calcDiscount() kijken we (in een geneste suite) of de twee input-parameters van het verwachte datatype zijn:
<pre lang="javascript">describe("FronteersShop", function() {

  var fs;

  var CLIENTTYPE_MEMBER    = 'member',
      CLIENTTYPE_FRONTEERS = 'fronteers',
      CLIENTTYPE_NONMEMBER = 'other';

  beforeEach(function() {
    fs = new FronteersShop();
  });

  describe("when the discount price is calculated", function() {

    it("should correctly validate function input", function() {
      // Wrong number of expected arguments
      expect(fs.calcDiscount(1)).toBeUndefined();
      // First argument of wrong data type
      expect(fs.calcDiscount(null, CLIENTTYPE_FRONTEERS)).toBeUndefined();
      // Second argument of wrong data type
      expect(fs.calcDiscount(100, null)).toBeUndefined();
      // Input should be accepted
      expect(fs.calcDiscount(100, CLIENTTYPE_FRONTEERS)).toBeDefined();
    });

  });

});</pre>
</li>
</ol>
<p>De testen zullen falen, want de bijbehorende code ontbreekt. Hier volgt een eerste implementatie van calcDiscount():</p>
<pre lang="javascript">FronteersShop.prototype.calcDiscount = function(price, customerType) {

	// Check if parameter "price" is correct, must be floating point number
	if (isNaN(parseFloat(price)) || (!isFinite(price)) ) {
		return;
	}
	// Check if parameter "customerType" is a String
	if (typeof customerType !== 'string') {
		return;
	}

}</pre>
<p>(Normaal gesproken wil je waarschijnlijk geen kale return doen, maar handel je de fout af. Dat valt buiten de scope van dit artikel.)</p>
<p>Tenslotte moet calcDiscount() doen waarvoor het in het leven geroepen is, de juiste prijs teruggeven, al dan niet met korting. Eerst schrijven we de spec:</p>
<pre lang="javascript">describe("FronteersShop", function() {

   // ...

  describe("when the discount price is calculated", function() {

    // ....

    it("should correctly calculate discount", function() {
      // Expect 50% of 100 =&gt; 50
      expect(fs.calcDiscount(100, CLIENTTYPE_FRONTEERS)).toEqual(50);
      // Expect 80% of 100 =&gt; 80
      expect(fs.calcDiscount(100, CLIENTTYPE_MEMBER)).toEqual(80);
      // Expect 100% of 100 =&gt; 100
      expect(fs.calcDiscount(100, CLIENTTYPE_NONMEMBER)).toEqual(100);
      // Check decimals, expect 50% of 17.1 =&gt; 8.55
      expect(fs.calcDiscount(17.1, CLIENTTYPE_FRONTEERS)).toEqual(8.55);
    });

  });

});</pre>
<p>Met vallen en opstaan kunnen we dan de bijbehorende JavaScript afleveren:</p>
<pre lang="javascript">FronteersShop.prototype.calcDiscount = function(price, customerType) {

	// ...

	if (customerType === 'member') {
		return price * 0.8;
	} else if (customerType === 'fronteers') {
		return price * 0.5;
	} else {
		return price;
	}
};</pre>
<p>Dit is natuurlijk een simpel voorbeeld. Hoe complexer je code, hoe meer de waarde van unittesten toeneemt.</p>
<h2>Wat verder?</h2>
<p>Om verder up-speed te komen met Jasmine kan het <a href="http://net.tutsplus.com/tutorials/javascript-ajax/testing-your-javascript-with-jasmine/">inleidende artikel op Nettuts</a> erg nuttig zijn. De <a href="https://github.com/pivotal/jasmine/wiki/Asynchronous-specs">Jasmine-wiki</a> biedt alle noodzakelijke informatie. Er zijn veel plugins voor Jasmine beschikbaar, bijvoorbeeld om Jasmine in je IDE te integreren (<a href="https://github.com/ibolmo/jasmine-jstd-adapter">JsTestDriver</a>) of om met zogeheten fixtures de interactie met de DOM te testen (zie de <a href="https://github.com/velesin/jasmine-jquery">Jasmine jQuery-plugin</a>). Het is ook mogelijk om Jasminetesten automatisch uit te voeren in <a href="http://maven.apache.org/">Maven</a> en hen zo een onderdeel te maken van de <a href="http://en.wikipedia.org/wiki/Continuous_integration">Continuous Integration</a>.</p>
<p>Mocht je offline zijn dan heb je wellicht iets aan het verhelderende boek van Christian Johansen <a href="http://tddjs.com/">Test-Driven JavaScript Development</a>.</p>
<h2>Tot slot</h2>
<p>Wanneer moet je nu alles uit de kast halen met unittesten? Als je een JavaScript-library, plugins of herbruikbare componenten schrijft, zijn unittesten een must. Maar ook in langlopende projecten met een snelle release cycle zijn unittesten onmisbaar om mogelijke regressiebugs af te vangen. Zelfs als je korte toevoeging schrijft voor een kleine website kunnen unittesten erg nuttig blijken. Ze laten je anders tegen je code aankijken, waardoor je code robuuster, leesbaarder en makkelijker overdraagbaar wordt. Ook voor front-enders belangrijke waarden.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2011/12/geharnast-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSS code insight in Eclipse or Aptana</title>
		<link>http://www.tomgreuter.nl/tech/2011/10/css-code-insight-in-eclipse-or-aptana/</link>
		<comments>http://www.tomgreuter.nl/tech/2011/10/css-code-insight-in-eclipse-or-aptana/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 12:42:32 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Editors]]></category>
		<category><![CDATA[Settings]]></category>
		<category><![CDATA[aptana]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[insight]]></category>

		<guid isPermaLink="false">http://tomgreuter.nl/tech/?p=76</guid>
		<description><![CDATA[Lately I changed my editor from Aptana to Eclipse with the Aptana plugin. Suddenly my CSS code insight did not work any longer. With these steps I could get it working again: Goto Window / Preferences Type filter text &#8220;assoc&#8221; &#8230; <a href="http://www.tomgreuter.nl/tech/2011/10/css-code-insight-in-eclipse-or-aptana/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Lately I changed my editor from Aptana to Eclipse with the Aptana plugin. Suddenly my CSS code insight did not work any longer. With these steps I could get it working again:</p>
<ol>
<li>Goto Window / Preferences</li>
<li>Type filter text &#8220;assoc&#8221;</li>
<li>At &#8220;General &#8211; Editors &#8211; File Associations&#8221; select &#8220;*.css&#8221;</li>
<li>Verify that the &#8220;CSS Source editor&#8221; is the default editor. If not select it and restart Eclipse.</li>
<li>If that still does not give you CSS code insight, check the following:</li>
<li>Goto the Project Explorer and right click on your project.</li>
<li>Select &#8220;Properties&#8221; and then &#8220;Project Natures&#8221;.</li>
<li>Select project nature &#8220;Web&#8221; and set it to primary. Eclipse should restart and refresh your project.</li>
<li>Now you should have CSS code insight. If not, throw your computer out of the window. Btw, that does not necessarily give you code insight.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2011/10/css-code-insight-in-eclipse-or-aptana/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Run Selenium IDE tests with jQuery selectors</title>
		<link>http://www.tomgreuter.nl/tech/2010/12/run-selenium-ide-tests-with-jquery-selectors/</link>
		<comments>http://www.tomgreuter.nl/tech/2010/12/run-selenium-ide-tests-with-jquery-selectors/#comments</comments>
		<pubDate>Mon, 20 Dec 2010 16:38:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[validatie]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[selector]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[sizzle]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://cssgreut.wordpress.com/?p=74</guid>
		<description><![CDATA[This took me a lot of time to find out, so here is a short and handy overview for everyone that wants to use jQuery selectors instead of Xpath selectors in their Selenium IDE tests. First the steps to achieve &#8230; <a href="http://www.tomgreuter.nl/tech/2010/12/run-selenium-ide-tests-with-jquery-selectors/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This took me a lot of time to find out, so here is a short and handy overview for everyone that wants to use jQuery selectors instead of Xpath selectors in their Selenium IDE tests. First the steps to achieve this, followed by some comments for the few readers that are still interested.</p>
<h2>Add jQuery selectors to Selenium</h2>
<ol>
<li>The selector engine of jQuery is called Sizzle. Download it from <a href="http://sizzlejs.com/">sizzlejs.com</a> and store the file sizzle.js in your Selenium project. (I used the current version, 1.0.)</li>
<li>Create a blank JavaScript file, rename it to &#8220;user-extensions.js&#8221; and save it to your Selenium project.</li>
<li>Add the following code to &#8220;user-extensions.js&#8221;:<br />
<code>PageBot.prototype.locateElementBySizzle = function(locator, inDocument) {<br />
var results = [];<br />
window.Sizzle(locator, inDocument, results);<br />
return results.length &gt; 0 ? results[0] : null;<br />
}</code></li>
<li>Open Selenium IDE from Firefox.</li>
<li>Go to Options &gt; Options &gt; General.</li>
<li>Click the &#8220;Browse &#8230;&#8221;-button of &#8220;Selenium Core extensions (user-extensions.js)&#8221;</li>
<li>Multiple select &#8220;sizzle.js&#8221; and &#8220;user-selections.js&#8221;. They should be added comma-seperated to the input field (for example: &#8220;<code>D:myProjectuser-extensions.js, D:myProjectsizzle.js</code>&#8220;).</li>
<li>Restart Selenium IDE.</li>
<li>Execute the following test:</li>
</ol>
<p>Command:<code> verifyElementPresent</code><br />
Target: <code>sizzle=body</code><br />
Value: <code>true</code></p>
<p>This test should succeed on every normal HTML page. ;)</p>
<h2>Comments</h2>
<ul>
<li>Why use Sizzle and not the complete  jQuery library? The same setup can also be used for jQuery, but I could not get it working. Some say that recent versions of jQuery (I use 1.4.4) don&#8217;t cope with Selenium, at the moment.</li>
<li>It&#8217;s still possible though to use jQuery functionality in your tests. If jQuery is available on the page you are testing, one could do a test similar to:</li>
</ul>
<p>Command:<code>assertEval </code><br />
Target: <code>selenium.browserbot.getUserWindow().jQuery("body").length</code><br />
Value: <code>1</code></p>
<p>&nbsp;</p>
<h2>Helpful resources</h2>
<ul>
<li><a href="http://germanrumm.eu/how-to-add-jquery-sizzle-selectors-to-selenium/">How to add jQuery (Sizzle) selectors to Selenium</a></li>
<li><a href="http://sizzlejs.com/">Sizzle</a></li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2010/12/run-selenium-ide-tests-with-jquery-selectors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Set text file encoding to UTF-8 in Aptana</title>
		<link>http://www.tomgreuter.nl/tech/2010/02/set-text-file-encoding-to-utf-8-in-aptana/</link>
		<comments>http://www.tomgreuter.nl/tech/2010/02/set-text-file-encoding-to-utf-8-in-aptana/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 12:48:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Editors]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Settings]]></category>
		<category><![CDATA[aptana]]></category>
		<category><![CDATA[utf-8]]></category>

		<guid isPermaLink="false">http://cssgreut.wordpress.com/?p=67</guid>
		<description><![CDATA[Working in a web environment, it&#8217;s important to keep your character encoding clear. Serious websites set their character encoding to UTF-8 to be sure to be compatible with different language sets. Obviously the same accounts for the database. Sometimes it&#8217;s &#8230; <a href="http://www.tomgreuter.nl/tech/2010/02/set-text-file-encoding-to-utf-8-in-aptana/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Working in a web environment, it&#8217;s important to keep your character encoding clear. Serious websites set their character encoding to UTF-8 to be sure to be compatible with different language sets. Obviously the same accounts for the database.</p>
<p>Sometimes it&#8217;s also important to set the text file encoding of your script file (php etc.). In <a href="http://www.aptana.com">Aptana</a> 2 the global text file encoding is set to Cp1252. You can change this to UTF-8 the following way:</p>
<ul>
<li>In Aptana go to Window -&gt; Preferences</li>
<li>Type &#8220;encoding&#8221; in the search box.</li>
<li>Go to General -&gt; Workspace</li>
<li>Change the text file encoding to UTF-8 and apply.</li>
</ul>
<p>In my case Aptana hung with the build settings so I had to uncheck them all:</p>
<p><a href="http://cssgreut.files.wordpress.com/2010/02/aptana.png"><img class="alignnone size-full wp-image-68" title="Aptana settings screen" src="http://cssgreut.files.wordpress.com/2010/02/aptana.png" alt="" width="480" height="442" /></a></p>
<p>Happy UTF-8 programming!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2010/02/set-text-file-encoding-to-utf-8-in-aptana/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CSS and ellipsis: Cross-browser practices</title>
		<link>http://www.tomgreuter.nl/tech/2009/09/css-and-ellipsis-cross-browser-practices/</link>
		<comments>http://www.tomgreuter.nl/tech/2009/09/css-and-ellipsis-cross-browser-practices/#comments</comments>
		<pubDate>Mon, 28 Sep 2009 20:25:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://cssgreut.wordpress.com/?p=50</guid>
		<description><![CDATA[Every now and then, say twice a year, I run into the same problem: what is the best cross-browser ellipsis solution? Because I end up searching the internet everytime, I decided the write down my prefererred solution. The problem is &#8230; <a href="http://www.tomgreuter.nl/tech/2009/09/css-and-ellipsis-cross-browser-practices/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Every now and then, say twice a year, I run into the same problem: what is the best cross-browser ellipsis solution? Because I end up searching the internet everytime, I decided the write down my prefererred solution.</p>
<p>The problem is as follows: You have a long sentence and you want to show only the first line and end up with &#8230; (the ellipsis) and trunk the rest of the sentence. Of course you can implement a server side solution, but today I prefer a client-side one.</p>
<p>IE6 and IE7 are simple, they support the CSS-property<strong> text-overflow</strong>, as do the Webkit based browsers Safari and Chrome. Text-overflow is part of the coming <a href="http://www.css3.info/preview/text-overflow/">CSS3-recommendation</a>, by the way. Because the property is not standardized yet Opera has it&#8217;s own implementation <strong>-o-text-overflow</strong>, while IE8 in standards mode supports <strong>-ms-text-overflow</strong>.</p>
<p>The only hickup we encouter with Firefox. The current version (Firefox 3.5) still does not support this property&#8230; This leaves us for several workarounds:</p>
<ul>
<li>Do nothing. All browsers will show an ellipsis, Firefox just shows nothing. My prefered solution, because it involves less time and effort.</li>
<li>Create a Firefox-only selector in your CSS. This can be handy is you have something like <a href="http://www.cyscape.com/" target="_blank">Browserhawk</a> installed on your server. Is not 100% waterproof though. Don&#8217;t just add the <a href="http://www.jide.fr/emulate-text-overflowellipsis-in-firefox-with-css">sometimes suggested</a> &#8220;:after-content&#8221; option. (With something like myclass:after { content: &#8220;&#8230;&#8221; } we could easy add ellipsis to Firefox, but other modern browsers would render the ellipsis twice.</li>
<li>Use the &#8220;:after-content&#8221; setting for all modern browsers and show the ellipsis in IE6 and IE7 with conditional comments.</li>
<li>Use a JavaScript solution. Check for example <a href="http://devongovett.wordpress.com/2009/04/06/text-overflow-ellipsis-for-firefox-via-jquery/">this nice jQuery plugin</a>.</li>
<li>Use <a href="http://mattsnider.com/css/css-string-truncation-with-ellipsis/">XUL</a>.</li>
</ul>
<p>The CSS at last:</p>
<pre><span style="color:#0000ff;">.ellipsis {
  display: block;
  white-space: nowrap;
  text-overflow: ellipsis;
  -o-text-overflow: ellipsis;
  -ms-text-overflow: ellipsis;
  width: 230px;
  overflow: hidden;
}</span></pre>
<p><em>Bonus:</em></p>
<p>Toggle the ellipsis view with jQuery:</p>
<pre>$(".ellipsis").click( function() { $(this).toggleClass(".ellipsis") });</pre>
<p><em>Disclaimer:</em></p>
<p>Not all options are tested. Please comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2009/09/css-and-ellipsis-cross-browser-practices/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>IIS7 configuren voor Windows Vista Home Premium (NL)</title>
		<link>http://www.tomgreuter.nl/tech/2007/07/iis7-configuren-voor-windows-vista-home-premium-nl/</link>
		<comments>http://www.tomgreuter.nl/tech/2007/07/iis7-configuren-voor-windows-vista-home-premium-nl/#comments</comments>
		<pubDate>Thu, 12 Jul 2007 20:19:21 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[classic asp]]></category>
		<category><![CDATA[iis]]></category>
		<category><![CDATA[windows vista]]></category>

		<guid isPermaLink="false">http://cssgreut.wordpress.com/2007/07/12/iis7-configuren-voor-windows-vista-home-premium-nl/</guid>
		<description><![CDATA[Daar ging mijn halve avond in rook op: ik wilde even mijn oude ASP-site draaiend krijgen op mijn localhost op Windows Vista&#8230; Met Windows Vista wordt IIS7 meegeleverd. Deze staat standaard (natuurlijk) niet aan. IIS aanzetten gaat via het Configuratiescherm &#8230; <a href="http://www.tomgreuter.nl/tech/2007/07/iis7-configuren-voor-windows-vista-home-premium-nl/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Daar ging mijn halve avond in rook op: ik wilde even mijn oude ASP-site draaiend krijgen op mijn localhost op Windows Vista&#8230;</p>
<ol>
<li>Met Windows Vista wordt IIS7 meegeleverd. Deze staat standaard (natuurlijk) niet aan. IIS aanzetten gaat via het Configuratiescherm &gt; Programma&#8217;s &gt; Windows-onderdelen in- of uitschakelen (administrator-rechten vereist).</li>
<li>Simpel <em>Internet Information Services</em> aanklikken is niet voldoende. Je moet ook kiezen voor World Wide Web-services &gt; Toepassingsontwikkelingsfuncties &gt; ASP.</li>
<li>Je zou nu een ASP-site moeten kunnen draaien op http://localhost.</li>
</ol>
<p>Iedereen &#8211; behalve de Goden op de Olympus &#8211; maakt wel eens fouten in hun software. Om gedetailleerde foutmeldingen te tonen moet je de halve wereld omdraaien, maar de volgende handelingen zouden ook kunnen helpen:</p>
<ol>
<li>Je kunt de IIS-manager (IIS-beheer geheten in het Nederlands) openen door in Vista te zoeken op &#8220;iis&#8221;.</li>
<li>Selecteer de default website (of een andere als het daar om gaat&#8230;).</li>
<li>Dubbelklik op het icoon <em>Foutpagina&#8217;s</em>. Klik op de actie <em>Functie-instellingen bewerken&#8230;</em></li>
<li>Selecteer een van de opties voor gedetailleerde foutmeldingen.</li>
<li>Nu kreeg ik direct de weinig verhelderende foutmelding &#8220;<em>An error occurred on the server when processing the URL. Please contact the system administrator</em>&#8221; voor de kiezen.</li>
<li>Nu kun je a) in je logfiles gaan neuzen (die standaard op onzichtbaar staan in de Verkenner, dus die moet je eerst tweaken).</li>
<li>Fijner is het natuurlijk om de exacte foutmelding in je browser te zien. Daartoe moet je een command box openen (als administrator!!) en de volgende regel uitvoeren &#8220;<strong>%windir%system32inetsrvappcmd.exe set config -section:asp /scriptErrorSentToBrowser:true</strong>&#8220;. (Zie de <a href="http://forums.iis.net/p/1095571/1693847.aspx#1693847">comments op IIS.net</a>)</li>
</ol>
<p>Happy debugging!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2007/07/iis7-configuren-voor-windows-vista-home-premium-nl/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Bij de ING geen Firefox</title>
		<link>http://www.tomgreuter.nl/tech/2007/06/bij-de-ing-geen-firefox/</link>
		<comments>http://www.tomgreuter.nl/tech/2007/06/bij-de-ing-geen-firefox/#comments</comments>
		<pubDate>Fri, 22 Jun 2007 19:34:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://cssgreut.wordpress.com/2007/06/22/bij-de-ing-geen-firefox/</guid>
		<description><![CDATA[Je kunt je natuurlijk afvragen wat ik op de banensite van de ING doe, maar deze foutmelding &#8211; die mij nota bene verhindert bij de vacaturedetails te komen &#8211; wilde ik jullie toch niet onthouden: https://careers.ing.com/]]></description>
			<content:encoded><![CDATA[<p>Je kunt je natuurlijk afvragen wat ik op de banensite van de ING doe, maar deze foutmelding &#8211; die mij nota bene verhindert bij de vacaturedetails te komen &#8211; wilde ik jullie toch niet onthouden:</p>
<p><a href="http://www.flickr.com/photos/tomgreuter/591813931/" title="Photo Sharing"><img src="http://farm2.static.flickr.com/1233/591813931_9f58fc8cf2_m.jpg" alt="Foutmeldinkie" height="139" width="240" /></a></p>
<p><a href="https://careers.ing.com/">https://careers.ing.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tomgreuter.nl/tech/2007/06/bij-de-ing-geen-firefox/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

